From 340f06c9eaee097e626c251bf7a013350649c091 Mon Sep 17 00:00:00 2001 From: Junfeng Dong Date: Tue, 19 Nov 2013 17:45:23 +0800 Subject: Import upstream 1.6.0. Change-Id: Icf52b556470cac8677297f2ef14ded16684f7887 Signed-off-by: Junfeng Dong --- roms/Makefile | 49 + roms/SLOF/.gitignore | 10 +- roms/SLOF/board-js2x/llfw/u4mem.c | 6 +- roms/SLOF/board-js2x/slof/OF.fs | 2 +- roms/SLOF/board-js2x/slof/ht.fs | 2 +- roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs | 4 +- roms/SLOF/board-qemu/config | 2 +- roms/SLOF/board-qemu/include/southbridge.h | 1 - roms/SLOF/board-qemu/llfw/Makefile | 2 +- roms/SLOF/board-qemu/slof/.gitignore | 1 + roms/SLOF/board-qemu/slof/Makefile | 1 + roms/SLOF/board-qemu/slof/qemu-bootlist.fs | 14 +- roms/SLOF/board-qemu/slof/rtas-nvram.fs | 48 + roms/SLOF/board-qemu/slof/tree.fs | 3 + roms/SLOF/board-qemu/slof/vio-vscsi.fs | 28 +- roms/SLOF/board-qemu/virtio-net/vn-pci.c | 2 +- roms/SLOF/clients/.gitignore | 3 + roms/SLOF/clients/net-snk/app/biosemu/biosemu.c | 2 +- roms/SLOF/clients/net-snk/app/biosemu/io.c | 12 +- roms/SLOF/clients/net-snk/app/biosemu/mem.c | 12 +- roms/SLOF/clients/net-snk/app/biosemu/vbe.c | 2 +- roms/SLOF/clients/net-snk/app/netapps/args.c | 12 +- roms/SLOF/clients/net-snk/app/netapps/netboot.c | 6 +- roms/SLOF/clients/net-snk/app/netlib/dhcp.c | 12 +- roms/SLOF/clients/net-snk/app/netlib/dns.c | 8 +- roms/SLOF/clients/net-snk/app/netlib/ipv4.c | 6 +- roms/SLOF/clients/net-snk/app/netlib/tftp.c | 2 +- roms/SLOF/clients/net-snk/kernel/modules.c | 2 +- roms/SLOF/clients/net-snk/kernel/systemcall.c | 2 +- roms/SLOF/clients/net-snk/kernel/timer.c | 4 +- roms/SLOF/drivers/bcm57xx/bcm57xx.c | 2 +- roms/SLOF/drivers/bcm57xx/bcm57xx.h | 4 +- roms/SLOF/drivers/e1k/e1k.c | 2 +- roms/SLOF/include/byteorder.h | 2 +- roms/SLOF/lib/libbases/libbases.code | 2 +- roms/SLOF/lib/libbootmsg/bootmsg_lvl.S | 5 +- roms/SLOF/lib/libelf/elf.c | 2 +- roms/SLOF/lib/libhvcall/libhvcall.h | 14 + roms/SLOF/lib/libnvram/libnvram.code | 10 +- roms/SLOF/lib/libnvram/libnvram.in | 1 + roms/SLOF/lib/libnvram/nvram.c | 88 +- roms/SLOF/lib/libnvram/nvram.h | 3 + roms/SLOF/llfw/nvramlog.S | 7 +- roms/SLOF/romfs/tools/.gitignore | 1 + roms/SLOF/romfs/tools/build_ffs.c | 2 +- roms/SLOF/romfs/tools/create_crc.c | 2 +- roms/SLOF/slof/fs/base.fs | 4 +- roms/SLOF/slof/fs/debug.fs | 4 +- roms/SLOF/slof/fs/devices/pci-device_10de_0141.fs | 2 +- roms/SLOF/slof/fs/dictionary.fs | 2 +- roms/SLOF/slof/fs/envvar.fs | 2 +- roms/SLOF/slof/fs/exception.fs | 4 +- roms/SLOF/slof/fs/fcode/1275.fs | 2 +- roms/SLOF/slof/fs/ide.fs | 4 +- roms/SLOF/slof/fs/logging.fs | 6 +- roms/SLOF/slof/fs/node.fs | 2 +- roms/SLOF/slof/fs/packages/disk-label.fs | 2 +- roms/SLOF/slof/fs/property.fs | 2 +- roms/SLOF/slof/fs/scsi-loader.fs | 2 +- roms/SLOF/slof/fs/scsi-support.fs | 6 +- roms/SLOF/slof/fs/usb/usb-ohci.fs | 8 +- roms/SLOF/slof/fs/usb/usb-storage-support.fs | 2 +- roms/SLOF/slof/fs/usb/usb-storage.fs | 4 +- roms/SLOF/slof/fs/usb/usb-support.fs | 4 +- roms/SLOF/tools/.gitignore | 1 + roms/SLOF/tools/gen_reloc_table.c | 2 +- roms/config.ipxe.general.h | 2 + roms/ipxe/contrib/rom-o-matic/bottom.php | 18 +- roms/ipxe/contrib/rom-o-matic/build.php | 9 +- roms/ipxe/contrib/rom-o-matic/customize-flags.php | 18 +- roms/ipxe/contrib/rom-o-matic/directions.php | 12 +- roms/ipxe/contrib/rom-o-matic/flag-table.php | 32 + roms/ipxe/contrib/rom-o-matic/index.php | 6 +- roms/ipxe/contrib/rom-o-matic/top.php | 12 +- roms/ipxe/contrib/rom-o-matic/utils.php | 5 +- roms/ipxe/contrib/vm/bochsrc.txt | 720 +- roms/ipxe/src/Makefile | 21 +- roms/ipxe/src/Makefile.housekeeping | 226 +- roms/ipxe/src/arch/i386/Makefile | 10 +- roms/ipxe/src/arch/i386/Makefile.pcbios | 1 + roms/ipxe/src/arch/i386/core/aout_loader.c | 144 - roms/ipxe/src/arch/i386/core/basemem_packet.c | 3 +- roms/ipxe/src/arch/i386/core/cmdline.c | 113 - roms/ipxe/src/arch/i386/core/cpu.c | 73 - roms/ipxe/src/arch/i386/core/freebsd_loader.c | 377 - roms/ipxe/src/arch/i386/core/gdbmach.c | 3 +- roms/ipxe/src/arch/i386/core/linux/linuxprefix.S | 28 + roms/ipxe/src/arch/i386/core/pic8259.c | 3 +- roms/ipxe/src/arch/i386/core/rdtsc_timer.c | 3 +- roms/ipxe/src/arch/i386/core/relocate.c | 25 +- roms/ipxe/src/arch/i386/core/runtime.c | 265 + roms/ipxe/src/arch/i386/core/video_subr.c | 9 + roms/ipxe/src/arch/i386/core/wince_loader.c | 273 - roms/ipxe/src/arch/i386/core/x86_io.c | 96 - roms/ipxe/src/arch/i386/drivers/net/undi.c | 5 +- roms/ipxe/src/arch/i386/drivers/net/undiload.c | 3 +- roms/ipxe/src/arch/i386/drivers/net/undinet.c | 119 +- roms/ipxe/src/arch/i386/drivers/net/undionly.c | 15 +- roms/ipxe/src/arch/i386/drivers/net/undipreload.c | 3 +- roms/ipxe/src/arch/i386/drivers/net/undirom.c | 3 +- roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c | 3 +- .../src/arch/i386/firmware/pcbios/bios_console.c | 21 +- .../src/arch/i386/firmware/pcbios/e820mangler.S | 3 +- roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c | 3 +- roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c | 3 +- roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c | 3 +- roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c | 3 +- roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c | 3 +- roms/ipxe/src/arch/i386/hci/commands/reboot_cmd.c | 3 +- roms/ipxe/src/arch/i386/image/bootsector.c | 18 +- roms/ipxe/src/arch/i386/image/bzimage.c | 257 +- roms/ipxe/src/arch/i386/image/com32.c | 3 +- roms/ipxe/src/arch/i386/image/comboot.c | 5 +- roms/ipxe/src/arch/i386/image/elfboot.c | 6 +- roms/ipxe/src/arch/i386/image/initrd.c | 300 + roms/ipxe/src/arch/i386/image/multiboot.c | 155 +- roms/ipxe/src/arch/i386/image/nbi.c | 11 +- roms/ipxe/src/arch/i386/image/pxe_image.c | 19 +- roms/ipxe/src/arch/i386/image/sdi.c | 136 + roms/ipxe/src/arch/i386/include/bios.h | 1 + roms/ipxe/src/arch/i386/include/bits/byteswap.h | 91 +- roms/ipxe/src/arch/i386/include/bits/cpu.h | 86 - roms/ipxe/src/arch/i386/include/bits/entropy.h | 14 + roms/ipxe/src/arch/i386/include/bits/errfile.h | 42 - roms/ipxe/src/arch/i386/include/bits/io.h | 14 - roms/ipxe/src/arch/i386/include/bits/time.h | 14 + .../src/arch/i386/include/efi/ipxe/dhcp_arch.h | 3 +- roms/ipxe/src/arch/i386/include/initrd.h | 29 + roms/ipxe/src/arch/i386/include/int13.h | 186 +- .../ipxe/src/arch/i386/include/ipxe/bios_sanboot.h | 11 + roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h | 68 + roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h | 62 + roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h | 18 + roms/ipxe/src/arch/i386/include/ipxe/vmware.h | 81 + roms/ipxe/src/arch/i386/include/ipxe/x86_io.h | 153 - roms/ipxe/src/arch/i386/include/librm.h | 6 + .../src/arch/i386/include/pcbios/ipxe/dhcp_arch.h | 3 +- roms/ipxe/src/arch/i386/include/pic8259.h | 2 + roms/ipxe/src/arch/i386/include/pxe.h | 50 +- roms/ipxe/src/arch/i386/include/pxe_api.h | 148 +- roms/ipxe/src/arch/i386/include/rtc.h | 83 + roms/ipxe/src/arch/i386/include/sdi.h | 39 + .../src/arch/i386/interface/pcbios/bios_smbios.c | 3 +- .../src/arch/i386/interface/pcbios/bios_timer.c | 3 +- roms/ipxe/src/arch/i386/interface/pcbios/int13.c | 771 ++- .../arch/i386/interface/pcbios/memtop_umalloc.c | 88 +- roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c | 3 +- .../src/arch/i386/interface/pcbios/rtc_entropy.c | 199 + .../ipxe/src/arch/i386/interface/pcbios/rtc_time.c | 138 + roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c | 317 +- roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S | 3 +- .../src/arch/i386/interface/pxe/pxe_exit_hook.c | 61 + roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c | 142 +- roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c | 3 +- .../ipxe/src/arch/i386/interface/pxe/pxe_preboot.c | 117 +- roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c | 27 +- roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c | 25 +- roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c | 514 +- .../src/arch/i386/interface/pxeparent/pxeparent.c | 3 +- .../arch/i386/interface/pxeparent/pxeparent_dhcp.c | 3 +- .../src/arch/i386/interface/syslinux/com32_call.c | 3 +- .../arch/i386/interface/syslinux/com32_wrapper.S | 3 +- .../arch/i386/interface/syslinux/comboot_call.c | 27 +- .../src/arch/i386/interface/vmware/guestinfo.c | 282 + .../ipxe/src/arch/i386/interface/vmware/guestrpc.c | 328 + .../src/arch/i386/interface/vmware/vmconsole.c | 134 + roms/ipxe/src/arch/i386/interface/vmware/vmware.c | 58 + roms/ipxe/src/arch/i386/prefix/exeprefix.S | 5 +- roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S | 19 + roms/ipxe/src/arch/i386/prefix/libprefix.S | 74 +- roms/ipxe/src/arch/i386/prefix/linuxprefix.S | 28 - roms/ipxe/src/arch/i386/prefix/lkrnprefix.S | 54 +- roms/ipxe/src/arch/i386/prefix/mromprefix.S | 118 +- roms/ipxe/src/arch/i386/prefix/pxeprefix.S | 72 +- roms/ipxe/src/arch/i386/prefix/romprefix.S | 127 +- roms/ipxe/src/arch/i386/prefix/undiloader.S | 4 +- roms/ipxe/src/arch/i386/scripts/i386.lds | 51 +- roms/ipxe/src/arch/i386/transitions/liba20.S | 12 +- roms/ipxe/src/arch/i386/transitions/librm.S | 28 +- roms/ipxe/src/arch/x86/Makefile | 1 + roms/ipxe/src/arch/x86/core/cpuid.c | 155 + roms/ipxe/src/arch/x86/core/debugcon.c | 86 + roms/ipxe/src/arch/x86/core/pcidirect.c | 3 +- roms/ipxe/src/arch/x86/core/x86_bigint.c | 91 + roms/ipxe/src/arch/x86/core/x86_io.c | 102 + roms/ipxe/src/arch/x86/core/x86_string.c | 161 +- roms/ipxe/src/arch/x86/core/x86_tcpip.c | 169 + roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c | 98 + roms/ipxe/src/arch/x86/include/bits/bigint.h | 318 + roms/ipxe/src/arch/x86/include/bits/errfile.h | 50 + roms/ipxe/src/arch/x86/include/bits/io.h | 14 + roms/ipxe/src/arch/x86/include/bits/string.h | 214 +- roms/ipxe/src/arch/x86/include/bits/tcpip.h | 17 + roms/ipxe/src/arch/x86/include/ipxe/cpuid.h | 53 + roms/ipxe/src/arch/x86/include/ipxe/x86_io.h | 159 + roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c | 3 +- roms/ipxe/src/arch/x86/prefix/efidrvprefix.c | 3 +- roms/ipxe/src/arch/x86/prefix/efiprefix.c | 3 +- roms/ipxe/src/arch/x86_64/Makefile | 12 + roms/ipxe/src/arch/x86_64/core/linux/linuxprefix.S | 25 + roms/ipxe/src/arch/x86_64/include/bits/byteswap.h | 25 + roms/ipxe/src/arch/x86_64/include/bits/entropy.h | 12 + roms/ipxe/src/arch/x86_64/include/bits/errfile.h | 11 - roms/ipxe/src/arch/x86_64/include/bits/io.h | 10 - roms/ipxe/src/arch/x86_64/include/bits/time.h | 12 + .../src/arch/x86_64/include/efi/ipxe/dhcp_arch.h | 5 +- roms/ipxe/src/arch/x86_64/prefix/linuxprefix.S | 25 - roms/ipxe/src/config/colour.h | 32 + roms/ipxe/src/config/config.c | 47 +- roms/ipxe/src/config/console.h | 6 +- roms/ipxe/src/config/defaults/efi.h | 4 +- roms/ipxe/src/config/defaults/linux.h | 2 + roms/ipxe/src/config/defaults/pcbios.h | 6 +- roms/ipxe/src/config/entropy.h | 16 + roms/ipxe/src/config/general.h | 27 +- roms/ipxe/src/config/sideband.h | 3 + roms/ipxe/src/config/time.h | 16 + roms/ipxe/src/core/acpi.c | 3 +- roms/ipxe/src/core/ansiesc.c | 3 +- roms/ipxe/src/core/assert.c | 31 + roms/ipxe/src/core/base16.c | 3 +- roms/ipxe/src/core/base64.c | 12 +- roms/ipxe/src/core/basename.c | 3 +- roms/ipxe/src/core/bitmap.c | 3 +- roms/ipxe/src/core/blockdev.c | 3 +- roms/ipxe/src/core/btext.c | 5039 -------------- roms/ipxe/src/core/console.c | 7 +- roms/ipxe/src/core/cpio.c | 3 +- roms/ipxe/src/core/ctype.c | 3 +- roms/ipxe/src/core/cwuri.c | 3 +- roms/ipxe/src/core/debug.c | 56 +- roms/ipxe/src/core/debug_md5.c | 3 +- roms/ipxe/src/core/device.c | 3 +- roms/ipxe/src/core/downloader.c | 17 +- roms/ipxe/src/core/edd.c | 3 +- roms/ipxe/src/core/exec.c | 125 +- roms/ipxe/src/core/fnrec.c | 3 +- roms/ipxe/src/core/gdbserial.c | 3 +- roms/ipxe/src/core/gdbstub.c | 3 +- roms/ipxe/src/core/gdbudp.c | 3 +- roms/ipxe/src/core/getkey.c | 5 +- roms/ipxe/src/core/getopt.c | 8 +- roms/ipxe/src/core/hw.c | 23 +- roms/ipxe/src/core/image.c | 167 +- roms/ipxe/src/core/init.c | 3 +- roms/ipxe/src/core/interface.c | 3 +- roms/ipxe/src/core/iobuf.c | 154 +- roms/ipxe/src/core/job.c | 3 +- roms/ipxe/src/core/linebuf.c | 3 +- roms/ipxe/src/core/lineconsole.c | 67 + roms/ipxe/src/core/list.c | 84 + roms/ipxe/src/core/log.c | 63 + roms/ipxe/src/core/main.c | 9 +- roms/ipxe/src/core/malloc.c | 130 +- roms/ipxe/src/core/memblock.c | 81 + roms/ipxe/src/core/menu.c | 178 + roms/ipxe/src/core/misc.c | 12 + roms/ipxe/src/core/monojob.c | 57 +- roms/ipxe/src/core/null_sanboot.c | 4 +- roms/ipxe/src/core/null_time.c | 30 + roms/ipxe/src/core/nvo.c | 10 +- roms/ipxe/src/core/open.c | 3 +- roms/ipxe/src/core/parseopt.c | 92 +- roms/ipxe/src/core/pcmcia.c | 1 - roms/ipxe/src/core/pending.c | 80 + roms/ipxe/src/core/posix_io.c | 3 +- roms/ipxe/src/core/process.c | 51 +- roms/ipxe/src/core/refcnt.c | 3 +- roms/ipxe/src/core/resolv.c | 14 +- roms/ipxe/src/core/serial.c | 7 +- roms/ipxe/src/core/serial_console.c | 17 +- roms/ipxe/src/core/settings.c | 858 ++- roms/ipxe/src/core/strtoull.c | 12 + roms/ipxe/src/core/time.c | 138 + roms/ipxe/src/core/timer.c | 3 +- roms/ipxe/src/core/uri.c | 3 +- roms/ipxe/src/core/uuid.c | 5 +- roms/ipxe/src/core/version.c | 41 + roms/ipxe/src/core/vsprintf.c | 77 +- roms/ipxe/src/core/wchar.c | 43 + roms/ipxe/src/core/xfer.c | 46 +- roms/ipxe/src/core/xferbuf.c | 108 + roms/ipxe/src/crypto/aes_wrap.c | 5 +- roms/ipxe/src/crypto/arc4.c | 3 +- roms/ipxe/src/crypto/asn1.c | 745 +- roms/ipxe/src/crypto/axtls/aes.c | 197 +- roms/ipxe/src/crypto/axtls/bigint.c | 1496 ---- roms/ipxe/src/crypto/axtls/bigint.h | 60 +- roms/ipxe/src/crypto/axtls/bigint_impl.h | 66 +- roms/ipxe/src/crypto/axtls/config.h | 13 + roms/ipxe/src/crypto/axtls/crypto.h | 235 +- roms/ipxe/src/crypto/axtls/os_port.h | 67 +- roms/ipxe/src/crypto/axtls/rsa.c | 332 - roms/ipxe/src/crypto/axtls/sha1.c | 240 - roms/ipxe/src/crypto/axtls_aes.c | 8 +- roms/ipxe/src/crypto/axtls_sha1.c | 25 - roms/ipxe/src/crypto/bigint.c | 135 + roms/ipxe/src/crypto/cbc.c | 7 +- roms/ipxe/src/crypto/chap.c | 3 +- roms/ipxe/src/crypto/clientcert.c | 183 + roms/ipxe/src/crypto/cms.c | 705 ++ roms/ipxe/src/crypto/crandom.c | 55 - roms/ipxe/src/crypto/crc32.c | 3 +- roms/ipxe/src/crypto/crypto_null.c | 52 +- roms/ipxe/src/crypto/drbg.c | 427 ++ roms/ipxe/src/crypto/entropy.c | 479 ++ roms/ipxe/src/crypto/hash_df.c | 138 + roms/ipxe/src/crypto/hmac.c | 3 +- roms/ipxe/src/crypto/hmac_drbg.c | 359 + roms/ipxe/src/crypto/md5.c | 424 +- roms/ipxe/src/crypto/null_entropy.c | 36 + roms/ipxe/src/crypto/ocsp.c | 824 +++ roms/ipxe/src/crypto/random_nz.c | 76 + roms/ipxe/src/crypto/rbg.c | 115 + roms/ipxe/src/crypto/rootcert.c | 133 + roms/ipxe/src/crypto/rsa.c | 642 ++ roms/ipxe/src/crypto/sha1.c | 272 + roms/ipxe/src/crypto/sha1extra.c | 37 +- roms/ipxe/src/crypto/sha256.c | 256 + roms/ipxe/src/crypto/x509.c | 1636 ++++- roms/ipxe/src/drivers/bitbash/bitbash.c | 3 +- roms/ipxe/src/drivers/bitbash/i2c_bit.c | 14 +- roms/ipxe/src/drivers/bitbash/spi_bit.c | 9 +- roms/ipxe/src/drivers/block/ata.c | 3 +- roms/ipxe/src/drivers/block/scsi.c | 33 +- roms/ipxe/src/drivers/bus/isa.c | 6 +- roms/ipxe/src/drivers/bus/isapnp.c | 3 +- roms/ipxe/src/drivers/bus/pci.c | 3 +- roms/ipxe/src/drivers/bus/pcibackup.c | 3 +- roms/ipxe/src/drivers/bus/pcivpd.c | 3 +- roms/ipxe/src/drivers/infiniband/arbel.c | 909 ++- roms/ipxe/src/drivers/infiniband/arbel.h | 36 +- roms/ipxe/src/drivers/infiniband/hermon.c | 2550 +++---- roms/ipxe/src/drivers/infiniband/hermon.h | 35 +- roms/ipxe/src/drivers/infiniband/linda.c | 20 +- roms/ipxe/src/drivers/infiniband/linda.h | 3 +- roms/ipxe/src/drivers/infiniband/mlx_bitops.h | 3 +- roms/ipxe/src/drivers/infiniband/qib7322.c | 23 +- roms/ipxe/src/drivers/infiniband/qib7322.h | 3 +- roms/ipxe/src/drivers/infiniband/qib_genbits.pl | 3 +- roms/ipxe/src/drivers/net/3c509-eisa.c | 1 - roms/ipxe/src/drivers/net/3c509.h | 2 +- roms/ipxe/src/drivers/net/3c515.c | 5 +- roms/ipxe/src/drivers/net/3c595.c | 2 +- roms/ipxe/src/drivers/net/amd8111e.c | 3 +- roms/ipxe/src/drivers/net/amd8111e.h | 5 +- roms/ipxe/src/drivers/net/ath/ath.h | 239 + roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c | 1698 +++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k.h | 1279 ++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c | 340 + roms/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c | 154 + roms/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c | 544 ++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c | 631 ++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c | 1760 +++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c | 122 + .../src/drivers/net/ath/ath5k/ath5k_initvals.c | 1560 +++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c | 534 ++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c | 2581 +++++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c | 390 ++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c | 1174 ++++ roms/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c | 107 + roms/ipxe/src/drivers/net/ath/ath5k/base.h | 145 + roms/ipxe/src/drivers/net/ath/ath5k/desc.h | 332 + roms/ipxe/src/drivers/net/ath/ath5k/eeprom.h | 451 ++ roms/ipxe/src/drivers/net/ath/ath5k/reg.h | 2589 +++++++ roms/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h | 1181 ++++ roms/ipxe/src/drivers/net/ath/ath5k/rfgain.h | 516 ++ roms/ipxe/src/drivers/net/ath/ath9k/ani.h | 168 + .../src/drivers/net/ath/ath9k/ar5008_initvals.h | 672 ++ .../src/drivers/net/ath/ath9k/ar9001_initvals.h | 1356 ++++ .../src/drivers/net/ath/ath9k/ar9002_initvals.h | 3264 +++++++++ roms/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h | 613 ++ .../drivers/net/ath/ath9k/ar9003_2p2_initvals.h | 1864 +++++ .../ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h | 338 + roms/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h | 125 + roms/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h | 1124 +++ .../src/drivers/net/ath/ath9k/ar9340_initvals.h | 1525 +++++ .../src/drivers/net/ath/ath9k/ar9485_initvals.h | 1161 ++++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k.c | 208 + roms/ipxe/src/drivers/net/ath/ath9k/ath9k.h | 521 ++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c | 733 ++ .../src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c | 1663 +++++ .../src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c | 997 +++ .../src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c | 607 ++ .../src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c | 454 ++ .../src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c | 578 ++ .../src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c | 932 +++ .../drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c | 5005 ++++++++++++++ .../src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c | 409 ++ .../src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c | 669 ++ .../src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c | 1277 ++++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c | 403 ++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c | 69 + roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c | 551 ++ .../src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c | 1078 +++ .../src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c | 1019 +++ .../src/drivers/net/ath/ath9k/ath9k_eeprom_def.c | 1351 ++++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c | 2067 ++++++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c | 593 ++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c | 733 ++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c | 916 +++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c | 521 ++ roms/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c | 813 +++ roms/ipxe/src/drivers/net/ath/ath9k/calib.h | 115 + roms/ipxe/src/drivers/net/ath/ath9k/common.h | 56 + roms/ipxe/src/drivers/net/ath/ath9k/eeprom.h | 714 ++ roms/ipxe/src/drivers/net/ath/ath9k/hw-ops.h | 268 + roms/ipxe/src/drivers/net/ath/ath9k/hw.h | 995 +++ roms/ipxe/src/drivers/net/ath/ath9k/mac.h | 707 ++ roms/ipxe/src/drivers/net/ath/ath9k/phy.h | 51 + roms/ipxe/src/drivers/net/ath/ath9k/reg.h | 1919 ++++++ roms/ipxe/src/drivers/net/ath/ath_hw.c | 183 + roms/ipxe/src/drivers/net/ath/ath_key.c | 82 + roms/ipxe/src/drivers/net/ath/ath_main.c | 59 + roms/ipxe/src/drivers/net/ath/ath_regd.c | 602 ++ roms/ipxe/src/drivers/net/ath/reg.h | 64 + roms/ipxe/src/drivers/net/ath/regd.h | 263 + roms/ipxe/src/drivers/net/ath/regd_common.h | 481 ++ roms/ipxe/src/drivers/net/ath5k/ath5k.c | 1698 ----- roms/ipxe/src/drivers/net/ath5k/ath5k.h | 1279 ---- roms/ipxe/src/drivers/net/ath5k/ath5k_attach.c | 340 - roms/ipxe/src/drivers/net/ath5k/ath5k_caps.c | 154 - roms/ipxe/src/drivers/net/ath5k/ath5k_desc.c | 544 -- roms/ipxe/src/drivers/net/ath5k/ath5k_dma.c | 631 -- roms/ipxe/src/drivers/net/ath5k/ath5k_eeprom.c | 1760 ----- roms/ipxe/src/drivers/net/ath5k/ath5k_gpio.c | 122 - roms/ipxe/src/drivers/net/ath5k/ath5k_initvals.c | 1560 ----- roms/ipxe/src/drivers/net/ath5k/ath5k_pcu.c | 534 -- roms/ipxe/src/drivers/net/ath5k/ath5k_phy.c | 2581 ------- roms/ipxe/src/drivers/net/ath5k/ath5k_qcu.c | 390 -- roms/ipxe/src/drivers/net/ath5k/ath5k_reset.c | 1174 ---- roms/ipxe/src/drivers/net/ath5k/ath5k_rfkill.c | 107 - roms/ipxe/src/drivers/net/ath5k/base.h | 145 - roms/ipxe/src/drivers/net/ath5k/desc.h | 332 - roms/ipxe/src/drivers/net/ath5k/eeprom.h | 451 -- roms/ipxe/src/drivers/net/ath5k/reg.h | 2589 ------- roms/ipxe/src/drivers/net/ath5k/rfbuffer.h | 1181 ---- roms/ipxe/src/drivers/net/ath5k/rfgain.h | 516 -- roms/ipxe/src/drivers/net/atl1e.c | 4 +- roms/ipxe/src/drivers/net/atl1e.h | 4 +- roms/ipxe/src/drivers/net/b44.c | 60 +- roms/ipxe/src/drivers/net/b44.h | 3 +- roms/ipxe/src/drivers/net/cs89x0.c | 3 +- roms/ipxe/src/drivers/net/cs89x0.h | 3 +- roms/ipxe/src/drivers/net/davicom.c | 8 +- roms/ipxe/src/drivers/net/depca.c | 1 - roms/ipxe/src/drivers/net/dmfe.c | 23 +- roms/ipxe/src/drivers/net/e1000/e1000.c | 35 - roms/ipxe/src/drivers/net/e1000/e1000.h | 326 - roms/ipxe/src/drivers/net/e1000/e1000_82540.c | 754 -- roms/ipxe/src/drivers/net/e1000/e1000_82541.c | 1314 ---- roms/ipxe/src/drivers/net/e1000/e1000_82541.h | 86 - roms/ipxe/src/drivers/net/e1000/e1000_82542.c | 571 -- roms/ipxe/src/drivers/net/e1000/e1000_82543.c | 1635 ----- roms/ipxe/src/drivers/net/e1000/e1000_82543.h | 45 - roms/ipxe/src/drivers/net/e1000/e1000_api.c | 1108 --- roms/ipxe/src/drivers/net/e1000/e1000_api.h | 127 - roms/ipxe/src/drivers/net/e1000/e1000_defines.h | 1416 ---- roms/ipxe/src/drivers/net/e1000/e1000_hw.h | 728 -- roms/ipxe/src/drivers/net/e1000/e1000_mac.c | 2196 ------ roms/ipxe/src/drivers/net/e1000/e1000_mac.h | 94 - roms/ipxe/src/drivers/net/e1000/e1000_main.c | 909 --- roms/ipxe/src/drivers/net/e1000/e1000_manage.c | 389 -- roms/ipxe/src/drivers/net/e1000/e1000_manage.h | 84 - roms/ipxe/src/drivers/net/e1000/e1000_nvm.c | 923 --- roms/ipxe/src/drivers/net/e1000/e1000_nvm.h | 63 - roms/ipxe/src/drivers/net/e1000/e1000_osdep.h | 118 - roms/ipxe/src/drivers/net/e1000/e1000_phy.c | 2308 ------- roms/ipxe/src/drivers/net/e1000/e1000_phy.h | 171 - roms/ipxe/src/drivers/net/e1000/e1000_regs.h | 329 - roms/ipxe/src/drivers/net/e1000e/e1000e.c | 34 - roms/ipxe/src/drivers/net/e1000e/e1000e.h | 532 -- .../src/drivers/net/e1000e/e1000e_80003es2lan.c | 1533 ----- .../src/drivers/net/e1000e/e1000e_80003es2lan.h | 100 - roms/ipxe/src/drivers/net/e1000e/e1000e_82571.c | 1818 ----- roms/ipxe/src/drivers/net/e1000e/e1000e_82571.h | 55 - roms/ipxe/src/drivers/net/e1000e/e1000e_defines.h | 1469 ---- roms/ipxe/src/drivers/net/e1000e/e1000e_hw.h | 719 -- roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.c | 3444 ---------- roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.h | 196 - roms/ipxe/src/drivers/net/e1000e/e1000e_mac.c | 1883 ----- roms/ipxe/src/drivers/net/e1000e/e1000e_mac.h | 79 - roms/ipxe/src/drivers/net/e1000e/e1000e_main.c | 1265 ---- roms/ipxe/src/drivers/net/e1000e/e1000e_manage.c | 372 - roms/ipxe/src/drivers/net/e1000e/e1000e_manage.h | 86 - roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.c | 596 -- roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.h | 53 - roms/ipxe/src/drivers/net/e1000e/e1000e_phy.c | 3323 --------- roms/ipxe/src/drivers/net/e1000e/e1000e_phy.h | 261 - roms/ipxe/src/drivers/net/e1000e/e1000e_regs.h | 340 - roms/ipxe/src/drivers/net/eepro100.c | 6 +- roms/ipxe/src/drivers/net/efi/snpnet.c | 45 +- roms/ipxe/src/drivers/net/epic100.c | 9 +- roms/ipxe/src/drivers/net/epic100.h | 2 +- roms/ipxe/src/drivers/net/etherfabric.c | 11 +- roms/ipxe/src/drivers/net/forcedeth.c | 13 +- roms/ipxe/src/drivers/net/forcedeth.h | 5 +- roms/ipxe/src/drivers/net/igb/igb.c | 32 - roms/ipxe/src/drivers/net/igb/igb.h | 324 - roms/ipxe/src/drivers/net/igb/igb_82575.c | 1617 ----- roms/ipxe/src/drivers/net/igb/igb_82575.h | 442 -- roms/ipxe/src/drivers/net/igb/igb_api.c | 1108 --- roms/ipxe/src/drivers/net/igb/igb_api.h | 166 - roms/ipxe/src/drivers/net/igb/igb_defines.h | 1515 ---- roms/ipxe/src/drivers/net/igb/igb_hw.h | 697 -- roms/ipxe/src/drivers/net/igb/igb_mac.c | 1991 ------ roms/ipxe/src/drivers/net/igb/igb_mac.h | 82 - roms/ipxe/src/drivers/net/igb/igb_main.c | 1010 --- roms/ipxe/src/drivers/net/igb/igb_manage.c | 388 -- roms/ipxe/src/drivers/net/igb/igb_manage.h | 83 - roms/ipxe/src/drivers/net/igb/igb_nvm.c | 627 -- roms/ipxe/src/drivers/net/igb/igb_nvm.h | 52 - roms/ipxe/src/drivers/net/igb/igb_osdep.h | 129 - roms/ipxe/src/drivers/net/igb/igb_phy.c | 2470 ------- roms/ipxe/src/drivers/net/igb/igb_phy.h | 171 - roms/ipxe/src/drivers/net/igb/igb_regs.h | 486 -- roms/ipxe/src/drivers/net/igbvf/igbvf_main.c | 3 +- roms/ipxe/src/drivers/net/igbvf/igbvf_vf.h | 1 + roms/ipxe/src/drivers/net/intel.c | 959 +++ roms/ipxe/src/drivers/net/intel.h | 257 + roms/ipxe/src/drivers/net/ipoib.c | 655 +- roms/ipxe/src/drivers/net/jme.c | 3 +- roms/ipxe/src/drivers/net/jme.h | 3 +- roms/ipxe/src/drivers/net/mii.c | 113 + roms/ipxe/src/drivers/net/mtd80x.c | 1022 --- roms/ipxe/src/drivers/net/myri10ge.c | 11 +- roms/ipxe/src/drivers/net/myri10ge_mcp.h | 5 +- roms/ipxe/src/drivers/net/myson.c | 670 ++ roms/ipxe/src/drivers/net/myson.h | 200 + roms/ipxe/src/drivers/net/natsemi.c | 1287 ++-- roms/ipxe/src/drivers/net/natsemi.h | 485 +- roms/ipxe/src/drivers/net/ns83820.c | 1007 --- roms/ipxe/src/drivers/net/p80211hdr.h | 2 +- roms/ipxe/src/drivers/net/pcnet32.c | 5 +- roms/ipxe/src/drivers/net/pcnet32.h | 3 +- roms/ipxe/src/drivers/net/phantom/nx_bitops.h | 3 +- roms/ipxe/src/drivers/net/phantom/phantom.c | 3 +- roms/ipxe/src/drivers/net/phantom/phantom.h | 3 +- roms/ipxe/src/drivers/net/phantom/phantom_hw.h | 3 +- roms/ipxe/src/drivers/net/r8169.c | 2232 ------ roms/ipxe/src/drivers/net/r8169.h | 486 -- roms/ipxe/src/drivers/net/realtek.c | 1169 ++++ roms/ipxe/src/drivers/net/realtek.h | 286 + roms/ipxe/src/drivers/net/rtl8139.c | 596 -- roms/ipxe/src/drivers/net/sis190.h | 4 +- roms/ipxe/src/drivers/net/sis900.c | 10 +- roms/ipxe/src/drivers/net/skeleton.c | 310 + roms/ipxe/src/drivers/net/skeleton.h | 23 + roms/ipxe/src/drivers/net/skge.c | 3 +- roms/ipxe/src/drivers/net/skge.h | 8 +- roms/ipxe/src/drivers/net/sky2.c | 7 +- roms/ipxe/src/drivers/net/sky2.h | 6 +- roms/ipxe/src/drivers/net/smc9000.h | 4 +- roms/ipxe/src/drivers/net/sundance.c | 9 +- roms/ipxe/src/drivers/net/tg3.c | 3435 ---------- roms/ipxe/src/drivers/net/tg3.h | 2121 ------ roms/ipxe/src/drivers/net/tg3/tg3.c | 945 +++ roms/ipxe/src/drivers/net/tg3/tg3.h | 3425 ++++++++++ roms/ipxe/src/drivers/net/tg3/tg3_hw.c | 2653 +++++++ roms/ipxe/src/drivers/net/tg3/tg3_phy.c | 1603 +++++ roms/ipxe/src/drivers/net/tlan.c | 9 +- roms/ipxe/src/drivers/net/tlan.h | 3 +- roms/ipxe/src/drivers/net/via-rhine.c | 10 +- roms/ipxe/src/drivers/net/via-velocity.c | 5 +- roms/ipxe/src/drivers/net/via-velocity.h | 2 +- roms/ipxe/src/drivers/net/virtio-net.c | 2 +- roms/ipxe/src/drivers/net/vmxnet3.c | 670 ++ roms/ipxe/src/drivers/net/vmxnet3.h | 498 ++ roms/ipxe/src/drivers/net/vxge/vxge_main.c | 2 +- roms/ipxe/src/drivers/net/w89c840.c | 3 +- roms/ipxe/src/drivers/nvs/nvs.c | 3 +- roms/ipxe/src/drivers/nvs/nvsvpd.c | 3 +- roms/ipxe/src/drivers/nvs/spi.c | 3 +- roms/ipxe/src/drivers/nvs/threewire.c | 3 +- roms/ipxe/src/hci/commands/autoboot_cmd.c | 3 +- roms/ipxe/src/hci/commands/config_cmd.c | 3 +- roms/ipxe/src/hci/commands/dhcp_cmd.c | 3 +- roms/ipxe/src/hci/commands/digest_cmd.c | 8 +- roms/ipxe/src/hci/commands/fcmgmt_cmd.c | 3 +- roms/ipxe/src/hci/commands/gdbstub_cmd.c | 3 +- roms/ipxe/src/hci/commands/ifmgmt_cmd.c | 3 +- roms/ipxe/src/hci/commands/image_cmd.c | 433 +- roms/ipxe/src/hci/commands/image_trust_cmd.c | 173 + roms/ipxe/src/hci/commands/iwmgmt_cmd.c | 3 +- roms/ipxe/src/hci/commands/login_cmd.c | 3 +- roms/ipxe/src/hci/commands/lotest_cmd.c | 3 +- roms/ipxe/src/hci/commands/menu_cmd.c | 286 + roms/ipxe/src/hci/commands/nslookup_cmd.c | 79 + roms/ipxe/src/hci/commands/nvo_cmd.c | 42 +- roms/ipxe/src/hci/commands/route_cmd.c | 3 +- roms/ipxe/src/hci/commands/sanboot_cmd.c | 137 +- roms/ipxe/src/hci/commands/sync_cmd.c | 83 + roms/ipxe/src/hci/commands/time_cmd.c | 52 +- roms/ipxe/src/hci/commands/vlan_cmd.c | 3 +- roms/ipxe/src/hci/editstring.c | 19 +- roms/ipxe/src/hci/keymap/keymap_no-latin1.c | 34 + roms/ipxe/src/hci/mucurses/ansi_screen.c | 16 +- roms/ipxe/src/hci/mucurses/mucurses.c | 1 - roms/ipxe/src/hci/mucurses/widgets/editbox.c | 3 +- roms/ipxe/src/hci/readline.c | 40 +- roms/ipxe/src/hci/shell.c | 5 +- roms/ipxe/src/hci/tui/login_ui.c | 18 +- roms/ipxe/src/hci/tui/menu_ui.c | 367 + roms/ipxe/src/hci/tui/settings_ui.c | 14 +- roms/ipxe/src/hci/wireless_errors.c | 3 +- roms/ipxe/src/image/efi_image.c | 129 +- roms/ipxe/src/image/elf.c | 32 +- roms/ipxe/src/image/script.c | 42 +- roms/ipxe/src/image/segment.c | 3 +- roms/ipxe/src/include/assert.h | 3 + roms/ipxe/src/include/btext.h | 62 - roms/ipxe/src/include/compiler.h | 19 +- roms/ipxe/src/include/errno.h | 3 +- roms/ipxe/src/include/etherboot.h | 1 - roms/ipxe/src/include/hci/ifmgmt_cmd.h | 3 +- roms/ipxe/src/include/ipxe/aes.h | 4 + roms/ipxe/src/include/ipxe/ansiesc.h | 7 + roms/ipxe/src/include/ipxe/arp.h | 8 +- roms/ipxe/src/include/ipxe/asn1.h | 287 +- roms/ipxe/src/include/ipxe/bigint.h | 301 + roms/ipxe/src/include/ipxe/bitbash.h | 32 + roms/ipxe/src/include/ipxe/bitops.h | 3 +- roms/ipxe/src/include/ipxe/clientcert.h | 43 + roms/ipxe/src/include/ipxe/cms.h | 75 + roms/ipxe/src/include/ipxe/console.h | 61 +- roms/ipxe/src/include/ipxe/crypto.h | 100 +- roms/ipxe/src/include/ipxe/dhcp.h | 86 +- roms/ipxe/src/include/ipxe/drbg.h | 135 + roms/ipxe/src/include/ipxe/eapol.h | 3 +- roms/ipxe/src/include/ipxe/efi/Base.h | 51 +- .../ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h | 22 +- roms/ipxe/src/include/ipxe/efi/Library/BaseLib.h | 7218 ++++++++++++++++++++ roms/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h | 13 +- roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h | 24 +- .../src/include/ipxe/efi/Pi/PiFirmwareVolume.h | 13 +- roms/ipxe/src/include/ipxe/efi/Pi/PiHob.h | 21 +- roms/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h | 78 +- .../src/include/ipxe/efi/Protocol/ComponentName2.h | 5 +- roms/ipxe/src/include/ipxe/efi/Protocol/Cpu.h | 4 +- .../src/include/ipxe/efi/Protocol/DevicePath.h | 235 +- .../src/include/ipxe/efi/Protocol/FormBrowser2.h | 4 + .../include/ipxe/efi/Protocol/HiiConfigAccess.h | 6 + roms/ipxe/src/include/ipxe/efi/Protocol/LoadFile.h | 90 + .../ipxe/efi/Protocol/NetworkInterfaceIdentifier.h | 25 +- .../include/ipxe/efi/Protocol/PciRootBridgeIo.h | 10 +- .../src/include/ipxe/efi/Protocol/SimpleTextIn.h | 4 +- .../src/include/ipxe/efi/Protocol/SimpleTextInEx.h | 327 + roms/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h | 4 +- roms/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h | 3 +- .../ipxe/efi/Uefi/UefiInternalFormRepresentation.h | 33 +- .../src/include/ipxe/efi/Uefi/UefiMultiPhase.h | 42 +- roms/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h | 29 +- roms/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h | 6 +- roms/ipxe/src/include/ipxe/efi/efi.h | 2 + roms/ipxe/src/include/ipxe/efi/efi_hii.h | 192 +- roms/ipxe/src/include/ipxe/efi/efi_pci.h | 5 + roms/ipxe/src/include/ipxe/efi/efi_snp.h | 75 + roms/ipxe/src/include/ipxe/efi/efi_uaccess.h | 6 + roms/ipxe/src/include/ipxe/efi/ipxe_download.h | 154 + roms/ipxe/src/include/ipxe/elf.h | 2 +- roms/ipxe/src/include/ipxe/entropy.h | 224 + roms/ipxe/src/include/ipxe/errfile.h | 28 +- roms/ipxe/src/include/ipxe/ethernet.h | 9 + roms/ipxe/src/include/ipxe/fc.h | 77 +- roms/ipxe/src/include/ipxe/features.h | 2 + roms/ipxe/src/include/ipxe/fip.h | 3 +- roms/ipxe/src/include/ipxe/hash_df.h | 18 + roms/ipxe/src/include/ipxe/hmac_drbg.h | 253 + roms/ipxe/src/include/ipxe/http.h | 1 + roms/ipxe/src/include/ipxe/ib_packet.h | 5 +- roms/ipxe/src/include/ipxe/image.h | 44 +- roms/ipxe/src/include/ipxe/infiniband.h | 31 +- roms/ipxe/src/include/ipxe/iobuf.h | 14 +- roms/ipxe/src/include/ipxe/ip.h | 25 +- roms/ipxe/src/include/ipxe/ipoib.h | 42 +- roms/ipxe/src/include/ipxe/isapnp.h | 3 +- roms/ipxe/src/include/ipxe/iscsi.h | 4 +- roms/ipxe/src/include/ipxe/lineconsole.h | 36 + roms/ipxe/src/include/ipxe/linux/linux_entropy.h | 32 + roms/ipxe/src/include/ipxe/linux/linux_time.h | 18 + roms/ipxe/src/include/ipxe/linux/linux_uaccess.h | 6 + roms/ipxe/src/include/ipxe/list.h | 385 +- roms/ipxe/src/include/ipxe/malloc.h | 38 +- roms/ipxe/src/include/ipxe/md5.h | 69 +- roms/ipxe/src/include/ipxe/memblock.h | 17 + roms/ipxe/src/include/ipxe/menu.h | 49 + roms/ipxe/src/include/ipxe/mii.h | 87 + roms/ipxe/src/include/ipxe/net80211.h | 2 +- roms/ipxe/src/include/ipxe/netdevice.h | 39 +- roms/ipxe/src/include/ipxe/null_entropy.h | 52 + roms/ipxe/src/include/ipxe/null_sanboot.h | 5 + roms/ipxe/src/include/ipxe/null_time.h | 23 + roms/ipxe/src/include/ipxe/nvo.h | 4 + roms/ipxe/src/include/ipxe/ocsp.h | 102 + roms/ipxe/src/include/ipxe/parseopt.h | 7 +- roms/ipxe/src/include/ipxe/pci.h | 5 +- roms/ipxe/src/include/ipxe/pending.h | 34 + roms/ipxe/src/include/ipxe/process.h | 140 +- roms/ipxe/src/include/ipxe/random_nz.h | 16 + roms/ipxe/src/include/ipxe/rbg.h | 43 + roms/ipxe/src/include/ipxe/retry.h | 1 + roms/ipxe/src/include/ipxe/rootcert.h | 16 + roms/ipxe/src/include/ipxe/rotate.h | 12 +- roms/ipxe/src/include/ipxe/rsa.h | 75 +- roms/ipxe/src/include/ipxe/sanboot.h | 11 +- roms/ipxe/src/include/ipxe/sec80211.h | 3 +- roms/ipxe/src/include/ipxe/serial.h | 1 + roms/ipxe/src/include/ipxe/settings.h | 61 +- roms/ipxe/src/include/ipxe/sha1.h | 78 +- roms/ipxe/src/include/ipxe/sha256.h | 73 + roms/ipxe/src/include/ipxe/syslog.h | 13 +- roms/ipxe/src/include/ipxe/tcp.h | 78 +- roms/ipxe/src/include/ipxe/tcpip.h | 12 +- roms/ipxe/src/include/ipxe/test.h | 45 + roms/ipxe/src/include/ipxe/threewire.h | 13 + roms/ipxe/src/include/ipxe/time.h | 59 + roms/ipxe/src/include/ipxe/tls.h | 161 +- roms/ipxe/src/include/ipxe/uaccess.h | 21 + roms/ipxe/src/include/ipxe/uuid.h | 2 +- roms/ipxe/src/include/ipxe/validator.h | 17 + roms/ipxe/src/include/ipxe/version.h | 16 + roms/ipxe/src/include/ipxe/wpa.h | 3 +- roms/ipxe/src/include/ipxe/x509.h | 376 +- roms/ipxe/src/include/ipxe/xferbuf.h | 31 + roms/ipxe/src/include/linux_api.h | 1 - roms/ipxe/src/include/mii.h | 288 +- roms/ipxe/src/include/readline/readline.h | 4 +- roms/ipxe/src/include/stdarg.h | 26 + roms/ipxe/src/include/stddef.h | 1 + roms/ipxe/src/include/stdio.h | 4 + roms/ipxe/src/include/stdlib.h | 4 - roms/ipxe/src/include/string.h | 1 + roms/ipxe/src/include/sys/time.h | 24 +- roms/ipxe/src/include/syslog.h | 100 + roms/ipxe/src/include/time.h | 51 +- roms/ipxe/src/include/usr/autoboot.h | 14 +- roms/ipxe/src/include/usr/imgmgmt.h | 43 +- roms/ipxe/src/include/usr/imgtrust.h | 17 + roms/ipxe/src/include/usr/nslookup.h | 14 + roms/ipxe/src/include/wchar.h | 29 + roms/ipxe/src/interface/bofm/bofm.c | 24 +- roms/ipxe/src/interface/efi/efi_bofm.c | 120 +- roms/ipxe/src/interface/efi/efi_console.c | 11 +- roms/ipxe/src/interface/efi/efi_download.c | 233 + roms/ipxe/src/interface/efi/efi_driver.c | 30 +- roms/ipxe/src/interface/efi/efi_hii.c | 577 ++ roms/ipxe/src/interface/efi/efi_init.c | 3 +- roms/ipxe/src/interface/efi/efi_io.c | 3 +- roms/ipxe/src/interface/efi/efi_pci.c | 25 +- roms/ipxe/src/interface/efi/efi_smbios.c | 3 +- roms/ipxe/src/interface/efi/efi_snp.c | 477 +- roms/ipxe/src/interface/efi/efi_snp_hii.c | 707 ++ roms/ipxe/src/interface/efi/efi_strerror.c | 3 +- roms/ipxe/src/interface/efi/efi_strings.c | 3 +- roms/ipxe/src/interface/efi/efi_timer.c | 3 +- roms/ipxe/src/interface/efi/efi_uaccess.c | 3 +- roms/ipxe/src/interface/efi/efi_umalloc.c | 3 +- roms/ipxe/src/interface/linux/linux_console.c | 9 + roms/ipxe/src/interface/linux/linux_entropy.c | 97 + roms/ipxe/src/interface/linux/linux_nap.c | 3 +- roms/ipxe/src/interface/linux/linux_time.c | 45 + roms/ipxe/src/interface/linux/linux_uaccess.c | 3 +- roms/ipxe/src/interface/smbios/smbios.c | 3 +- roms/ipxe/src/interface/smbios/smbios_settings.c | 16 +- roms/ipxe/src/net/80211/net80211.c | 39 +- roms/ipxe/src/net/80211/rc80211.c | 3 +- roms/ipxe/src/net/80211/sec80211.c | 3 +- roms/ipxe/src/net/80211/wep.c | 3 +- roms/ipxe/src/net/80211/wpa.c | 8 +- roms/ipxe/src/net/80211/wpa_ccmp.c | 4 +- roms/ipxe/src/net/80211/wpa_psk.c | 4 +- roms/ipxe/src/net/80211/wpa_tkip.c | 12 +- roms/ipxe/src/net/aoe.c | 8 +- roms/ipxe/src/net/arp.c | 456 +- roms/ipxe/src/net/cachedhcp.c | 3 +- roms/ipxe/src/net/dhcpopts.c | 3 +- roms/ipxe/src/net/dhcppkt.c | 3 +- roms/ipxe/src/net/eapol.c | 7 +- roms/ipxe/src/net/eth_slow.c | 7 +- roms/ipxe/src/net/ethernet.c | 22 +- roms/ipxe/src/net/fakedhcp.c | 12 +- roms/ipxe/src/net/fc.c | 91 +- roms/ipxe/src/net/fcels.c | 19 +- roms/ipxe/src/net/fcns.c | 19 +- roms/ipxe/src/net/fcoe.c | 11 +- roms/ipxe/src/net/fcp.c | 71 +- roms/ipxe/src/net/icmp.c | 3 +- roms/ipxe/src/net/infiniband.c | 72 +- roms/ipxe/src/net/infiniband/ib_cm.c | 3 +- roms/ipxe/src/net/infiniband/ib_cmrc.c | 33 +- roms/ipxe/src/net/infiniband/ib_mcast.c | 3 +- roms/ipxe/src/net/infiniband/ib_mi.c | 19 +- roms/ipxe/src/net/infiniband/ib_packet.c | 66 +- roms/ipxe/src/net/infiniband/ib_pathrec.c | 3 +- roms/ipxe/src/net/infiniband/ib_sma.c | 3 +- roms/ipxe/src/net/infiniband/ib_smc.c | 3 +- roms/ipxe/src/net/iobpad.c | 3 +- roms/ipxe/src/net/ipv4.c | 454 +- roms/ipxe/src/net/ipv6.c | 4 +- roms/ipxe/src/net/mii.c | 147 - roms/ipxe/src/net/netdev_settings.c | 3 +- roms/ipxe/src/net/netdevice.c | 115 +- roms/ipxe/src/net/nullnet.c | 3 +- roms/ipxe/src/net/rarp.c | 7 +- roms/ipxe/src/net/retry.c | 26 +- roms/ipxe/src/net/tcp.c | 174 +- roms/ipxe/src/net/tcp/ftp.c | 100 +- roms/ipxe/src/net/tcp/http.c | 519 +- roms/ipxe/src/net/tcp/httpcore.c | 1363 ++++ roms/ipxe/src/net/tcp/https.c | 3 +- roms/ipxe/src/net/tcp/iscsi.c | 146 +- roms/ipxe/src/net/tcp/syslogs.c | 274 + roms/ipxe/src/net/tcpip.c | 4 +- roms/ipxe/src/net/tls.c | 1759 +++-- roms/ipxe/src/net/udp.c | 7 +- roms/ipxe/src/net/udp/dhcp.c | 73 +- roms/ipxe/src/net/udp/dns.c | 37 +- roms/ipxe/src/net/udp/slam.c | 3 +- roms/ipxe/src/net/udp/syslog.c | 142 +- roms/ipxe/src/net/udp/tftp.c | 11 +- roms/ipxe/src/net/validator.c | 576 ++ roms/ipxe/src/net/vlan.c | 10 +- roms/ipxe/src/tests/aes_cbc_test.c | 193 + roms/ipxe/src/tests/base64_test.c | 124 + roms/ipxe/src/tests/bigint_test.c | 2437 +++++++ roms/ipxe/src/tests/bofm_test.c | 3 +- roms/ipxe/src/tests/byteswap_test.c | 92 + roms/ipxe/src/tests/cbc_test.c | 171 + roms/ipxe/src/tests/cbc_test.h | 57 + roms/ipxe/src/tests/cms_test.c | 1438 ++++ roms/ipxe/src/tests/crc32_test.c | 116 + roms/ipxe/src/tests/digest_test.c | 105 + roms/ipxe/src/tests/digest_test.h | 37 + roms/ipxe/src/tests/entropy_sample.c | 72 + roms/ipxe/src/tests/hash_df_test.c | 898 +++ roms/ipxe/src/tests/hmac_drbg_test.c | 1386 ++++ roms/ipxe/src/tests/list_test.c | 483 ++ roms/ipxe/src/tests/md5_test.c | 100 + roms/ipxe/src/tests/memcpy_test.c | 290 +- roms/ipxe/src/tests/ocsp_test.c | 1450 ++++ roms/ipxe/src/tests/pubkey_test.h | 175 + roms/ipxe/src/tests/rsa_test.c | 492 ++ roms/ipxe/src/tests/settings_test.c | 278 + roms/ipxe/src/tests/sha1_test.c | 105 + roms/ipxe/src/tests/sha256_test.c | 108 + roms/ipxe/src/tests/string_test.c | 133 + roms/ipxe/src/tests/tcpip_test.c | 213 + roms/ipxe/src/tests/test.c | 174 + roms/ipxe/src/tests/tests.c | 48 + roms/ipxe/src/tests/time_test.c | 183 + roms/ipxe/src/tests/x509_test.c | 948 +++ roms/ipxe/src/usr/autoboot.c | 112 +- roms/ipxe/src/usr/dhcpmgmt.c | 15 +- roms/ipxe/src/usr/fcmgmt.c | 6 +- roms/ipxe/src/usr/ifmgmt.c | 6 +- roms/ipxe/src/usr/imgmgmt.c | 202 +- roms/ipxe/src/usr/imgtrust.c | 110 + roms/ipxe/src/usr/iwmgmt.c | 4 +- roms/ipxe/src/usr/lotest.c | 149 +- roms/ipxe/src/usr/nslookup.c | 185 + roms/ipxe/src/usr/prompt.c | 3 +- roms/ipxe/src/usr/pxemenu.c | 5 +- roms/ipxe/src/usr/route.c | 3 +- roms/ipxe/src/util/Makefile | 10 +- roms/ipxe/src/util/Option/ROM.pm | 236 +- roms/ipxe/src/util/catrom.pl | 49 +- roms/ipxe/src/util/disrom.pl | 130 +- roms/ipxe/src/util/efirom.c | 21 +- roms/ipxe/src/util/einfo.c | 21 +- roms/ipxe/src/util/elf2efi.c | 19 +- roms/ipxe/src/util/fixrom.pl | 13 +- roms/ipxe/src/util/fnrec.pl | 3 +- roms/ipxe/src/util/geniso | 2 +- roms/ipxe/src/util/genkeymap.pl | 9 +- roms/ipxe/src/util/get-pci-ids | 3 +- roms/ipxe/src/util/iccfix.c | 3 +- roms/ipxe/src/util/licence.pl | 3 +- roms/ipxe/src/util/mergerom.pl | 33 +- roms/ipxe/src/util/niclist.pl | 588 ++ roms/ipxe/src/util/nrv2b.c | 7 +- roms/ipxe/src/util/parserom.pl | 4 +- roms/ipxe/src/util/romcheck.pl | 54 + roms/ipxe/src/util/zbin.c | 77 +- roms/openbios/.gitignore | 1 + roms/openbios/Makefile | 21 +- roms/openbios/Makefile.target | 8 +- roms/openbios/VERSION | 2 +- roms/openbios/arch/amd64/build.xml | 1 + roms/openbios/arch/amd64/init.fs | 7 + roms/openbios/arch/ppc/build.xml | 4 + roms/openbios/arch/ppc/ppc.fs | 21 + roms/openbios/arch/ppc/qemu/init.c | 36 +- roms/openbios/arch/ppc/qemu/main.c | 139 - roms/openbios/arch/ppc/qemu/ofmem.c | 60 +- roms/openbios/arch/ppc/qemu/qemu.fs | 33 + roms/openbios/arch/ppc/qemu/start.S | 9 +- roms/openbios/arch/sparc32/boot.h | 3 - roms/openbios/arch/sparc32/build.xml | 1 + roms/openbios/arch/sparc32/console.c | 48 +- roms/openbios/arch/sparc32/entry.S | 1 + roms/openbios/arch/sparc32/init.fs | 8 +- roms/openbios/arch/sparc32/lib.c | 34 +- roms/openbios/arch/sparc32/ofmem_sparc32.c | 5 +- roms/openbios/arch/sparc32/openbios.c | 27 +- roms/openbios/arch/sparc32/tree.fs | 1 + roms/openbios/arch/sparc32/wuf.S | 1 + roms/openbios/arch/sparc64/build.xml | 1 + roms/openbios/arch/sparc64/console.c | 12 - roms/openbios/arch/sparc64/init.fs | 6 + roms/openbios/arch/sparc64/openbios.c | 16 +- roms/openbios/arch/sparc64/tree.fs | 2 + roms/openbios/arch/unix/unix.c | 20 + roms/openbios/arch/x86/build.xml | 1 + roms/openbios/arch/x86/init.fs | 8 + roms/openbios/arch/x86/openbios.c | 8 +- roms/openbios/config/examples/amd64_config.xml | 1 + roms/openbios/config/examples/ppc_config.xml | 2 + roms/openbios/config/scripts/switch-arch | 65 +- roms/openbios/config/xml/dictionary.xsl | 43 +- roms/openbios/config/xml/fcode.xsl | 48 + roms/openbios/config/xml/makefile.xsl | 2 + roms/openbios/config/xml/object.xsl | 1 - roms/openbios/config/xml/rules.xml | 3 + roms/openbios/drivers/adb_kbd.c | 27 + roms/openbios/drivers/build.xml | 3 + roms/openbios/drivers/cuda.c | 15 + roms/openbios/drivers/escc.c | 10 +- roms/openbios/drivers/esp.c | 6 +- roms/openbios/drivers/ide.c | 10 +- roms/openbios/drivers/macio.c | 112 +- roms/openbios/drivers/pci.c | 38 +- roms/openbios/drivers/pci.h | 1 + roms/openbios/drivers/pci_database.c | 6 +- roms/openbios/drivers/pci_database.h | 1 - roms/openbios/drivers/sbus.c | 18 + roms/openbios/drivers/tcx.fs | 46 + roms/openbios/drivers/vga.fs | 46 + roms/openbios/drivers/vga_vbe.c | 89 +- roms/openbios/forth/admin/iocontrol.fs | 7 +- roms/openbios/forth/admin/userboot.fs | 2 +- roms/openbios/forth/bootstrap/bootstrap.fs | 27 +- roms/openbios/forth/debugging/client.fs | 96 +- roms/openbios/forth/device/device.fs | 11 + roms/openbios/forth/device/display.fs | 264 +- roms/openbios/forth/device/font.fs | 4 + roms/openbios/forth/device/pathres.fs | 39 +- roms/openbios/forth/device/property.fs | 2 +- roms/openbios/forth/device/terminal.fs | 75 +- roms/openbios/forth/device/tree.fs | 2 - roms/openbios/forth/lib/build.xml | 1 + roms/openbios/forth/lib/locals.fs | 197 + roms/openbios/forth/lib/split.fs | 21 - roms/openbios/fs/hfsplus/hfsp_fs.c | 141 +- roms/openbios/fs/hfsplus/hfsp_unicode.c | 5 +- roms/openbios/fs/hfsplus/hfsp_volume.c | 15 +- roms/openbios/include/arch/common/fw_cfg.h | 3 +- roms/openbios/include/arch/ppc/types.h | 8 + roms/openbios/include/arch/sparc32/io.h | 7 + roms/openbios/include/arch/sparc32/ofmem_sparc32.h | 3 + roms/openbios/include/drivers/drivers.h | 1 + roms/openbios/include/libopenbios/bootcode_load.h | 22 + roms/openbios/include/libopenbios/console.h | 9 - roms/openbios/include/libopenbios/video.h | 38 + roms/openbios/include/packages/video.h | 6 +- roms/openbios/libopenbios/bootcode_load.c | 75 + roms/openbios/libopenbios/build.xml | 3 +- roms/openbios/libopenbios/console_common.c | 415 -- roms/openbios/libopenbios/load.c | 13 + roms/openbios/libopenbios/ofmem_common.c | 22 +- roms/openbios/libopenbios/video_common.c | 280 + roms/openbios/packages/build.xml | 2 +- roms/openbios/packages/disk-label.c | 105 +- roms/openbios/packages/mac-parts.c | 272 +- roms/openbios/packages/molvideo.c | 172 + roms/openbios/packages/pc-parts.c | 51 +- roms/openbios/packages/sun-parts.c | 57 +- roms/openbios/packages/video.c | 360 - roms/qemu-palcode/Makefile | 4 +- roms/qemu-palcode/init.c | 3 +- roms/qemu-palcode/pal.S | 11 +- roms/qemu-palcode/pal.h | 1 + roms/qemu-palcode/palcode.ld | 11 +- roms/qemu-palcode/protos.h | 1 + roms/qemu-palcode/uart.c | 2 +- roms/qemu-palcode/vgafonts.c | 6 +- roms/qemu-palcode/vgatables.c | 2 +- roms/qemu-palcode/vgatables.h | 14 +- roms/seabios/Makefile | 55 +- roms/seabios/src/Kconfig | 2 +- roms/seabios/src/acpi-dsdt-cpu-hotplug.dsl | 78 + roms/seabios/src/acpi-dsdt-dbug.dsl | 26 + roms/seabios/src/acpi-dsdt-hpet.dsl | 36 + roms/seabios/src/acpi-dsdt-isa.dsl | 102 + roms/seabios/src/acpi-dsdt-pci-crs.dsl | 107 + roms/seabios/src/acpi-dsdt.dsl | 767 +-- roms/seabios/src/acpi.c | 89 +- roms/seabios/src/acpi.h | 17 + roms/seabios/src/boot.c | 25 +- roms/seabios/src/bootsplash.c | 2 +- roms/seabios/src/config.h | 1 - roms/seabios/src/dev-q35.h | 46 + roms/seabios/src/floppy.c | 34 +- roms/seabios/src/megasas.c | 25 +- roms/seabios/src/mtrr.c | 5 +- roms/seabios/src/pciinit.c | 126 +- roms/seabios/src/post.c | 11 +- roms/seabios/src/q35-acpi-dsdt.dsl | 450 ++ roms/seabios/src/shadow.c | 13 + roms/seabios/src/smbios.c | 68 + roms/seabios/src/smbios.h | 1 + roms/seabios/src/smm.c | 37 + roms/seabios/src/ssdt-pcihp.dsl | 20 +- roms/seabios/src/ssdt-proc.dsl | 14 +- roms/seabios/src/ssdt-susp.dsl | 9 +- roms/seabios/src/usb-ehci.c | 2 +- roms/seabios/src/virtio-scsi.c | 5 +- roms/seabios/src/virtio-scsi.h | 4 +- roms/seabios/tools/acpi_extract.py | 4 +- roms/seabios/tools/test-build.sh | 63 +- roms/seabios/tools/vgafixup.py | 2 +- roms/seabios/vgasrc/vgabios.c | 60 + 1021 files changed, 136174 insertions(+), 97137 deletions(-) create mode 100644 roms/SLOF/board-qemu/slof/.gitignore create mode 100644 roms/SLOF/board-qemu/slof/rtas-nvram.fs create mode 100644 roms/SLOF/clients/.gitignore create mode 100644 roms/SLOF/romfs/tools/.gitignore create mode 100644 roms/SLOF/tools/.gitignore create mode 100644 roms/config.ipxe.general.h delete mode 100644 roms/ipxe/src/arch/i386/core/aout_loader.c delete mode 100644 roms/ipxe/src/arch/i386/core/cmdline.c delete mode 100644 roms/ipxe/src/arch/i386/core/cpu.c delete mode 100644 roms/ipxe/src/arch/i386/core/freebsd_loader.c create mode 100644 roms/ipxe/src/arch/i386/core/linux/linuxprefix.S create mode 100644 roms/ipxe/src/arch/i386/core/runtime.c delete mode 100644 roms/ipxe/src/arch/i386/core/wince_loader.c delete mode 100644 roms/ipxe/src/arch/i386/core/x86_io.c create mode 100644 roms/ipxe/src/arch/i386/image/initrd.c create mode 100644 roms/ipxe/src/arch/i386/image/sdi.c delete mode 100644 roms/ipxe/src/arch/i386/include/bits/cpu.h create mode 100644 roms/ipxe/src/arch/i386/include/bits/entropy.h delete mode 100644 roms/ipxe/src/arch/i386/include/bits/errfile.h delete mode 100644 roms/ipxe/src/arch/i386/include/bits/io.h create mode 100644 roms/ipxe/src/arch/i386/include/bits/time.h create mode 100644 roms/ipxe/src/arch/i386/include/initrd.h create mode 100644 roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h create mode 100644 roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h create mode 100644 roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h create mode 100644 roms/ipxe/src/arch/i386/include/ipxe/vmware.h delete mode 100644 roms/ipxe/src/arch/i386/include/ipxe/x86_io.h create mode 100644 roms/ipxe/src/arch/i386/include/rtc.h create mode 100644 roms/ipxe/src/arch/i386/include/sdi.h create mode 100644 roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c create mode 100644 roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c create mode 100644 roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c create mode 100644 roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c create mode 100644 roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c create mode 100644 roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c create mode 100644 roms/ipxe/src/arch/i386/interface/vmware/vmware.c create mode 100644 roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S delete mode 100644 roms/ipxe/src/arch/i386/prefix/linuxprefix.S create mode 100644 roms/ipxe/src/arch/x86/core/cpuid.c create mode 100644 roms/ipxe/src/arch/x86/core/debugcon.c create mode 100644 roms/ipxe/src/arch/x86/core/x86_bigint.c create mode 100644 roms/ipxe/src/arch/x86/core/x86_io.c create mode 100644 roms/ipxe/src/arch/x86/core/x86_tcpip.c create mode 100644 roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c create mode 100644 roms/ipxe/src/arch/x86/include/bits/bigint.h create mode 100644 roms/ipxe/src/arch/x86/include/bits/errfile.h create mode 100644 roms/ipxe/src/arch/x86/include/bits/io.h create mode 100644 roms/ipxe/src/arch/x86/include/bits/tcpip.h create mode 100644 roms/ipxe/src/arch/x86/include/ipxe/cpuid.h create mode 100644 roms/ipxe/src/arch/x86/include/ipxe/x86_io.h create mode 100644 roms/ipxe/src/arch/x86_64/core/linux/linuxprefix.S create mode 100644 roms/ipxe/src/arch/x86_64/include/bits/entropy.h delete mode 100644 roms/ipxe/src/arch/x86_64/include/bits/errfile.h delete mode 100644 roms/ipxe/src/arch/x86_64/include/bits/io.h create mode 100644 roms/ipxe/src/arch/x86_64/include/bits/time.h delete mode 100644 roms/ipxe/src/arch/x86_64/prefix/linuxprefix.S create mode 100644 roms/ipxe/src/config/colour.h create mode 100644 roms/ipxe/src/config/entropy.h create mode 100644 roms/ipxe/src/config/time.h create mode 100644 roms/ipxe/src/core/assert.c delete mode 100644 roms/ipxe/src/core/btext.c create mode 100644 roms/ipxe/src/core/lineconsole.c create mode 100644 roms/ipxe/src/core/list.c create mode 100644 roms/ipxe/src/core/log.c create mode 100644 roms/ipxe/src/core/memblock.c create mode 100644 roms/ipxe/src/core/menu.c create mode 100644 roms/ipxe/src/core/null_time.c create mode 100644 roms/ipxe/src/core/pending.c create mode 100644 roms/ipxe/src/core/time.c create mode 100644 roms/ipxe/src/core/version.c create mode 100644 roms/ipxe/src/core/wchar.c create mode 100644 roms/ipxe/src/core/xferbuf.c delete mode 100644 roms/ipxe/src/crypto/axtls/bigint.c create mode 100644 roms/ipxe/src/crypto/axtls/config.h delete mode 100644 roms/ipxe/src/crypto/axtls/rsa.c delete mode 100644 roms/ipxe/src/crypto/axtls/sha1.c delete mode 100644 roms/ipxe/src/crypto/axtls_sha1.c create mode 100644 roms/ipxe/src/crypto/bigint.c create mode 100644 roms/ipxe/src/crypto/clientcert.c create mode 100644 roms/ipxe/src/crypto/cms.c delete mode 100644 roms/ipxe/src/crypto/crandom.c create mode 100644 roms/ipxe/src/crypto/drbg.c create mode 100644 roms/ipxe/src/crypto/entropy.c create mode 100644 roms/ipxe/src/crypto/hash_df.c create mode 100644 roms/ipxe/src/crypto/hmac_drbg.c create mode 100644 roms/ipxe/src/crypto/null_entropy.c create mode 100644 roms/ipxe/src/crypto/ocsp.c create mode 100644 roms/ipxe/src/crypto/random_nz.c create mode 100644 roms/ipxe/src/crypto/rbg.c create mode 100644 roms/ipxe/src/crypto/rootcert.c create mode 100644 roms/ipxe/src/crypto/rsa.c create mode 100644 roms/ipxe/src/crypto/sha1.c create mode 100644 roms/ipxe/src/crypto/sha256.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/base.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/desc.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/eeprom.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/reg.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath5k/rfgain.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ani.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/calib.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/common.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/eeprom.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/hw-ops.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/hw.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/mac.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/phy.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath9k/reg.h create mode 100644 roms/ipxe/src/drivers/net/ath/ath_hw.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath_key.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath_main.c create mode 100644 roms/ipxe/src/drivers/net/ath/ath_regd.c create mode 100644 roms/ipxe/src/drivers/net/ath/reg.h create mode 100644 roms/ipxe/src/drivers/net/ath/regd.h create mode 100644 roms/ipxe/src/drivers/net/ath/regd_common.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_attach.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_caps.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_desc.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_dma.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_eeprom.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_gpio.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_initvals.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_pcu.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_phy.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_qcu.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_reset.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/ath5k_rfkill.c delete mode 100644 roms/ipxe/src/drivers/net/ath5k/base.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/desc.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/eeprom.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/reg.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/rfbuffer.h delete mode 100644 roms/ipxe/src/drivers/net/ath5k/rfgain.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82540.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82541.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82541.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82542.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82543.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_82543.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_api.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_api.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_defines.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_hw.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_mac.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_mac.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_main.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_manage.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_manage.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_nvm.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_nvm.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_osdep.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_phy.c delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_phy.h delete mode 100644 roms/ipxe/src/drivers/net/e1000/e1000_regs.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_82571.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_82571.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_defines.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_hw.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_mac.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_mac.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_main.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_manage.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_manage.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_phy.c delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_phy.h delete mode 100644 roms/ipxe/src/drivers/net/e1000e/e1000e_regs.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_82575.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_82575.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_api.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_api.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_defines.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_hw.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_mac.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_mac.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_main.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_manage.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_manage.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_nvm.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_nvm.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_osdep.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_phy.c delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_phy.h delete mode 100644 roms/ipxe/src/drivers/net/igb/igb_regs.h create mode 100644 roms/ipxe/src/drivers/net/intel.c create mode 100644 roms/ipxe/src/drivers/net/intel.h create mode 100644 roms/ipxe/src/drivers/net/mii.c delete mode 100644 roms/ipxe/src/drivers/net/mtd80x.c create mode 100644 roms/ipxe/src/drivers/net/myson.c create mode 100644 roms/ipxe/src/drivers/net/myson.h delete mode 100644 roms/ipxe/src/drivers/net/ns83820.c delete mode 100644 roms/ipxe/src/drivers/net/r8169.c delete mode 100644 roms/ipxe/src/drivers/net/r8169.h create mode 100644 roms/ipxe/src/drivers/net/realtek.c create mode 100644 roms/ipxe/src/drivers/net/realtek.h delete mode 100644 roms/ipxe/src/drivers/net/rtl8139.c create mode 100644 roms/ipxe/src/drivers/net/skeleton.c create mode 100644 roms/ipxe/src/drivers/net/skeleton.h delete mode 100644 roms/ipxe/src/drivers/net/tg3.c delete mode 100644 roms/ipxe/src/drivers/net/tg3.h create mode 100644 roms/ipxe/src/drivers/net/tg3/tg3.c create mode 100644 roms/ipxe/src/drivers/net/tg3/tg3.h create mode 100644 roms/ipxe/src/drivers/net/tg3/tg3_hw.c create mode 100644 roms/ipxe/src/drivers/net/tg3/tg3_phy.c create mode 100644 roms/ipxe/src/drivers/net/vmxnet3.c create mode 100644 roms/ipxe/src/drivers/net/vmxnet3.h create mode 100644 roms/ipxe/src/hci/commands/image_trust_cmd.c create mode 100644 roms/ipxe/src/hci/commands/menu_cmd.c create mode 100644 roms/ipxe/src/hci/commands/nslookup_cmd.c create mode 100644 roms/ipxe/src/hci/commands/sync_cmd.c create mode 100644 roms/ipxe/src/hci/keymap/keymap_no-latin1.c create mode 100644 roms/ipxe/src/hci/tui/menu_ui.c delete mode 100644 roms/ipxe/src/include/btext.h create mode 100644 roms/ipxe/src/include/ipxe/bigint.h create mode 100644 roms/ipxe/src/include/ipxe/clientcert.h create mode 100644 roms/ipxe/src/include/ipxe/cms.h create mode 100644 roms/ipxe/src/include/ipxe/drbg.h create mode 100644 roms/ipxe/src/include/ipxe/efi/Library/BaseLib.h create mode 100644 roms/ipxe/src/include/ipxe/efi/Protocol/LoadFile.h create mode 100644 roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextInEx.h create mode 100644 roms/ipxe/src/include/ipxe/efi/efi_snp.h create mode 100644 roms/ipxe/src/include/ipxe/efi/ipxe_download.h create mode 100644 roms/ipxe/src/include/ipxe/entropy.h create mode 100644 roms/ipxe/src/include/ipxe/hash_df.h create mode 100644 roms/ipxe/src/include/ipxe/hmac_drbg.h create mode 100644 roms/ipxe/src/include/ipxe/lineconsole.h create mode 100644 roms/ipxe/src/include/ipxe/linux/linux_entropy.h create mode 100644 roms/ipxe/src/include/ipxe/linux/linux_time.h create mode 100644 roms/ipxe/src/include/ipxe/memblock.h create mode 100644 roms/ipxe/src/include/ipxe/menu.h create mode 100644 roms/ipxe/src/include/ipxe/mii.h create mode 100644 roms/ipxe/src/include/ipxe/null_entropy.h create mode 100644 roms/ipxe/src/include/ipxe/null_time.h create mode 100644 roms/ipxe/src/include/ipxe/ocsp.h create mode 100644 roms/ipxe/src/include/ipxe/pending.h create mode 100644 roms/ipxe/src/include/ipxe/random_nz.h create mode 100644 roms/ipxe/src/include/ipxe/rbg.h create mode 100644 roms/ipxe/src/include/ipxe/rootcert.h create mode 100644 roms/ipxe/src/include/ipxe/sha256.h create mode 100644 roms/ipxe/src/include/ipxe/test.h create mode 100644 roms/ipxe/src/include/ipxe/time.h create mode 100644 roms/ipxe/src/include/ipxe/validator.h create mode 100644 roms/ipxe/src/include/ipxe/version.h create mode 100644 roms/ipxe/src/include/ipxe/xferbuf.h create mode 100644 roms/ipxe/src/include/syslog.h create mode 100644 roms/ipxe/src/include/usr/imgtrust.h create mode 100644 roms/ipxe/src/include/usr/nslookup.h create mode 100644 roms/ipxe/src/include/wchar.h create mode 100644 roms/ipxe/src/interface/efi/efi_download.c create mode 100644 roms/ipxe/src/interface/efi/efi_hii.c create mode 100644 roms/ipxe/src/interface/efi/efi_snp_hii.c create mode 100644 roms/ipxe/src/interface/linux/linux_entropy.c create mode 100644 roms/ipxe/src/interface/linux/linux_time.c delete mode 100644 roms/ipxe/src/net/mii.c create mode 100644 roms/ipxe/src/net/tcp/httpcore.c create mode 100644 roms/ipxe/src/net/tcp/syslogs.c create mode 100644 roms/ipxe/src/net/validator.c create mode 100644 roms/ipxe/src/tests/aes_cbc_test.c create mode 100644 roms/ipxe/src/tests/base64_test.c create mode 100644 roms/ipxe/src/tests/bigint_test.c create mode 100644 roms/ipxe/src/tests/byteswap_test.c create mode 100644 roms/ipxe/src/tests/cbc_test.c create mode 100644 roms/ipxe/src/tests/cbc_test.h create mode 100644 roms/ipxe/src/tests/cms_test.c create mode 100644 roms/ipxe/src/tests/crc32_test.c create mode 100644 roms/ipxe/src/tests/digest_test.c create mode 100644 roms/ipxe/src/tests/digest_test.h create mode 100644 roms/ipxe/src/tests/entropy_sample.c create mode 100644 roms/ipxe/src/tests/hash_df_test.c create mode 100644 roms/ipxe/src/tests/hmac_drbg_test.c create mode 100644 roms/ipxe/src/tests/list_test.c create mode 100644 roms/ipxe/src/tests/md5_test.c create mode 100644 roms/ipxe/src/tests/ocsp_test.c create mode 100644 roms/ipxe/src/tests/pubkey_test.h create mode 100644 roms/ipxe/src/tests/rsa_test.c create mode 100644 roms/ipxe/src/tests/settings_test.c create mode 100644 roms/ipxe/src/tests/sha1_test.c create mode 100644 roms/ipxe/src/tests/sha256_test.c create mode 100644 roms/ipxe/src/tests/string_test.c create mode 100644 roms/ipxe/src/tests/tcpip_test.c create mode 100644 roms/ipxe/src/tests/test.c create mode 100644 roms/ipxe/src/tests/tests.c create mode 100644 roms/ipxe/src/tests/time_test.c create mode 100644 roms/ipxe/src/tests/x509_test.c create mode 100644 roms/ipxe/src/usr/imgtrust.c create mode 100644 roms/ipxe/src/usr/nslookup.c create mode 100755 roms/ipxe/src/util/niclist.pl mode change 100644 => 100755 roms/ipxe/src/util/parserom.pl create mode 100755 roms/ipxe/src/util/romcheck.pl create mode 100644 roms/openbios/config/xml/fcode.xsl create mode 100644 roms/openbios/drivers/tcx.fs create mode 100644 roms/openbios/drivers/vga.fs create mode 100644 roms/openbios/forth/lib/locals.fs create mode 100644 roms/openbios/include/libopenbios/bootcode_load.h delete mode 100644 roms/openbios/include/libopenbios/console.h create mode 100644 roms/openbios/include/libopenbios/video.h create mode 100644 roms/openbios/libopenbios/bootcode_load.c delete mode 100644 roms/openbios/libopenbios/console_common.c create mode 100644 roms/openbios/libopenbios/video_common.c create mode 100644 roms/openbios/packages/molvideo.c delete mode 100644 roms/openbios/packages/video.c create mode 100644 roms/seabios/src/acpi-dsdt-cpu-hotplug.dsl create mode 100644 roms/seabios/src/acpi-dsdt-dbug.dsl create mode 100644 roms/seabios/src/acpi-dsdt-hpet.dsl create mode 100644 roms/seabios/src/acpi-dsdt-isa.dsl create mode 100644 roms/seabios/src/acpi-dsdt-pci-crs.dsl create mode 100644 roms/seabios/src/dev-q35.h create mode 100644 roms/seabios/src/q35-acpi-dsdt.dsl (limited to 'roms') diff --git a/roms/Makefile b/roms/Makefile index 5e645bc7d..7a228aed8 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -1,5 +1,30 @@ vgabios_variants := stdvga cirrus vmware qxl +pxerom_variants := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio + +pxe-rom-e1000 efi-rom-e1000 : VID := 8086 +pxe-rom-e1000 efi-rom-e1000 : DID := 100e +pxe-rom-eepro100 efi-rom-eepro100 : VID := 8086 +pxe-rom-eepro100 efi-rom-eepro100 : DID := 1209 +pxe-rom-ne2k_pci efi-rom-ne2k_pci : VID := 1050 +pxe-rom-ne2k_pci efi-rom-ne2k_pci : DID := 0940 +pxe-rom-pcnet efi-rom-pcnet : VID := 1022 +pxe-rom-pcnet efi-rom-pcnet : DID := 2000 +pxe-rom-rtl8139 efi-rom-rtl8139 : VID := 10ec +pxe-rom-rtl8139 efi-rom-rtl8139 : DID := 8139 +pxe-rom-virtio efi-rom-virtio : VID := 1af4 +pxe-rom-virtio efi-rom-virtio : DID := 1000 + +# +# EfiRom utility is shipped with edk2 / tianocore, in BaseTools/ +# +# We need that to combine multiple images (legacy bios, +# efi ia32, efi x64) into a single rom binary. +# +# We try to find it in the path. You can also pass the location on +# the command line, i.e. "make EFIROM=/path/to/EfiRom efirom" +# +EFIROM ?= $(shell which EfiRom 2>/dev/null) default: @echo "nothing is build by default" @@ -7,6 +32,9 @@ default: @echo " bios -- update bios.bin (seabios)" @echo " seavgabios -- update vgabios binaries (seabios)" @echo " lgplvgabios -- update vgabios binaries (lgpl)" + @echo " pxerom -- update nic roms (bios only)" + @echo " efirom -- update nic roms (bios+efi, this needs" + @echo " the EfiRom utility from edk2 / tianocore)" bios: config.seabios sh configure-seabios.sh $< @@ -26,3 +54,24 @@ lgplvgabios: $(patsubst %,lgplvgabios-%,$(vgabios_variants)) lgplvgabios-%: make -C vgabios vgabios-$*.bin cp vgabios/VGABIOS-lgpl-latest.$*.bin ../pc-bios/vgabios-$*.bin + +pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants)) + +pxe-rom-%: ipxe/src/config/local/general.h + make -C ipxe/src bin/$(VID)$(DID).rom + cp ipxe/src/bin/$(VID)$(DID).rom ../pc-bios/pxe-$*.rom + +efirom: $(patsubst %,efi-rom-%,$(pxerom_variants)) + +efi-rom-%: ipxe/src/config/local/general.h + make -C ipxe/src bin/$(VID)$(DID).rom + make -C ipxe/src bin-i386-efi/$(VID)$(DID).efidrv + make -C ipxe/src bin-x86_64-efi/$(VID)$(DID).efidrv + $(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \ + -b ipxe/src/bin/$(VID)$(DID).rom \ + -ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \ + -ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \ + -o ../pc-bios/efi-$*.rom + +ipxe/src/config/local/%: config.ipxe.% + cp $< $@ diff --git a/roms/SLOF/.gitignore b/roms/SLOF/.gitignore index 861289b84..802365c2e 100644 --- a/roms/SLOF/.gitignore +++ b/roms/SLOF/.gitignore @@ -3,4 +3,12 @@ *.a *.dep *.depend - +*.bin +*.elf +*~ +/.target +board.code +dict.xt +build_info.img +paflof +paflof.unstripped diff --git a/roms/SLOF/board-js2x/llfw/u4mem.c b/roms/SLOF/board-js2x/llfw/u4mem.c index 17fa857ec..68bba56df 100644 --- a/roms/SLOF/board-js2x/llfw/u4mem.c +++ b/roms/SLOF/board-js2x/llfw/u4mem.c @@ -81,7 +81,7 @@ static const uint32_t SUBVER = 1; #define CLK_DDR_CLK_MSK (IBIT(11) | IBIT(12) | IBIT(13)) /* - * memory controler registers + * memory controller registers */ #define RASTimer0_R u4reg(0x2030) #define RASTimer1_R u4reg(0x2040) @@ -2210,7 +2210,7 @@ u4_auto_calib_MemBus( auto_calib_t *f_ac_pt ) l_Ver_u32 /= n; /* - * set appropiate vernier register for + * set appropriate vernier register for * the current bytelane */ bidx = ( b >> 2 ); @@ -2384,7 +2384,7 @@ u4_InitialScrub( void ) /* * RND: calculates Timer cycles from the given frequency - * devided by the clock frequency. Values are rounded + * divided by the clock frequency. Values are rounded * up to the nearest integer value if the division is not even. */ #define RND( tXXX ) ( ( ( tXXX ) + tCK - 1 ) / tCK ) diff --git a/roms/SLOF/board-js2x/slof/OF.fs b/roms/SLOF/board-js2x/slof/OF.fs index 044a0c8ff..33a98b6aa 100644 --- a/roms/SLOF/board-js2x/slof/OF.fs +++ b/roms/SLOF/board-js2x/slof/OF.fs @@ -154,7 +154,7 @@ THEN takeover? IF - \ potentially comming from phype + \ potentially coming from phype u4? IF \ takeover on JS21 is using some nvram area \ which might be available diff --git a/roms/SLOF/board-js2x/slof/ht.fs b/roms/SLOF/board-js2x/slof/ht.fs index e122a0398..8f818a825 100644 --- a/roms/SLOF/board-js2x/slof/ht.fs +++ b/roms/SLOF/board-js2x/slof/ht.fs @@ -59,7 +59,7 @@ f2000000 CONSTANT my-puid : config-dump ( addr size -- ) ['] config-l@ 4 (dump) ; -\ 16MB of configuration space, seperate for type 0 and type 1. +\ 16MB of configuration space, separate for type 0 and type 1. 00000000 encode-int f2000000 encode-int+ 00000000 encode-int+ 02000000 encode-int+ s" reg" property diff --git a/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs b/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs index 84561c40c..9f7d8c279 100644 --- a/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs +++ b/roms/SLOF/board-js2x/slof/pci-device_1002_515e.fs @@ -391,10 +391,10 @@ pllwriteoff _color h# B4 reg-rl! ; -: SET-COLORS ( addr index #indicies -- ) +: SET-COLORS ( addr index #indices -- ) swap h# B0 pc! - ( addr #indicies ) 0 ?do dup ( index ) i 3 * + DO-COLOR loop + ( addr #indices ) 0 ?do dup ( index ) i 3 * + DO-COLOR loop ( addr ) drop ; : init-card diff --git a/roms/SLOF/board-qemu/config b/roms/SLOF/board-qemu/config index 63976a078..a381f19a4 100644 --- a/roms/SLOF/board-qemu/config +++ b/roms/SLOF/board-qemu/config @@ -1,6 +1,6 @@ BOARD=qemu TARG=ppc64 -export FLAG="-DDISABLE_NVRAM" +export FLAG=-DRTAS_NVRAM export CPUARCH=ppcp7 export CPUARCHDEF=-DCPU_PPCP7 #export SNK_BIOSEMU_APPS=1 diff --git a/roms/SLOF/board-qemu/include/southbridge.h b/roms/SLOF/board-qemu/include/southbridge.h index 3ca4e048a..1cdb422c0 100644 --- a/roms/SLOF/board-qemu/include/southbridge.h +++ b/roms/SLOF/board-qemu/include/southbridge.h @@ -13,7 +13,6 @@ /* Not used */ #define SB_NVRAM_adr 0 #define SB_FLASH_adr 0 -#define NVRAM_LENGTH 0x10000 #define FLASH_LENGTH 0 #define SB_MAILBOX_adr 0 diff --git a/roms/SLOF/board-qemu/llfw/Makefile b/roms/SLOF/board-qemu/llfw/Makefile index e40472c5f..89f17f80f 100644 --- a/roms/SLOF/board-qemu/llfw/Makefile +++ b/roms/SLOF/board-qemu/llfw/Makefile @@ -14,7 +14,7 @@ include ../../make.rules CPPFLAGS = -I$(INCLBRDDIR) -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) \ -I$(LIBCMNDIR)/libc/include -CFLAGS += -fno-builtin $(CPPFLAGS) -O2 -msoft-float $(MAMBO) +CFLAGS += -fno-builtin $(FLAG) $(CPPFLAGS) -O2 -msoft-float $(MAMBO) CFLAGS += $(BOOT) $(IOCONF) -Wa,-mregnames $(RELEASE) $(CPUARCHDEF) -Wall ASFLAGS = $(BOOT) $(IOCONF) $(RELEASE)$(CPUARCHDEF) -Wa,-mregnames LDFLAGS1 = -nostdlib -e__start -Tstage2.lds -N -Ttext=0x100 diff --git a/roms/SLOF/board-qemu/slof/.gitignore b/roms/SLOF/board-qemu/slof/.gitignore new file mode 100644 index 000000000..55268aa6a --- /dev/null +++ b/roms/SLOF/board-qemu/slof/.gitignore @@ -0,0 +1 @@ +OF.ffs diff --git a/roms/SLOF/board-qemu/slof/Makefile b/roms/SLOF/board-qemu/slof/Makefile index 07d491690..036ad6100 100644 --- a/roms/SLOF/board-qemu/slof/Makefile +++ b/roms/SLOF/board-qemu/slof/Makefile @@ -63,6 +63,7 @@ VIO_FFS_FILES = \ $(SLOFBRDDIR)/vio-vscsi.fs \ $(SLOFBRDDIR)/vio-vscsi-device.fs \ $(SLOFBRDDIR)/vio-veth.fs \ + $(SLOFBRDDIR)/rtas-nvram.fs \ $(SLOFBRDDIR)/virtio-net.fs \ $(SLOFBRDDIR)/virtio-block.fs \ $(SLOFBRDDIR)/virtio-fs.fs diff --git a/roms/SLOF/board-qemu/slof/qemu-bootlist.fs b/roms/SLOF/board-qemu/slof/qemu-bootlist.fs index 6b52b9701..0a1aaf304 100644 --- a/roms/SLOF/board-qemu/slof/qemu-bootlist.fs +++ b/roms/SLOF/board-qemu/slof/qemu-bootlist.fs @@ -16,11 +16,15 @@ defer add-boot-device : qemu-read-bootlist ( -- ) 0 0 set-boot-device - \ check nvram - " boot-device" evaluate swap drop 0 <> IF EXIT THEN - - \ check qemu boot list - " qemu,boot-device" get-chosen not IF EXIT THEN + " qemu,boot-device" get-chosen not IF + \ No boot list set from qemu, so check nvram + " boot-device" evaluate swap drop 0= IF + \ Not set in nvram too, set default disk/cdrom alias + " disk" add-boot-device + " cdrom" add-boot-device + THEN + EXIT + THEN 0 ?DO dup i + c@ CASE diff --git a/roms/SLOF/board-qemu/slof/rtas-nvram.fs b/roms/SLOF/board-qemu/slof/rtas-nvram.fs new file mode 100644 index 000000000..fdebfb239 --- /dev/null +++ b/roms/SLOF/board-qemu/slof/rtas-nvram.fs @@ -0,0 +1,48 @@ +\ ***************************************************************************** +\ * Copyright (c) 2012 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + +." Populating " pwd cr + +0 VALUE my-nvram-fetch +0 VALUE my-nvram-store +0 VALUE my-nvram-size +0 VALUE nvram-addr + +: open true ; +: close ; + +: write ( adr len -- actual ) + nip +; + +: read ( adr len -- actual ) + nip +; + +: setup-alias + " nvram" find-alias 0= IF + " nvram" get-node node>path set-alias + ELSE + drop + THEN +; + +" #bytes" get-node get-package-property 0= IF + decode-int to my-nvram-size 2drop + " nvram-fetch" rtas-get-token to my-nvram-fetch + " nvram-store" rtas-get-token to my-nvram-store + my-nvram-size to nvram-size + nvram-size alloc-mem to nvram-addr + my-nvram-fetch my-nvram-store nvram-size nvram-addr internal-nvram-init +THEN + +setup-alias diff --git a/roms/SLOF/board-qemu/slof/tree.fs b/roms/SLOF/board-qemu/slof/tree.fs index 533fc9580..d00f5af0d 100644 --- a/roms/SLOF/board-qemu/slof/tree.fs +++ b/roms/SLOF/board-qemu/slof/tree.fs @@ -80,6 +80,9 @@ include fbuffer.fs 2dup " IBM,l-lan" strequal IF " vio-veth.fs" included THEN + 2dup " qemu,spapr-nvram" strequal IF + " rtas-nvram.fs" included + THEN 2drop THEN peer diff --git a/roms/SLOF/board-qemu/slof/vio-vscsi.fs b/roms/SLOF/board-qemu/slof/vio-vscsi.fs index f3f1fc1a3..4b49bdaa8 100644 --- a/roms/SLOF/board-qemu/slof/vio-vscsi.fs +++ b/roms/SLOF/board-qemu/slof/vio-vscsi.fs @@ -593,6 +593,14 @@ CREATE sector d# 512 allot 8 CONSTANT #dev +: vscsi-read-lun ( addr -- lun true | false ) + dup c@ C0 AND CASE + 40 OF w@-be 3FFF AND TRUE ENDOF + 0 OF w@-be TRUE ENDOF + dup dup OF ." Unsupported LUN format = " . cr FALSE ENDOF + ENDCASE +; + : vscsi-report-luns ( -- array ndev ) \ array of pointers, up to 8 devices #dev 3 << alloc-mem dup @@ -606,7 +614,11 @@ CREATE sector d# 512 allot dup rot 0 fill ( devarray devcur ndev lunarray size mem ) dup >r swap move r> ( devarray devcur ndev mem ) dup sector l@ 3 >> 0 DO ( devarray devcur ndev mem memcur ) - dup dup x@ j 8 << 8000 or or 30 << swap x! 8 + + dup dup vscsi-read-lun IF + j 8 << 8000 or or 30 << swap x! 8 + + ELSE + 2drop + THEN LOOP drop rot ( devarray ndev mem devcur ) dup >r x! r> 8 + ( devarray ndev devcur ) @@ -619,11 +631,11 @@ CREATE sector d# 512 allot : vscsi-find-disks ( -- ) ." VSCSI: Looking for devices" cr vscsi-report-luns - 0 DO + 0 ?DO dup x@ BEGIN dup x@ - dup 0= IF drop FALSE ELSE + dup 0= IF drop TRUE ELSE set-target wrapped-inquiry IF ." " current-target (u.) type ." " \ XXX FIXME: Check top bits to ignore unsupported units @@ -638,7 +650,7 @@ CREATE sector d# 512 allot ENDCASE sector .inquiry-text cr THEN - 8 + TRUE + 8 + FALSE THEN UNTIL drop 8 + @@ -671,4 +683,12 @@ scsi-close r> to my-self ; +\ Create a dummy "disk" node with no unit for the sake of +\ the SLES11 installer. It is -not- a fully functional node +\ you can open to access a disk at this stage +new-device +s" disk" device-name +s" block" device-type +finish-device + vscsi-init-and-scan diff --git a/roms/SLOF/board-qemu/virtio-net/vn-pci.c b/roms/SLOF/board-qemu/virtio-net/vn-pci.c index 0eb009104..bd2054595 100644 --- a/roms/SLOF/board-qemu/virtio-net/vn-pci.c +++ b/roms/SLOF/board-qemu/virtio-net/vn-pci.c @@ -33,7 +33,7 @@ /** * Module init for virtio via PCI. - * Checks whether we're reponsible for the given device and set up + * Checks whether we're responsible for the given device and set up * the virtqueue configuration. */ int diff --git a/roms/SLOF/clients/.gitignore b/roms/SLOF/clients/.gitignore new file mode 100644 index 000000000..c5c20bfab --- /dev/null +++ b/roms/SLOF/clients/.gitignore @@ -0,0 +1,3 @@ +*.client +*/client +*/client.unstripped diff --git a/roms/SLOF/clients/net-snk/app/biosemu/biosemu.c b/roms/SLOF/clients/net-snk/app/biosemu/biosemu.c index 8d36de63e..82a763acf 100644 --- a/roms/SLOF/clients/net-snk/app/biosemu/biosemu.c +++ b/roms/SLOF/clients/net-snk/app/biosemu/biosemu.c @@ -327,7 +327,7 @@ biosemu(char argc, char **argv) // indicating that the initialization probably was successful if ((pop_word() == 0xf4f4) && (M.x86.R_SS == STACK_SEGMENT) && (M.x86.R_SP == STACK_START_OFFSET)) { - DEBUG_PRINTF("Stack is clean, initialization successfull!\n"); + DEBUG_PRINTF("Stack is clean, initialization successful!\n"); } else { DEBUG_PRINTF ("Stack unclean, initialization probably NOT COMPLETE!!!\n"); diff --git a/roms/SLOF/clients/net-snk/app/biosemu/io.c b/roms/SLOF/clients/net-snk/app/biosemu/io.c index 5cc1ad742..3092c224c 100644 --- a/roms/SLOF/clients/net-snk/app/biosemu/io.c +++ b/roms/SLOF/clients/net-snk/app/biosemu/io.c @@ -83,7 +83,7 @@ my_inb(X86EMU_pioAddr addr) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, addr); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -132,7 +132,7 @@ my_inw(X86EMU_pioAddr addr) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, addr); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -177,7 +177,7 @@ my_inl(X86EMU_pioAddr addr) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, addr); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -223,7 +223,7 @@ my_outb(X86EMU_pioAddr addr, uint8_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -255,7 +255,7 @@ my_outw(X86EMU_pioAddr addr, uint16_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -296,7 +296,7 @@ my_outl(X86EMU_pioAddr addr, uint32_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access Device I/O (BAR or Legacy...) + //translation successful, access Device I/O (BAR or Legacy...) DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); diff --git a/roms/SLOF/clients/net-snk/app/biosemu/mem.c b/roms/SLOF/clients/net-snk/app/biosemu/mem.c index b214a96da..3a62c960e 100644 --- a/roms/SLOF/clients/net-snk/app/biosemu/mem.c +++ b/roms/SLOF/clients/net-snk/app/biosemu/mem.c @@ -177,7 +177,7 @@ my_rdb(uint32_t addr) uint8_t translated = dev_translate_address(&translated_addr); uint8_t rval; if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n", __FUNCTION__, addr); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -209,7 +209,7 @@ my_rdw(uint32_t addr) uint8_t translated = dev_translate_address(&translated_addr); uint16_t rval; if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n", __FUNCTION__, addr); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -260,7 +260,7 @@ my_rdl(uint32_t addr) uint8_t translated = dev_translate_address(&translated_addr); uint32_t rval; if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%x): access to VGA Memory\n", __FUNCTION__, addr); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -322,7 +322,7 @@ my_wrb(uint32_t addr, uint8_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -347,7 +347,7 @@ my_wrw(uint32_t addr, uint16_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); @@ -392,7 +392,7 @@ my_wrl(uint32_t addr, uint32_t val) uint64_t translated_addr = addr; uint8_t translated = dev_translate_address(&translated_addr); if (translated != 0) { - //translation successfull, access VGA Memory (BAR or Legacy...) + //translation successful, access VGA Memory (BAR or Legacy...) DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n", __FUNCTION__, addr, val); //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); diff --git a/roms/SLOF/clients/net-snk/app/biosemu/vbe.c b/roms/SLOF/clients/net-snk/app/biosemu/vbe.c index 61b710264..f9618b460 100644 --- a/roms/SLOF/clients/net-snk/app/biosemu/vbe.c +++ b/roms/SLOF/clients/net-snk/app/biosemu/vbe.c @@ -111,7 +111,7 @@ vbe_prepare() M.x86.R_EDI = 0x0; M.x86.R_ES = VBE_SEGMENT; - return 0; // successfull init + return 0; // successful init } // VBE Function 00h diff --git a/roms/SLOF/clients/net-snk/app/netapps/args.c b/roms/SLOF/clients/net-snk/app/netapps/args.c index 72cf0ea26..52215e6a7 100644 --- a/roms/SLOF/clients/net-snk/app/netapps/args.c +++ b/roms/SLOF/clients/net-snk/app/netapps/args.c @@ -19,8 +19,8 @@ /** * Returns pointer of the n'th argument within a string. * - * @param arg_str string with arguments, seperated with ',' - * @param index index of the requested arguments whithin arg_str + * @param arg_str string with arguments, separated with ',' + * @param index index of the requested arguments within arg_str * @return pointer of argument[index] on success * NULL if index is out of range */ @@ -41,7 +41,7 @@ get_arg_ptr(const char *arg_str, unsigned int index) /** * Returns number of arguments within a string. * - * @param arg_str string with arguments, seperated with ',' + * @param arg_str string with arguments, separated with ',' * @return number of arguments */ unsigned int @@ -57,7 +57,7 @@ get_args_count(const char *arg_str) /** * Returns the length of the first argument. * - * @param arg_str string with arguments, seperated with ',' + * @param arg_str string with arguments, separated with ',' * @return length of first argument */ unsigned int @@ -74,8 +74,8 @@ get_arg_length(const char *arg_str) * Copy the n'th argument within a string into a buffer in respect * to a limited buffer size * - * @param arg_str string with arguments, seperated with ',' - * @param index index of the requested arguments whithin arg_str + * @param arg_str string with arguments, separated with ',' + * @param index index of the requested arguments within arg_str * @param buffer pointer to the buffer * @param length size of the buffer * @return pointer of buffer on success diff --git a/roms/SLOF/clients/net-snk/app/netapps/netboot.c b/roms/SLOF/clients/net-snk/app/netapps/netboot.c index aa4df11b9..952bb3315 100644 --- a/roms/SLOF/clients/net-snk/app/netapps/netboot.c +++ b/roms/SLOF/clients/net-snk/app/netapps/netboot.c @@ -55,7 +55,7 @@ typedef struct { * Parses a argument string for IPv6 booting, extracts all * parameters and fills a structure accordingly * - * @param arg_str string with arguments, seperated with ',' + * @param arg_str string with arguments, separated with ',' * @param argc number of arguments * @param obp_tftp_args structure which contains the result * @return updated arg_str @@ -144,7 +144,7 @@ parse_ipv6args (const char *arg_str, unsigned int argc, * Parses a argument string for IPv4 booting, extracts all * parameters and fills a structure accordingly * - * @param arg_str string with arguments, seperated with ',' + * @param arg_str string with arguments, separated with ',' * @param argc number of arguments * @param obp_tftp_args structure which contains the result * @return updated arg_str @@ -232,7 +232,7 @@ parse_ipv4args (const char *arg_str, unsigned int argc, * Netload-Parameters: * [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries * - * @param arg_str string with arguments, seperated with ',' + * @param arg_str string with arguments, separated with ',' * @param obp_tftp_args structure which contains the result * @return none */ diff --git a/roms/SLOF/clients/net-snk/app/netlib/dhcp.c b/roms/SLOF/clients/net-snk/app/netlib/dhcp.c index 8f81bf319..b00f0497b 100644 --- a/roms/SLOF/clients/net-snk/app/netlib/dhcp.c +++ b/roms/SLOF/clients/net-snk/app/netlib/dhcp.c @@ -177,7 +177,7 @@ static char * response_buffer; * DHCP: Obtains IP and configuration info from DHCP server * (makes several attempts). * - * @param boot_device a socket number used to send and recieve packets + * @param boot_device a socket number used to send and receive packets * @param fn_ip contains the following configuration information: * client MAC, client IP, TFTP-server MAC, * TFTP-server IP, Boot file name @@ -292,7 +292,7 @@ dhcp_attempt(void) { * * @param opt_field Points to the "vend" field of DHCP-message * (destination) - * @param opt_struct this structure stores info about the options wich + * @param opt_struct this structure stores info about the options which * will be added to DHCP-message (source) * @return TRUE - options packed; * FALSE - error condition occurs. @@ -387,7 +387,7 @@ dhcp_encode_options(uint8_t * opt_field, dhcp_options_t * opt_struct) { * @param opt_field Points to the "options" field of DHCP-message * (source). * @param opt_len Length of "options" field. - * @param opt_struct this structure stores info about the options wich + * @param opt_struct this structure stores info about the options which * was extracted from DHCP-message (destination). * @return TRUE - options extracted; * FALSE - error condition occurs. @@ -527,13 +527,13 @@ static int8_t dhcp_merge_options(uint8_t dst_options[], uint32_t * dst_len, } /** - * DHCP: Finds given occurence of the option with the given code (op_code) + * DHCP: Finds given occurrence of the option with the given code (op_code) * in "options" field of DHCP-message. * * @param options "options" field of DHCP-message * @param len length of the "options" field * @param op_code code of the option to find - * @param op_offset SUCCESS - offset to an option occurence; + * @param op_offset SUCCESS - offset to an option occurrence; * FAULT - offset is set to zero. * @return TRUE - option was find; * FALSE - option wasn't find. @@ -582,7 +582,7 @@ dhcp_append_option(uint8_t dst_options[], uint32_t * dst_len, * * @param dst_options "options" field of DHCP-message * @param dst_len length of the "options" field (modified) - * @param dst_offset offset of the option from beggining of the list + * @param dst_offset offset of the option from beginning of the list * @param new_option points to an option in another list (src) */ static void diff --git a/roms/SLOF/clients/net-snk/app/netlib/dns.c b/roms/SLOF/clients/net-snk/app/netlib/dns.c index 5a931d5a6..4acc08075 100644 --- a/roms/SLOF/clients/net-snk/app/netlib/dns.c +++ b/roms/SLOF/clients/net-snk/app/netlib/dns.c @@ -93,7 +93,7 @@ static int8_t dns_domain_cname[0x100]; /**< Canonical domain name */ * DNS: Initialize the environment for DNS client. * To perfrom DNS-queries use the function dns_get_ip. * - * @param device_socket a socket number used to send and recieve packets + * @param device_socket a socket number used to send and receive packets * @param server_ip DNS-server IPv4 address (e.g. 127.0.0.1) * @return TRUE in case of successful initialization; * FALSE in case of fault (e.g. can't obtain MAC). @@ -144,7 +144,7 @@ dns_get_ip(int8_t * url, uint32_t * domain_ip) { return 0; } - // Check if DNS server is presented and accessable + // Check if DNS server is presented and accessible if (dns_server_ip == 0) { printf("\nERROR:\t\t\tCan't resolve domain name " "(DNS server is not presented)!\n"); @@ -183,7 +183,7 @@ dns_get_ip(int8_t * url, uint32_t * domain_ip) { /** * DNS: Handles DNS-messages according to Receive-handle diagram. * Sets dns_result_ip for given dns_domain_name (see dns_get_ip) - * or signals error condition occurs during DNS-resolving proccess + * or signals error condition occurs during DNS-resolving process * by setting dns_error flag. * * @param packet DNS-packet to be handled @@ -266,7 +266,7 @@ handle_dns(uint8_t * packet, int32_t packetsize) { resp_section += htons(* (uint16_t *) (resp_section + 8)) + 10; } } - return 0; // Packet succesfuly handled but IP wasn't obtained + return 0; // Packet successfully handled but IP wasn't obtained } /** diff --git a/roms/SLOF/clients/net-snk/app/netlib/ipv4.c b/roms/SLOF/clients/net-snk/app/netlib/ipv4.c index df18970e0..e55b58233 100644 --- a/roms/SLOF/clients/net-snk/app/netlib/ipv4.c +++ b/roms/SLOF/clients/net-snk/app/netlib/ipv4.c @@ -398,10 +398,10 @@ handle_ipv4(uint8_t * ip_packet, int32_t packetsize) * - IPv4 checksum is calculaded. * - If payload type is UDP, then the UDP checksum is calculated also. * - * We sent an ARP request first, if this is the first packet sent to + * We send an ARP request first, if this is the first packet sent to * the declared IPv4 destination address. In this case we store the - * the packet and sent it later if we receive the ARP response. - * If the MAC address is known already, then we send the packet immediatly. + * the packet and send it later if we receive the ARP response. + * If the MAC address is known already, then we send the packet immediately. * If there is already an ARP request pending, then we drop this packet * and send again an ARP request. * diff --git a/roms/SLOF/clients/net-snk/app/netlib/tftp.c b/roms/SLOF/clients/net-snk/app/netlib/tftp.c index dd1e752fd..f58df18c6 100644 --- a/roms/SLOF/clients/net-snk/app/netlib/tftp.c +++ b/roms/SLOF/clients/net-snk/app/netlib/tftp.c @@ -535,7 +535,7 @@ tftp(filename_ip_t * _fn_ip, unsigned char *_buffer, int _len, * which do not support the RRQ blocksize option */ blocksize = 512; - /* Prefered blocksize - used as option for the read request */ + /* Preferred blocksize - used as option for the read request */ if (_blocksize < 8) _blocksize = 8; else if (_blocksize > MAX_BLOCKSIZE) diff --git a/roms/SLOF/clients/net-snk/kernel/modules.c b/roms/SLOF/clients/net-snk/kernel/modules.c index a719f274e..e7f8cbb5f 100644 --- a/roms/SLOF/clients/net-snk/kernel/modules.c +++ b/roms/SLOF/clients/net-snk/kernel/modules.c @@ -91,7 +91,7 @@ load_module(const char *name) } } if(i == MODULES_MAX) { - // no space avaliable! + // no space available! return -3; } diff --git a/roms/SLOF/clients/net-snk/kernel/systemcall.c b/roms/SLOF/clients/net-snk/kernel/systemcall.c index b63df52d7..644f459da 100644 --- a/roms/SLOF/clients/net-snk/kernel/systemcall.c +++ b/roms/SLOF/clients/net-snk/kernel/systemcall.c @@ -40,7 +40,7 @@ _syscall_open(const char* name, int flags) } if(fd == FILEIO_MAX) { printk ("Can not open \"%s\" because file descriptor list is full\n", name); - /* there is no free file descriptor avaliable */ + /* there is no free file descriptor available */ return -2; } diff --git a/roms/SLOF/clients/net-snk/kernel/timer.c b/roms/SLOF/clients/net-snk/kernel/timer.c index 0b8a18ff3..1d5ae1652 100644 --- a/roms/SLOF/clients/net-snk/kernel/timer.c +++ b/roms/SLOF/clients/net-snk/kernel/timer.c @@ -54,7 +54,7 @@ static void wait_ticks(uint64_t ticks) // wait for (at least) usecs microseconds void udelay(unsigned int usecs) { - // first multiply the usec with timebase and then devide + // first multiply the usec with timebase and then divide // because 1.000.000 is relatively huge compared to usecs wait_ticks((usecs*tb_freq)/1000000); } @@ -63,7 +63,7 @@ void udelay(unsigned int usecs) // wait for (at least) msecs milliseconds void mdelay(unsigned int msecs) { - // first multiply the msec and timebase and then devide + // first multiply the msec and timebase and then divide // because 1.000 is relatively huge compared to msecs wait_ticks((msecs*tb_freq)/1000); } diff --git a/roms/SLOF/drivers/bcm57xx/bcm57xx.c b/roms/SLOF/drivers/bcm57xx/bcm57xx.c index 65b319b9d..fa9616392 100644 --- a/roms/SLOF/drivers/bcm57xx/bcm57xx.c +++ b/roms/SLOF/drivers/bcm57xx/bcm57xx.c @@ -2647,7 +2647,7 @@ bcm_init( void ) // step 40/41/42: initialize rx producer ring bcm_init_rxprod_ring(); - // step 43: set rx producer ring replenish threshhold + // step 43: set rx producer ring replenish threshold // using recommended setting of maximum allocated BD's/8 bcm_write_reg32( STD_RXPR_REP_THR_R, (u32_t) BCM_MAX_RX_BUF / 8 ); diff --git a/roms/SLOF/drivers/bcm57xx/bcm57xx.h b/roms/SLOF/drivers/bcm57xx/bcm57xx.h index d968313ed..0f59262fb 100644 --- a/roms/SLOF/drivers/bcm57xx/bcm57xx.h +++ b/roms/SLOF/drivers/bcm57xx/bcm57xx.h @@ -140,7 +140,7 @@ #define RX_DAT_COMPL_MODE_R ( (u16_t) 0x2800 ) // Receive BD Initiator Mode register #define RX_BD_INIT_MODE_R ( (u16_t) 0x2c00 ) -// Standard Receive Producer Ring Replenish Threshhold register +// Standard Receive Producer Ring Replenish Threshold register #define STD_RXPR_REP_THR_R ( (u16_t) 0x2c18 ) // Receive BD Completion Mode register #define RX_BD_COMPL_MODE_R ( (u16_t) 0x3000 ) @@ -172,7 +172,7 @@ #define STB_HOST_ADDR_HI_R ( (u16_t) 0x3c38 ) // Status Block Host Address High register #define STB_HOST_ADDR_LO_R ( (u16_t) 0x3c3c ) -// Statistsics Base Adress register +// Statistics Base Address register #define STAT_NIC_ADDR_R ( (u16_t) 0x3c40 ) // Status Block Base Address register #define STB_NIC_ADDR_R ( (u16_t) 0x3c44 ) diff --git a/roms/SLOF/drivers/e1k/e1k.c b/roms/SLOF/drivers/e1k/e1k.c index 38a998786..a606b713a 100644 --- a/roms/SLOF/drivers/e1k/e1k.c +++ b/roms/SLOF/drivers/e1k/e1k.c @@ -474,7 +474,7 @@ e1k_init_transmitter(void) */ e1k_wr32(TCTL, BIT32(1) | // enable transmitter BIT32(3) | // pad short packets - ((uint32_t) 0x0f << 4) | // collision threshhold + ((uint32_t) 0x0f << 4) | // collision threshold ((uint32_t) 0x40 << 12)); // collision distance } diff --git a/roms/SLOF/include/byteorder.h b/roms/SLOF/include/byteorder.h index 0d7ebee0c..29910afb1 100644 --- a/roms/SLOF/include/byteorder.h +++ b/roms/SLOF/include/byteorder.h @@ -11,7 +11,7 @@ *****************************************************************************/ /* - * Common byteorder (endianess) macros + * Common byteorder (endianness) macros */ #ifndef BYTEORDER_H diff --git a/roms/SLOF/lib/libbases/libbases.code b/roms/SLOF/lib/libbases/libbases.code index 7dc941d5b..45312e2fa 100644 --- a/roms/SLOF/lib/libbases/libbases.code +++ b/roms/SLOF/lib/libbases/libbases.code @@ -20,7 +20,7 @@ MIRP // : get-nvram-size ( -- size ) PRIM(get_X2d_nvram_X2d_size) PUSH; - TOS.u = NVRAM_LENGTH; + TOS.u = get_nvram_size(); MIRP // : get-flash-base ( -- base ) diff --git a/roms/SLOF/lib/libbootmsg/bootmsg_lvl.S b/roms/SLOF/lib/libbootmsg/bootmsg_lvl.S index 65cf0c345..2e4c1359a 100644 --- a/roms/SLOF/lib/libbootmsg/bootmsg_lvl.S +++ b/roms/SLOF/lib/libbootmsg/bootmsg_lvl.S @@ -158,7 +158,8 @@ ENTRY(bootmsg_setlevel) andi. r3, r3, 0x7F add r6,r3,r6 // address | stb r4,0(r6) // store level |_ stwbrx r4,r3,r6 -#ifndef DISABLE_NVRAM + +#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM) LOAD64(r6, SB_NVRAM_FWONLY_adr + 8 ) add r6,r6,r3 stb r4,0(r6) @@ -167,7 +168,7 @@ ENTRY(bootmsg_setlevel) blr ENTRY(bootmsg_nvupdate) -#ifndef DISABLE_NVRAM +#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM) mflr r10 LOAD64(r3, SB_NVRAM_FWONLY_adr) lwz r4, 0(r3) diff --git a/roms/SLOF/lib/libelf/elf.c b/roms/SLOF/lib/libelf/elf.c index 0d403488c..33d92111f 100644 --- a/roms/SLOF/lib/libelf/elf.c +++ b/roms/SLOF/lib/libelf/elf.c @@ -25,7 +25,7 @@ * @param file_addr pointer to the start of the ELF file * @return the class (1 for 32 bit, 2 for 64 bit) * -1 if it is not an ELF file - * -2 if it has the wrong endianess + * -2 if it has the wrong endianness * -3 if it is not an ELF executable * -4 if it is not for PPC */ diff --git a/roms/SLOF/lib/libhvcall/libhvcall.h b/roms/SLOF/lib/libhvcall/libhvcall.h index 302e2a376..6e418bad5 100644 --- a/roms/SLOF/lib/libhvcall/libhvcall.h +++ b/roms/SLOF/lib/libhvcall/libhvcall.h @@ -70,6 +70,20 @@ static inline long h_add_logical_lan_buffer(unsigned long unit_address, return hv_generic(H_ADD_LOGICAL_LAN_BUFFER, unit_address, buffer); } +#define HV_RTAS_MAX_ARGRET 5 + +struct hv_rtas_call { + uint32_t token; + uint32_t nargs; + uint32_t nrets; + uint32_t argret[HV_RTAS_MAX_ARGRET]; +}; + +static inline unsigned long h_rtas(struct hv_rtas_call *rtas_buf) +{ + return hv_generic(KVMPPC_H_RTAS, (unsigned long)rtas_buf); +} + extern unsigned long hv_logical_ci_load(unsigned long size, unsigned long addr); extern unsigned long hv_logical_ci_store(unsigned long size, unsigned long addr, unsigned long value); diff --git a/roms/SLOF/lib/libnvram/libnvram.code b/roms/SLOF/lib/libnvram/libnvram.code index f1fd41440..723941d3e 100644 --- a/roms/SLOF/lib/libnvram/libnvram.code +++ b/roms/SLOF/lib/libnvram/libnvram.code @@ -276,4 +276,12 @@ PRIM(delete_X2d_nvram_X2d_partition) MIRP - +// ( fetch_token store_token size nvram-addr -- ) +PRIM(internal_X2d_nvram_X2d_init) + void *nvram_addr = TOS.a; POP; + uint32_t nvram_size = TOS.u; POP; + uint32_t store_token = TOS.u; POP; + long fetch_token = TOS.u; POP; + + nvram_init(fetch_token, store_token, nvram_size, nvram_addr); +MIRP diff --git a/roms/SLOF/lib/libnvram/libnvram.in b/roms/SLOF/lib/libnvram/libnvram.in index 33ab3bce7..bbb20a889 100644 --- a/roms/SLOF/lib/libnvram/libnvram.in +++ b/roms/SLOF/lib/libnvram/libnvram.in @@ -39,3 +39,4 @@ cod(internal-add-env) cod(internal-del-env) cod(internal-set-env) +cod(internal-nvram-init) diff --git a/roms/SLOF/lib/libnvram/nvram.c b/roms/SLOF/lib/libnvram/nvram.c index 048ec0fbc..2cb83dc52 100644 --- a/roms/SLOF/lib/libnvram/nvram.c +++ b/roms/SLOF/lib/libnvram/nvram.c @@ -12,6 +12,7 @@ #include "cache.h" #include "nvram.h" +#include "../libhvcall/libhvcall.h" #include #include @@ -20,9 +21,38 @@ #include #include +#ifdef RTAS_NVRAM +static uint32_t fetch_token; +static uint32_t store_token; +static uint32_t NVRAM_LENGTH; +static char *nvram_buffer; /* use buffer allocated by SLOF code */ +#else #ifndef NVRAM_LENGTH #define NVRAM_LENGTH 0x10000 #endif +/* + * This is extremely ugly, but still better than implementing + * another sbrk() around it. + */ +static char nvram_buffer[NVRAM_LENGTH]; +#endif + +static uint8_t nvram_buffer_locked=0x00; + +void nvram_init(uint32_t _fetch_token, uint32_t _store_token, + long _nvram_length, void* nvram_addr) +{ +#ifdef RTAS_NVRAM + fetch_token = _fetch_token; + store_token = _store_token; + NVRAM_LENGTH = _nvram_length; + nvram_buffer = nvram_addr; + + printf("\nNVRAM: size=%d, fetch=%x, store=%x\n", + NVRAM_LENGTH, fetch_token, store_token); +#endif +} + void asm_cout(long Character,long UART,long NVRAM); @@ -48,6 +78,46 @@ static volatile uint8_t nvram[NVRAM_LENGTH]; /* FAKE */ *pos = data; \ } +#elif defined(RTAS_NVRAM) + +static inline void nvram_fetch(unsigned int offset, void *buf, unsigned int len) +{ + struct hv_rtas_call rtas = { + .token = fetch_token, + .nargs = 3, + .nrets = 2, + .argret = { offset, (uint32_t)(unsigned long)buf, len }, + }; + h_rtas(&rtas); +} + +static inline void nvram_store(unsigned int offset, void *buf, unsigned int len) +{ + struct hv_rtas_call rtas = { + .token = store_token, + .nargs = 3, + .nrets = 2, + .argret = { offset, (uint32_t)(unsigned long)buf, len }, + }; + h_rtas(&rtas); +} + +#define nvram_access(type,size,name) \ + type nvram_read_##name(unsigned int offset) \ + { \ + type val; \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return 0; \ + nvram_fetch(offset, &val, size / 8); \ + return val; \ + } \ + void nvram_write_##name(unsigned int offset, type data) \ + { \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return; \ + nvram_store(offset, &data, size / 8); \ + } + #else /* DISABLE_NVRAM */ static volatile uint8_t *nvram = (volatile uint8_t *)SB_NVRAM_adr; @@ -83,12 +153,7 @@ nvram_access(uint16_t, 16, word) nvram_access(uint32_t, 32, dword) nvram_access(uint64_t, 64, qword) -/* - * This is extremely ugly, but still better than implementing - * another sbrk() around it. - */ -static char nvram_buffer[NVRAM_LENGTH]; -static uint8_t nvram_buffer_locked=0x00; + /** * This function is a minimal abstraction for our temporary @@ -184,7 +249,7 @@ static char * get_partition_name(int offset) for (i=0; i<12; i++) name[i]=nvram_read_byte(offset+4+i); - // DEBUG("name: \"%s\"\n", name); + DEBUG("name: \"%s\"\n", name); return name; } @@ -217,7 +282,7 @@ static int calc_used_nvram_space(void) } len=get_partition_len(walk); - // DEBUG("... part len=%x, %x\n", len, len*16); + DEBUG("... part len=%x, %x\n", len, len*16); if(!len) { /* If there's a partition type but no len, bail out. @@ -546,6 +611,13 @@ void reset_nvram(void) void nvram_debug(void) { +#ifndef RTAS_NVRAM printf("\nNVRAM_BASE: %p\n", nvram); printf("NVRAM_LEN: 0x%x\n", NVRAM_LENGTH); +#endif +} + +unsigned int get_nvram_size(void) +{ + return NVRAM_LENGTH; } diff --git a/roms/SLOF/lib/libnvram/nvram.h b/roms/SLOF/lib/libnvram/nvram.h index 1324809d4..fa6bdd425 100644 --- a/roms/SLOF/lib/libnvram/nvram.h +++ b/roms/SLOF/lib/libnvram/nvram.h @@ -60,6 +60,9 @@ int delete_nvram_partition(partition_t part); void reset_nvram(void); void wipe_nvram(void); void nvram_debug(void); +void nvram_init(uint32_t store_token, uint32_t fetch_token, + long nv_size, void* nvram_addr); +unsigned int get_nvram_size(void); /* envvar.c */ char *get_env(partition_t part, char *envvar); diff --git a/roms/SLOF/llfw/nvramlog.S b/roms/SLOF/llfw/nvramlog.S index be6bfd871..3ad2de754 100644 --- a/roms/SLOF/llfw/nvramlog.S +++ b/roms/SLOF/llfw/nvramlog.S @@ -14,8 +14,7 @@ #include #include - -#if !defined(DISABLE_NVRAM) +#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM) // detect overflow: if(aromaddr) != hdr->romaddr) { printf("BUG!!!! pad8_num(hdr->romaddr) != hdr->romaddr\n"); return -1; diff --git a/roms/SLOF/romfs/tools/create_crc.c b/roms/SLOF/romfs/tools/create_crc.c index 8ea634782..51f137d8e 100644 --- a/roms/SLOF/romfs/tools/create_crc.c +++ b/roms/SLOF/romfs/tools/create_crc.c @@ -115,7 +115,7 @@ createHeaderImage(int notime) } // length must be 13 instead 12 because of terminating // NUL. Therefore uH.stH.platform_revison must be - // writen later to overwrite the terminating NUL + // written later to overwrite the terminating NUL if (strftime(dastr, 15, "0x%Y%m%d%H%M", tm) == 0) { printf("strftime error\n"); } diff --git a/roms/SLOF/slof/fs/base.fs b/roms/SLOF/slof/fs/base.fs index da990f3af..f92fc0696 100644 --- a/roms/SLOF/slof/fs/base.fs +++ b/roms/SLOF/slof/fs/base.fs @@ -143,7 +143,7 @@ CONSTANT <2constant> then -1 +loop = ; -\ reverse split -- split at the last occurence of char +\ reverse split -- split at the last occurrence of char : rsplit ( str len char -- left len right len ) >r 2dup r> rfindchar IF >r over r@ 2swap r> 1+ /string ELSE 0 0 THEN ; @@ -221,7 +221,7 @@ CONSTANT <2constant> 1 >in +! \ advance input-index ; -\ Parse upto next " +\ Parse up to next " : parse-" ( dst-adr -- dst-adr' ) [char] " parse dup 3 pick + >r ( dst-adr str len R: dst-adr' ) diff --git a/roms/SLOF/slof/fs/debug.fs b/roms/SLOF/slof/fs/debug.fs index 0aa3acf37..e54f729fe 100644 --- a/roms/SLOF/slof/fs/debug.fs +++ b/roms/SLOF/slof/fs/debug.fs @@ -366,7 +366,7 @@ true value trace>up? : debug-off ( -- ) debug-last-xt IF - debug-last-xt-content debug-last-xt ! \ Restore overwriten token + debug-last-xt-content debug-last-xt ! \ Restore overwritten token 0 to debug-last-xt THEN ; @@ -377,7 +377,7 @@ true value trace>up? : (break-entry) ( -- ) debug-last-xt dup @ ['] breakpoint <> swap ( debug-addr? debug-last-xt ) - debug-last-xt-content swap ! \ Restore overwriten token + debug-last-xt-content swap ! \ Restore overwritten token r> drop \ Don't return to bp, but to caller debug-last-xt-content <> and IF \ Execute non colon definition debug-last-xt cr u. ." : " diff --git a/roms/SLOF/slof/fs/devices/pci-device_10de_0141.fs b/roms/SLOF/slof/fs/devices/pci-device_10de_0141.fs index dd62ca702..bb3b83516 100644 --- a/roms/SLOF/slof/fs/devices/pci-device_10de_0141.fs +++ b/roms/SLOF/slof/fs/devices/pci-device_10de_0141.fs @@ -20,7 +20,7 @@ pci-mem-enable 30 config-l@ pci-find-fcode execute-rom-fcode : check-display ( nodepath len -- true|false ) \ true if display found and "screen" alias set -\ check if display availabe, set screen alias +\ check if display available, set screen alias 2dup find-node \ ( path len phandle|0 ) find node ?dup IF \ node found, get "display-type" property diff --git a/roms/SLOF/slof/fs/dictionary.fs b/roms/SLOF/slof/fs/dictionary.fs index 5d1dae72d..3e5b29332 100644 --- a/roms/SLOF/slof/fs/dictionary.fs +++ b/roms/SLOF/slof/fs/dictionary.fs @@ -29,7 +29,7 @@ WHILE ( xt currxt *name pos ) dup @ 4 pick = IF ( xt currxt *name pos ) over count type space - BEGIN cell+ dup @ ['] semicolon = UNTIL cell - \ eat up other occurences + BEGIN cell+ dup @ ['] semicolon = UNTIL cell - \ eat up other occurrences THEN REPEAT THEN diff --git a/roms/SLOF/slof/fs/envvar.fs b/roms/SLOF/slof/fs/envvar.fs index 1d152e4b5..015e3660b 100644 --- a/roms/SLOF/slof/fs/envvar.fs +++ b/roms/SLOF/slof/fs/envvar.fs @@ -193,7 +193,7 @@ DEFER old-emit 5 OF env-secmode ENDOF ENDCASE ; -\ Enviroment variables might be board specific +\ Environment variables might be board specific #include diff --git a/roms/SLOF/slof/fs/exception.fs b/roms/SLOF/slof/fs/exception.fs index 91e39be48..dbf11fb46 100644 --- a/roms/SLOF/slof/fs/exception.fs +++ b/roms/SLOF/slof/fs/exception.fs @@ -51,7 +51,7 @@ CONSTANT ciregs-size 200 OF ." Machine Check" ENDOF 300 OF ." Data Storage" ENDOF 380 OF ." Data Segment" ENDOF - 400 OF ." Intruction Storage" ENDOF + 400 OF ." Instruction Storage" ENDOF 480 OF ." Instruction Segment" ENDOF 500 OF ." External" ENDOF 600 OF ." Alignment" ENDOF @@ -143,7 +143,7 @@ CONSTANT ciregs-size msr@ 8000 not and msr! ; -\ Generate external interrupt thru Internal Interrupt Controller of BE +\ Generate external interrupt through Internal Interrupt Controller of BE : gen-ext-int ( -- ) 7fffffff dec! \ Reset decrementer diff --git a/roms/SLOF/slof/fs/fcode/1275.fs b/roms/SLOF/slof/fs/fcode/1275.fs index 7c7e3665c..c2a67bcc9 100644 --- a/roms/SLOF/slof/fs/fcode/1275.fs +++ b/roms/SLOF/slof/fs/fcode/1275.fs @@ -33,7 +33,7 @@ dup 8000 >= IF 10000 - \ Create cell-sized negative value THEN - fcode-offset - \ IP is already behind offset, so substract offset size + fcode-offset - \ IP is already behind offset, so subtract offset size ; : ?negative diff --git a/roms/SLOF/slof/fs/ide.fs b/roms/SLOF/slof/fs/ide.fs index 93ca7660a..d6f16edd0 100644 --- a/roms/SLOF/slof/fs/ide.fs +++ b/roms/SLOF/slof/fs/ide.fs @@ -21,7 +21,7 @@ 0 VALUE >ata \ base address for command-block 0 VALUE >ata1 \ base address for control block -true VALUE no-timeout \ flag that no timeout occured +true VALUE no-timeout \ flag that no timeout occurred 0c CONSTANT #cdb-bytes \ command descriptor block (12 bytes) 800 CONSTANT atapi-size @@ -289,7 +289,7 @@ scsi-open \ add scsi functions IF cr ." packet size = 16 ** not supported ! **" THEN - no-timeout not \ any timeout occured so far ? + no-timeout not \ any timeout occurred so far ? IF cr ." ** timeout **" THEN diff --git a/roms/SLOF/slof/fs/logging.fs b/roms/SLOF/slof/fs/logging.fs index 4a31b5054..002c48091 100644 --- a/roms/SLOF/slof/fs/logging.fs +++ b/roms/SLOF/slof/fs/logging.fs @@ -15,10 +15,10 @@ defer nvramlog-write-byte : .nvramlog-write-byte ( byte -- ) -#ifndef DISABLE_NVRAM - 0 1 asm-cout -#else +#if defined(DISABLE_NVRAM) || defined(RTAS_NVRAM) drop +#else + 0 1 asm-cout #endif ; diff --git a/roms/SLOF/slof/fs/node.fs b/roms/SLOF/slof/fs/node.fs index 819593d40..95f5e1a3f 100644 --- a/roms/SLOF/slof/fs/node.fs +++ b/roms/SLOF/slof/fs/node.fs @@ -299,7 +299,7 @@ defer find-node ELSE 2drop dup IF .alias ELSE 2drop list-alias THEN THEN ; -\ sub-alias does a single iteration of an alias at the begining od dev path +\ sub-alias does a single iteration of an alias at the beginning od dev path \ expression. de-alias will repeat this until all indirect alising is resolved : sub-alias ( arg-str arg-len -- arg' len' | false ) 2dup diff --git a/roms/SLOF/slof/fs/packages/disk-label.fs b/roms/SLOF/slof/fs/packages/disk-label.fs index 97e3031e2..2dc581bef 100644 --- a/roms/SLOF/slof/fs/packages/disk-label.fs +++ b/roms/SLOF/slof/fs/packages/disk-label.fs @@ -265,7 +265,7 @@ CONSTANT /partition-entry \ Check for an ISO-9660 filesystem on the disk \ (cf. CHRP IEEE 1275 spec., chapter 11.1.2.3) : has-iso9660-filesystem ( -- TRUE|FALSE ) - \ Seek to the begining of logical 2048-byte sector 16 + \ Seek to the beginning of logical 2048-byte sector 16 \ refer to Chapter C.11.1 in PAPR 2.0 Spec \ was: 10 read-sector, but this might cause trouble if you \ try booting an ISO image from a device with 512b sectors. diff --git a/roms/SLOF/slof/fs/property.fs b/roms/SLOF/slof/fs/property.fs index c7fd46a86..cb99fbe9d 100644 --- a/roms/SLOF/slof/fs/property.fs +++ b/roms/SLOF/slof/fs/property.fs @@ -28,7 +28,7 @@ true value encode-first? : decode-int over >r 4 /string r> 4c@ swap 2swap swap bljoin ; : decode-64 decode-int -rot decode-int -rot 2swap swap lxjoin ; : decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len ) - dup 0= IF 2dup EXIT THEN \ string properties with zero lenght + dup 0= IF 2dup EXIT THEN \ string properties with zero length over BEGIN dup c@ 0= IF 1+ -rot swap 2 pick over - rot over - -rot 1- EXIT THEN 1+ AGAIN ; diff --git a/roms/SLOF/slof/fs/scsi-loader.fs b/roms/SLOF/slof/fs/scsi-loader.fs index 406c18464..fec1f78dc 100644 --- a/roms/SLOF/slof/fs/scsi-loader.fs +++ b/roms/SLOF/slof/fs/scsi-loader.fs @@ -14,7 +14,7 @@ \ Last change: MiR 13.11.2007 10:55:57 \ ************************************** -: .ansi-attr-off 1b emit ." [0m" ; \ ESC Sequence: all terminal atributes off +: .ansi-attr-off 1b emit ." [0m" ; \ ESC Sequence: all terminal attributes off : .ansi-blue 1b emit ." [34m" ; \ ESC Sequence: foreground-color = blue : .ansi-green 1b emit ." [32m" ; \ ESC Sequence: foreground-color = green : .ansi-red 1b emit ." [31m" ; \ ESC Sequence: foreground-color = green diff --git a/roms/SLOF/slof/fs/scsi-support.fs b/roms/SLOF/slof/fs/scsi-support.fs index d4b260bd5..73f905600 100644 --- a/roms/SLOF/slof/fs/scsi-support.fs +++ b/roms/SLOF/slof/fs/scsi-support.fs @@ -803,7 +803,7 @@ CONSTANT scsi-length-media-event \ **************************************************************************** \ close scsi-session and remove scsi word list (if exists) \ **************************************************************************** -\ if 'previous' is used without a preceeding 'also' all forth words are lost ! +\ if 'previous' is used without a preceding 'also' all forth words are lost ! \ **************************************************************************** : scsi-close ( -- ) \ FIXME This only works if scsi-words is the last vocabulary on the stack @@ -817,10 +817,10 @@ CONSTANT scsi-length-media-event THEN context scsi-context = \ scsi word list still active ? IF - scsi-param-errors 0<> \ any errors occured ? + scsi-param-errors 0<> \ any errors occurred ? IF cr ." ** WARNING: " scsi-param-errors .d - ." SCSI Errors occured ** " cr + ." SCSI Errors occurred ** " cr THEN previous \ remove scsi word list on top 0 to scsi-context \ prevent from being misinterpreted diff --git a/roms/SLOF/slof/fs/usb/usb-ohci.fs b/roms/SLOF/slof/fs/usb/usb-ohci.fs index f205e1db5..494b04a57 100644 --- a/roms/SLOF/slof/fs/usb/usb-ohci.fs +++ b/roms/SLOF/slof/fs/usb/usb-ohci.fs @@ -706,7 +706,7 @@ hchcca-dma hchcca - CONSTANT virt2phys-offset ; -\ COLON DEFINTION: HC-enable-bulk-list-processing +\ COLON DEFINITION: HC-enable-bulk-list-processing \ PENDING: Remove Hard coded constants. : HC-enable-bulk-list-processing ( -- ) @@ -779,7 +779,7 @@ hchcca-dma hchcca - CONSTANT virt2phys-offset \ If the caller specifies a wrong data toggle of 1 for a SETUP \ PACKET, this method will not find it out. -\ COLON DEFINTION: (toggle-current-toggle) +\ COLON DEFINITION: (toggle-current-toggle) \ Scope: Internal to fill-TD-list \ Functionality: \ Toggles the "T" field that is passed as argument. @@ -1002,7 +1002,7 @@ s" usb-support.fs" INCLUDED \ ===================================================================== -\ COLON DEFINTION: control-std-set-address +\ COLON DEFINITION: control-std-set-address \ INTERFACE FUNCTION \ Function allocates an USB addrss and uses it to send SET-ADDRESS packet \ to the default USB address. @@ -1022,7 +1022,7 @@ s" usb-support.fs" INCLUDED ; -\ Fetches the device decriptor of the usb-device +\ Fetches the device descriptor of the usb-device : control-std-get-device-descriptor diff --git a/roms/SLOF/slof/fs/usb/usb-storage-support.fs b/roms/SLOF/slof/fs/usb/usb-storage-support.fs index 765b758e4..aa620a412 100644 --- a/roms/SLOF/slof/fs/usb/usb-storage-support.fs +++ b/roms/SLOF/slof/fs/usb/usb-storage-support.fs @@ -17,7 +17,7 @@ s" entered usb-storage-support.fs" usb-debug-print \ --------------------------------------------------------------------------- : rw-endpoint - ( pt ed-type toggle buffer length mps addres -- toggle TRUE | toggle FALSE ) + ( pt ed-type toggle buffer length mps address -- toggle TRUE | toggle FALSE ) s" rw-endpoint" $call-parent ( toggle TRUE | toggle FALSE ) ; diff --git a/roms/SLOF/slof/fs/usb/usb-storage.fs b/roms/SLOF/slof/fs/usb/usb-storage.fs index fcb11134d..f7e257289 100644 --- a/roms/SLOF/slof/fs/usb/usb-storage.fs +++ b/roms/SLOF/slof/fs/usb/usb-storage.fs @@ -245,7 +245,7 @@ usb-debug-flag to scsi-param-debug \ copy debug flag \ --------------------------------------------------------------- \ Method to 1. Send the READ CAPACITY command -\ 2. Recieve and analyse the response data +\ 2. Receive and analyse the response data \ --------------------------------------------------------------- : read-capacity ( -- ) @@ -285,7 +285,7 @@ usb-debug-flag to scsi-param-debug \ copy debug flag dma-buf >response-buffer 0 do-bulk-command IF s" Successfully read test unit ready data" usb-debug-print - s" Test Unit STATUS availabe in dma-buf >csw-buffer" usb-debug-print + s" Test Unit STATUS available in dma-buf >csw-buffer" usb-debug-print dma-buf >csw-buffer 0c + c@ 0= IF s" Test Unit Command Successfully Executed" usb-debug-print TRUE ( TRUE ) diff --git a/roms/SLOF/slof/fs/usb/usb-support.fs b/roms/SLOF/slof/fs/usb/usb-support.fs index aa85ab9ca..c3c036564 100644 --- a/roms/SLOF/slof/fs/usb/usb-support.fs +++ b/roms/SLOF/slof/fs/usb/usb-support.fs @@ -537,7 +537,7 @@ VARIABLE controlxfer-cmd \ value of max packet size \ mps: Max Packet Size. \ address: Address of endpoint. 11-bit address. The lower 7-bits represent -\ the USB addres and the upper 4-bits represent the Endpoint +\ the USB address and the upper 4-bits represent the Endpoint \ number. : (do-rw-endpoint) @@ -578,7 +578,7 @@ VARIABLE controlxfer-cmd \ buffer length: Data buffer associated with the transfer \ mps: Max Packet Size. \ address: Address of endpoint. 11-bit address. The lower 7-bits represent -\ the USB addres and the upper 4-bits represent the Endpoint +\ the USB address and the upper 4-bits represent the Endpoint \ number. diff --git a/roms/SLOF/tools/.gitignore b/roms/SLOF/tools/.gitignore new file mode 100644 index 000000000..e45841399 --- /dev/null +++ b/roms/SLOF/tools/.gitignore @@ -0,0 +1 @@ +gen_reloc_table diff --git a/roms/SLOF/tools/gen_reloc_table.c b/roms/SLOF/tools/gen_reloc_table.c index b2e2176ab..b15ce9d00 100644 --- a/roms/SLOF/tools/gen_reloc_table.c +++ b/roms/SLOF/tools/gen_reloc_table.c @@ -69,7 +69,7 @@ main(int argc, char *argv[]) offset ++; if (cnt_a != cnt_b) { - fprintf (stderr, "Files >%s< and >%s< have not the same lenght\n",argv[1],argv[2]); + fprintf (stderr, "Files >%s< and >%s< have not the same length\n",argv[1],argv[2]); exit(-1); } diff --git a/roms/config.ipxe.general.h b/roms/config.ipxe.general.h new file mode 100644 index 000000000..b3fce5326 --- /dev/null +++ b/roms/config.ipxe.general.h @@ -0,0 +1,2 @@ +#undef BANNER_TIMEOUT +#define BANNER_TIMEOUT 0 diff --git a/roms/ipxe/contrib/rom-o-matic/bottom.php b/roms/ipxe/contrib/rom-o-matic/bottom.php index ff094fd8d..9ba8e3190 100644 --- a/roms/ipxe/contrib/rom-o-matic/bottom.php +++ b/roms/ipxe/contrib/rom-o-matic/bottom.php @@ -1,4 +1,4 @@ -. @@ -27,25 +27,25 @@ Resources:
  • Source code for iPXE images is available at - - http://etherboot.org/wiki/download + + http://www.ipxe.org/download

  • For general information about using iPXE, please visit the - - Etherboot Project Home Page + + iPXE Project Home Page

  • For Email-based support for iPXE please join - - Etherboot Project mailing lists. + + iPXE Project mailing lists.

  • For real-time online iPXE support via IRC please visit the - #etherboot channel + #ipxe channel of irc.freenode.net.

  • @@ -53,7 +53,7 @@ Resources:

    - Please email "> + Please email "> with questions or comments about this website.


    diff --git a/roms/ipxe/contrib/rom-o-matic/build.php b/roms/ipxe/contrib/rom-o-matic/build.php index 3101b3e39..b2b5bb452 100644 --- a/roms/ipxe/contrib/rom-o-matic/build.php +++ b/roms/ipxe/contrib/rom-o-matic/build.php @@ -179,7 +179,12 @@ if ( $embedded_script != "" ) { // 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"; +$gitversion = exec('git describe --always --abbrev=1 --match "" 2>/dev/null'); +if ($gitversion) { + $gitversion = "GITVERSION=$gitversion"; +} + +$make_cmd = "make -C '$build_dir' '$make_target' $gitversion $emb_script_cmd 2>&1"; exec ( $make_cmd, $maketxt, $status ); @@ -239,7 +244,7 @@ if ( $status == 0 ) { // Delete build directory as soon as it is not needed rm_build_dir (); - $output_filename = "ipxe-${version}-${nic}.${fmt_extension}"; + $output_filename = preg_replace('/[^a-z0-9\+\.\-]/i', '', "ipxe-${version}-${nic}.${fmt_extension}"); // Try to force IE to handle downloading right. Header ( "Cache-control: private"); diff --git a/roms/ipxe/contrib/rom-o-matic/customize-flags.php b/roms/ipxe/contrib/rom-o-matic/customize-flags.php index 230904393..e283921a8 100644 --- a/roms/ipxe/contrib/rom-o-matic/customize-flags.php +++ b/roms/ipxe/contrib/rom-o-matic/customize-flags.php @@ -34,30 +34,30 @@ include_once $top_inc; ?>
    - +

    - Make changes below and press to create an image,
    - Or press to return to the main page. + Make changes below and press to create an image,
    + Or press to return to the main page.


      - +

    - +

    Embedded Script:

    - +


    - - + +
    - + . @@ -21,12 +21,12 @@ ?>
  • - Choose an output format:

  • - Choose a NIC type:

  • @@ -37,14 +37,14 @@ PCI VENDOR CODE and PCI DEVICE CODE
    that match the NIC device for which you are making this image.

    Information on how to determine NIC PCI IDs may be found - here.

    - PCI VENDOR CODE:    - PCI DEVICE CODE:

    Please note for ROM images:

    diff --git a/roms/ipxe/contrib/rom-o-matic/flag-table.php b/roms/ipxe/contrib/rom-o-matic/flag-table.php index 078e5fd60..fe81c8029 100644 --- a/roms/ipxe/contrib/rom-o-matic/flag-table.php +++ b/roms/ipxe/contrib/rom-o-matic/flag-table.php @@ -98,6 +98,27 @@ $flag_table = array ( "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" + ), + + "LOG_LEVEL" + => array ( + "flag" => "LOG_LEVEL", + "type" => "choice", + "options" => array("LOG_NONE","LOG_EMERG","LOG_ALERT","LOG_CRIT","LOG_ERR", + "LOG_WARNING","LOG_NOTICE","LOG_INFO","LOG_DEBUG","LOG_ALL"), + "value" => "LOG_NONE", + "cfgsec" => "console" + ), + // End Console Options // Begin Network Protocol Options: @@ -487,6 +508,17 @@ $flag_table = array ( // 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: diff --git a/roms/ipxe/contrib/rom-o-matic/index.php b/roms/ipxe/contrib/rom-o-matic/index.php index 12b7e1a80..26585c975 100644 --- a/roms/ipxe/contrib/rom-o-matic/index.php +++ b/roms/ipxe/contrib/rom-o-matic/index.php @@ -27,10 +27,10 @@ include_once $top_inc; ?>
    - +

    To create an image:

      - +
    1. Generate and download an image: @@ -44,4 +44,4 @@ include_once $top_inc;
    - + diff --git a/roms/ipxe/contrib/rom-o-matic/top.php b/roms/ipxe/contrib/rom-o-matic/top.php index 25562086b..42a8e2d27 100644 --- a/roms/ipxe/contrib/rom-o-matic/top.php +++ b/roms/ipxe/contrib/rom-o-matic/top.php @@ -1,6 +1,6 @@ -. @@ -25,17 +25,17 @@ - "> + "> - <? echo $header_title ?> - + <?php echo $header_title ?> +

    -  + 


    - +


    diff --git a/roms/ipxe/contrib/rom-o-matic/utils.php b/roms/ipxe/contrib/rom-o-matic/utils.php index dc5bd4144..e0e62f447 100644 --- a/roms/ipxe/contrib/rom-o-matic/utils.php +++ b/roms/ipxe/contrib/rom-o-matic/utils.php @@ -1,4 +1,4 @@ -. @@ -131,7 +131,8 @@ function parse_nic_file () if ( strpos ( $first_eight_chars, "family" ) === 0 ) { // get pathname of NIC driver - list ( $dummy, $nic ) = split( "[ \t]+", $line ); + #list ( $dummy, $nic ) = split( "[ \t]+", $line ); + list ( $dummy, $nic ) = explode("\t", $line); settype ( $nic, "string" ); // extract filename name of driver from pathname diff --git a/roms/ipxe/contrib/vm/bochsrc.txt b/roms/ipxe/contrib/vm/bochsrc.txt index 32842a3b2..d0f12504b 100644 --- a/roms/ipxe/contrib/vm/bochsrc.txt +++ b/roms/ipxe/contrib/vm/bochsrc.txt @@ -1,15 +1,29 @@ # You may now use double quotes around pathnames, in case # your pathname includes spaces. +#======================================================================= +# PLUGIN_CTRL: +# Controls the presence of optional device plugins. These plugins are loaded +# directly with this option and some of them install a config option that is +# only available when the plugin device is loaded. The value "1" means to load +# the plugin and "0" will unload it (if loaded before). +# These plugins are currently supported: 'biosdev', 'e1000', 'es1370', +# 'extfpuirq', 'gameport', 'iodebug', 'ne2k', 'parallel', 'pcidev', 'pcipnic', +# 'sb16', 'serial', 'speaker', 'unmapped', 'usb_ohci', 'usb_uhci' and 'usb_xhci'. +#======================================================================= +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1 + #======================================================================= # 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 +# Depending on the platform there are up to 3 choices of configuration +# interface: a text mode version called "textconfig" and two graphical versions +# called "win32config" and "wx". The text mode version uses stdin/stdout and +# is always compiled in, unless Bochs is compiled for wx only. The choice +# "win32config" is only available on win32 and it is the default there. +# The choice "wx" 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. # @@ -17,6 +31,7 @@ # the "wx" display library. #======================================================================= #config_interface: textconfig +#config_interface: win32config #config_interface: wx #======================================================================= @@ -33,7 +48,6 @@ # 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 @@ -47,18 +61,23 @@ # 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. +# Some display libraries now support specific options to control their +# behaviour. These options are supported by more than one display library: +# +# "gui_debug" - use GTK debugger gui (sdl, x) / Win32 debugger gui (win32) +# "hideIPS" - disable IPS output in status bar (sdl, wx, x) +# "nokeyrepeat" - turn off host keyboard repeat (sdl, win32, x) +# +# See the examples below for other 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: win32 #display_library: wx #display_library: x @@ -67,67 +86,245 @@ # 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. +# starting at address 0xf0000, and it is exactly 64k long. Another option +# is 128k BIOS which is loaded at address 0xe0000. # 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. +# Bochs. The start address optional, since it can be calculated from image size. #======================================================================= -romimage: file=bochs/bios/BIOS-bochs-latest, address=0xe0000 +#romimage: file=$BXSHARE/BIOS-bochs-latest +#romimage: file=bios/seabios-1.6.3.bin #romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top -#romimage: file=mybios.bin # calculate start address from image size +romimage: file=bochs/bios/BIOS-bochs-latest #======================================================================= # CPU: # This defines cpu-related parameters inside Bochs: # +# MODEL: +# Selects CPU configuration to emulate from pre-defined list of all +# supported configurations. When this option is used, the CPUID option +# has no effect anymore. +# +# CPU configurations that can be selected: +# ----------------------------------------------------------------- +# pentium_mmx Intel Pentium MMX +# amd_k6_2_chomper AMD-K6(tm) 3D processor (Chomper) +# p2_klamath Intel Pentium II (Klamath) +# p3_katmai Intel Pentium III (Katmai) +# p4_willamette Intel(R) Pentium(R) 4 (Willamette) +# core_duo_t2400_yonah Intel(R) Core(TM) Duo CPU T2400 (Yonah) +# atom_n270 Intel(R) Atom(TM) CPU N270 +# athlon64_clawhammer AMD Athlon(tm) 64 Processor 2800+ (Clawhammer) +# athlon64_venice AMD Athlon(tm) 64 Processor 3000+ (Venice) +# turion64_tyler AMD Turion(tm) 64 X2 Mobile TL-60 (Tyler) +# phenom_8650_toliman AMD Phenom X3 8650 (Toliman) +# p4_prescott_celeron_336 Intel(R) Celeron(R) 336 (Prescott) +# core2_penryn_t9600 Intel Mobile Core 2 Duo T9600 (Penryn) +# corei5_lynnfield_750 Intel(R) Core(TM) i5 750 (Lynnfield) +# corei5_arrandale_m520 Intel(R) Core(TM) i5 M 520 (Arrandale) +# corei7_sandy_bridge_2600k Intel(R) Core(TM) i7-2600K (Sandy Bridge) +# corei7_ivy_bridge_3770k Intel(R) Core(TM) i7-3770K CPU (Ivy Bridge) +# # 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. +# 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. +# +# QUANTUM: +# Maximum amount of instructions allowed to execute by processor before +# returning control to another cpu. This option exists only in Bochs +# binary compiled with SMP support. # # 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 ! +# 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 ! +# +# CPUID_LIMIT_WINNT: +# Determine whether to limit maximum CPUID function to 2. This mode is +# required to workaround WinNT installation and boot issues. +# +# MSRS: +# Define path to user CPU Model Specific Registers (MSRs) specification. +# See example in msrs.def. +# +# IGNORE_BAD_MSRS: +# Ignore MSR references that Bochs does not understand; print a warning +# message instead of generating #GP exception. This option is enabled +# by default but will not be avaiable if configurable MSRs are enabled. +# +# MWAIT_IS_NOP: +# When this option is enabled MWAIT will not put the CPU into a sleep state. +# This option exists only if Bochs compiled with --enable-monitor-mwait. # # 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). +# 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 host's capability. +# Measured IPS value will then be logged into your log file or shown +# in the 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. +# 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 +# +# Bochs Machine/Compiler Mips +# ______________________________________________________________________ +# 2.4.6 3.4Ghz Intel Core i7 2600 with Win7x64/g++ 4.5.2 85 to 95 Mips +# 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips +# 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips +# 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips +# 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips +#======================================================================= +cpu: model=core2_penryn_t9600, count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" +cpu: cpuid_limit_winnt=0 + +#======================================================================= +# CPUID: +# +# This defines features and functionality supported by Bochs emulated CPU. +# The option has no offect if CPU model was selected in CPU option. +# +# MMX: +# Select MMX instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. +# +# APIC: +# Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC). +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. +# +# SEP: +# Select SYSENTER/SYSEXIT instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# SSE: +# Select SSE instruction set support. +# Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# SSE4A: +# Select AMD SSE4A instructions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# AES: +# Select AES instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# MOVBE: +# Select MOVBE Intel(R) Atom instruction support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XSAVE: +# Select XSAVE extensions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XSAVEOPT: +# Select XSAVEOPT instruction support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# AVX: +# Select AVX/AVX2 instruction set support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# AVX_F16C: +# Select AVX float16 convert instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# AVX_FMA: +# Select AVX fused multiply add (FMA) instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# BMI: +# Select BMI1/BMI2 instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# XOP: +# Select AMD XOP instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# FMA4: +# Select AMD four operand FMA instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# TBM: +# Select AMD Trailing Bit Manipulation (TBM) instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# X86-64: +# Enable x86-64 and long mode support. +# This option exists only if Bochs compiled with x86-64 support. +# +# 1G_PAGES: +# Enable 1G page size support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# PCID: +# Enable Process-Context Identifiers (PCID) support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# FSGSBASE: +# Enable GS/GS BASE access instructions support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# SMEP: +# Enable Supervisor Mode Execution Protection (SMEP) support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# MWAIT: +# Select MONITOR/MWAIT instructions support. +# This option exists only if Bochs compiled with --enable-monitor-mwait. +# +# VMX: +# Select VMX extensions emulation support. +# This option exists only if Bochs compiled with --enable-vmx option. +# +# VENDOR_STRING: +# Set the CPUID vendor string returned by CPUID(0x0). This should be a +# twelve-character ASCII string. +# +# BRAND_STRING: +# Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004). +# This should be at most a forty-eight-character ASCII string. +# +# FAMILY: +# Set model information returned by CPUID. Default family value determined +# by configure option --enable-cpu-level. +# +# MODEL: +# Set model information returned by CPUID. Default model value is 3. +# +# STEPPING: +# Set stepping information returned by CPUID. Default stepping value is 3. #======================================================================= -cpu: count=1, ips=10000000, reset_on_triple_fault=1 +#cpuid: x86_64=1, mmx=1, sep=1, sse=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1 +#cpuid: family=6, model=0x1a, stepping=5 #======================================================================= -# 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. +# MEMORY +# Set the amount of physical memory you want to emulate. +# +# GUEST: +# Set amount of guest physical memory to emulate. The default is 32MB, +# the maximum amount limited only by physical address space limitations. +# +# HOST: +# Set amount of host memory you want to allocate for guest RAM emulation. +# It is possible to allocate less memory than you want to emulate in guest +# system. This will fake guest to see the non-existing memory. Once guest +# system touches new memory block it will be dynamically taken from the +# memory pool. You will be warned (by FATAL PANIC) in case guest already +# used all allocated host memory and wants more. +# #======================================================================= -#megs: 256 -#megs: 128 -#megs: 64 -megs: 32 -#megs: 16 -#megs: 8 +memory: guest=512, host=256 #======================================================================= # OPTROMIMAGE[1-4]: @@ -144,8 +341,7 @@ megs: 32 #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 +optromimage1: file=../../src/bin/intel.rom, address=0xcb000 #optramimage1: file=/path/file1.img, address=0x0010000 #optramimage2: file=/path/file2.img, address=0x0020000 @@ -157,18 +353,31 @@ optromimage1: file=../../src/bin/pnic.rom, address=0xd0000 # 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=$BXSHARE/VGABIOS-lgpl-latest #vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest #======================================================================= # 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. +# This defines parameters related to the VGA display +# +# EXTENSION +# 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. +# +# UPDATE_FREQ +# The VGA update frequency is based on the emulated clock and the default +# value is 5. 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. If the realtime sync is +# enabled with the 'clock' option, the value is based on the real time. +# This parameter can be changed at runtime. +# +# Examples: +# vga: extension=cirrus, update_freq=10 #======================================================================= -#vga: extension=cirrus -#vga: extension=vbe -vga: extension=none +#vga: extension=vbe, update_freq=5 #======================================================================= # FLOPPYA: @@ -177,36 +386,42 @@ vga: extension=none # 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) +# floppya: 2_88=path, status=ejected (2.88M 3.5" media) +# floppya: 1_44=path, status=inserted (1.44M 3.5" media) +# floppya: 1_2=path, status=ejected (1.2M 5.25" media) +# floppya: 720k=path, status=inserted (720K 3.5" media) +# floppya: 360k=path, status=inserted (360K 5.25" media) +# floppya: 320k=path, status=inserted (320K 5.25" media) +# floppya: 180k=path, status=inserted (180K 5.25" media) +# floppya: 160k=path, status=inserted (160K 5.25" media) +# floppya: image=path, status=inserted (guess media type from image size) +# floppya: 1_44=vvfat:path, status=inserted (use directory as VFAT media) +# floppya: type=1_44 (1.44M 3.5" floppy drive, no media) # # 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. +# The parameter 'type' can be used to enable the floppy drive without media +# and status specified. Usually the drive type is set up based on the media type. +# The optional parameter 'write_protected' can be used to control the media +# write protect switch. By default it is turned off. #======================================================================= #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=a.img, status=inserted, write_protected=1 #floppya: 1_44=/dev/rfd0a, status=inserted -floppya: 1_44=../../src/bin/pnic.dsk, status=inserted +floppya: 1_44=../../src/bin/ipxe.dsk, status=inserted #======================================================================= # FLOPPYB: # See FLOPPYA above for syntax #======================================================================= #floppyb: 1_44=b:, status=inserted -floppyb: 1_44=b.img, status=inserted +#floppyb: 1_44=b.img, status=inserted #======================================================================= # ATA0, ATA1, ATA2, ATA3 @@ -236,8 +451,8 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # 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 +# mode= only valid for disks [undoable|growing|volatile|vvfat] +# path= path of the image / directory # cylinders= only valid for disks # heads= only valid for disks # spt= only valid for disks @@ -245,7 +460,7 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # 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 +# journal= optional filename of the redolog for undoable, volatile and vvfat 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 @@ -259,10 +474,11 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # 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. +# The path is mandatory for hard disks. Disk geometry autodetection works with +# images created by bximage if CHS is set to 0/0/0 (cylinders are calculated +# using heads=16 and spt=63). For other hard disk images and modes the +# cylinders, heads, and spt are mandatory. In all cases the disk size reported +# from the image must be exactly C*H*S*512. # # Default values are: # mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" @@ -279,7 +495,10 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # 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" #ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17 +#ata0-master: type=disk, mode=flat, path="c.img", cylinders=0 # autodetect +#ata0-slave: type=disk, mode=vvfat, path=/bochs/images/vvfat, journal=vvfat.redolog #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 @@ -287,15 +506,13 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 #======================================================================= # 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 +# This defines the boot sequence. Now you can specify up to 3 boot drives, +# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). +# Legacy 'a' and 'c' are also supported. # Examples: # boot: floppy -# boot: disk -# boot: cdrom -# boot: c -# boot: a +# boot: cdrom, disk +# boot: network, disk # boot: cdrom, floppy, disk #======================================================================= #boot: floppy @@ -307,7 +524,17 @@ boot: network, floppy # This defines the parameters of the clock inside Bochs: # # SYNC: -# TO BE COMPLETED (see Greg explanation in feature request #536329) +# This defines the method how to synchronize the Bochs internal time +# with realtime. With the value 'none' the Bochs time relies on the IPS +# value and no host time synchronization is used. The 'slowdown' method +# sacrifices performance to preserve reproducibility while allowing host +# time correlation. The 'realtime' method sacrifices reproducibility to +# preserve performance and host-time correlation. +# It is possible to enable both synchronization methods. +# +# RTC_SYNC: +# If this option is enabled together with the realtime synchronization, +# the RTC runs at realtime speed. This feature is disabled by default. # # TIME0: # Specifies the start (boot) time of the virtual machine. Use a time @@ -342,7 +569,6 @@ boot: network, floppy # floppy_bootsig_check: disabled=0 # floppy_bootsig_check: disabled=1 #======================================================================= -#floppy_bootsig_check: disabled=1 floppy_bootsig_check: disabled=0 #======================================================================= @@ -378,7 +604,7 @@ log: bochsout.txt #======================================================================= # LOG CONTROLS # -# Bochs now has four severity levels for event logging. +# Bochs 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 @@ -387,9 +613,13 @@ log: bochsout.txt # 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. +# For events of each level, you can choose to exit Bochs ('fatal'), 'report' +# or 'ignore'. On some guis you have the additional choice 'ask'. A gui dialog +# appears asks how to proceed. +# +# It is also possible to specify the 'action' to do for each Bochs facility +# separately (e.g. crash on panics from everything except the cdrom, and only +# report those). See the 'log function' module list in the user documentation. # # If you are experiencing many panics, it can be helpful to change # the panic action to report instead of fatal. However, be aware @@ -400,8 +630,7 @@ log: bochsout.txt panic: action=ask error: action=report info: action=report -debug: action=ignore -#pass: action=fatal +debug: action=ignore, pci=report # report BX_DEBUG from module 'pci' #======================================================================= # DEBUGGER_LOG: @@ -425,18 +654,29 @@ debugger_log: - # 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. +# In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe +# client or server. In client mode it connects to an already running server (if +# connection fails Bochs treats com port as not connected). In server mode it +# opens socket/named pipe and waits until a client application connects to it +# before starting simulation. This mode is useful for remote debugging (e.g. +# with gdb's "target remote host:port" command or windbg's command line option +# -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for +# 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP +# communication, pipe modes use duplex byte mode pipes. # 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). +# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys'). # # 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 +# com3: enabled=1, mode=socket-client, dev=localhost:8888 +# com3: enabled=1, mode=socket-server, dev=localhost:8888 +# com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe +# com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe #======================================================================= #com1: enabled=1, mode=term, dev=/dev/ttyp9 @@ -461,6 +701,9 @@ parport1: enabled=1, file="parport.out" # This defines the SB16 sound emulation. It can have several of the # following properties. # All properties are in the format sb16: property=value +# enabled: +# This optional property controls the presence of the SB16 emulation. +# The emulation is turned on unless this property is used and set to 0. # 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: @@ -488,26 +731,25 @@ parport1: enabled=1, file="parport.out" # 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: +# Examples for output devices: +# sb16: midimode=1, midi="", wavemode=1, wave="" # win32 +# sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA #======================================================================= - #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. +# ES1370: +# This defines the ES1370 sound emulation. The parameter 'enabled' controls the +# presence of the device. In addition to this, it must be loaded with 'plugin_ctrl' +# and assigned to a PCI slot. The 'wavedev' parameter is similar to the 'wave' +# parameter of the SB16 soundcard. The emulation supports recording and playback +# (except DAC1+DAC2 output at the same time). # # Examples: -# vga_update_interval: 250000 +# es1370: enabled=1, wavedev="" # win32 +# es1370: enabled=1, wavedev=alsa # Linux with ALSA #======================================================================= -vga_update_interval: 300000 - -# using for Winstone '98 tests -#vga_update_interval: 100000 +#es1370: enabled=1, wavedev=alsa #======================================================================= # KEYBOARD_SERIAL_DELAY: @@ -537,24 +779,34 @@ 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). +# This defines parameters for the emulated mouse type, the initial status +# of the mouse capture and the runtime method to toggle it. +# +# TYPE: +# 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' and 'serial_msys' (one com port requires +# setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci', +# 'usb_ohci' or 'usb_xhci' options (requires PCI and USB support). +# +# ENABLED: +# The Bochs gui creates mouse "events" unless the 'enabled' option is +# set to 0. The hardware emulation itself is not disabled by this. +# 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 (RFB, SDL, Win32, wxWidgets and X11 - see below). +# +# TOGGLE: +# The default method to toggle the mouse capture at runtime is to press the +# CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows +# to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (like QEMU) +# or 'f12' (replaces win32 'legacyF12' option). # # Examples: # mouse: enabled=1 -# mouse: enabled=1, type=imps2 -# mouse: enabled=1, type=serial -# mouse: enabled=0 +# mouse: type=imps2, enabled=1 +# mouse: type=serial, enabled=1 +# mouse: enabled=0, toggle=ctrl+f10 #======================================================================= mouse: enabled=0 @@ -586,54 +838,86 @@ private_colormap: enabled=0 #======================================================================= # ne2k: NE2000 compatible ethernet adapter # -# Examples: -# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# Format: +# ne2k: enabled=1, ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, +# ethdev=DEVICE, script=SCRIPT, bootrom=BOOTROM # -# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there -# are IRQ conflicts. +# IOADDR, IRQ: You probably won't need to change ioaddr and irq, unless there +# are IRQ conflicts. These arguments are ignored when assign the ne2k to a +# PCI slot. # -# mac: The MAC address MUST NOT match the address of any machine on the net. +# 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 +# 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 +# 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 +# as first parameter. +# +# BOOTROM: The bootrom value is optional, and is the name of the ROM image +# to load. Note that this feature is only implemented for the PCI version of +# the NE2000. # # 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 +# 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 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" +# ne2k: mac=b0:c4:20:00:00:01, ethmod=slirp, script=/usr/local/bin/slirp, bootrom=ne2k_pci.rom + +#======================================================================= +# pnic: Bochs/Etherboot pseudo-NIC +# +# Format: +# pnic: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT, +# bootrom=BOOTROM +# +# The pseudo-NIC accepts the same syntax (for mac, ethmod, ethdev, script, +# bootrom) and supports the same networking modules as the NE2000 adapter. +# In addition to this, it must be loaded with 'plugin_ctrl' and assigned +# to a PCI slot. +#======================================================================= +#pnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet + +#======================================================================= +# e1000: Intel(R) 82540EM Gigabit Ethernet adapter +# +# Format: +# e1000: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# bootrom=BOOTROM +# +# The E1000 accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) +# and supports the same networking modules as the NE2000 adapter. In addition +# to this, it must be loaded with 'plugin_ctrl' and assigned to a PCI slot. +#======================================================================= +#e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=slirp, script=/usr/local/bin/slirp +e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0 #======================================================================= # KEYBOARD_MAPPING: @@ -662,45 +946,88 @@ keyboard_mapping: enabled=0, map= # 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. +# 3 key names (listed below) separated with a '-' character. # 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". +# "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power". # # Example: # user_shortcut: keys=ctrl-alt-del #======================================================================= -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'. +# PCI: +# This option controls the presence of a PCI chipset in Bochs. Currently it only +# supports the i440FX chipset. You can also specify the devices connected to +# PCI slots. Up to 5 slots are available. These devices are currently supported: +# cirrus, e1000, es1370, ne2k, pcivga, pcidev, pcipnic, usb_ohci and usb_xhci. # # Example: -# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k +# pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k #======================================================================= -i440fxsupport: enabled=1, slot1=pcipnic -#i440fxsupport: enabled=1, slot1=ne2k +pci: enabled=1, chipset=i440fx, slot1=e1000 #======================================================================= -# USB1: +# USB_UHCI: # 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. +# of the i440FX PCI chipset. With the portX parameter you can connect devices +# to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom' +# 'hub' and 'printer'). NOTE: UHCI must be loaded with 'plugin_ctrl'. # -# Example: -# usb1: enabled=1, port1=mouse, port2=keypad +# The optionsX parameter can be used to assign specific options to the device +# connected to the corresponding USB port. Currently this feature is only used +# to set the speed reported by device and by the 'disk' device to specify +# an alternative redolog file of some image modes. +# +# If you connect the mouse or tablet to one of the ports, Bochs forwards the +# mouse movement data to the USB device instead of the selected mouse type. +# When connecting the keypad to one of the ports, Bochs forwards the input of +# the numeric keypad to the USB device instead of the PS/2 keyboard. +# +# To connect a 'flat' mode image as an USB hardisk you can use the 'disk' device +# with the path to the image separated with a colon. To use other disk image modes +# similar to ATA disks the syntax 'disk:mode:filename' must be used (see below). +# +# To emulate an USB cdrom you can use the 'cdrom' device name and the path to +# an ISO image or raw device name also separated with a colon. An option to +# insert/eject media is available in the runtime configuration. +# +# The device name 'hub' connects an external hub with max. 8 ports (default: 4) +# to the root hub. To specify the number of ports you have to add the value +# separated with a colon. Connecting devices to the external hub ports is only +# available in the runtime configuration. +# +# The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is +# sent to a file specified in bochsrc.txt. The current code appends the PCL +# code to the file if the file already existed. It would probably be nice to +# overwrite the file instead, asking user first. +#======================================================================= +#usb_uhci: enabled=1 +#usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img +#usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img +#usb_uhci: enabled=1, port2=disk:undoable:usbdisk.img, options1=journal:redo.log +#usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso + +#======================================================================= +# USB_OHCI: +# This option controls the presence of the USB OHCI host controller with a +# 2-port hub. The portX option accepts the same device types with the same +# syntax as the UHCI controller (see above). The OHCI HC must be assigned to +# a PCI slot and loaded with 'plugin_ctrl'. +#======================================================================= +#usb_ohci: enabled=1 +#usb_ohci: enabled=1, port1=printer:usbprinter.bin + #======================================================================= -#usb1: enabled=1 +# USB_XHCI: +# This option controls the presence of the experimental USB xHCI host controller +# with a 4-port hub. The portX option accepts the same device types with the +# same syntax as the UHCI controller (see above). The xHCI HC must be assigned +# to a PCI slot and loaded with 'plugin_ctrl'. +#======================================================================= +#usb_xhci: enabled=1 #======================================================================= # CMOSIMAGE: @@ -715,12 +1042,50 @@ i440fxsupport: enabled=1, slot1=pcipnic #cmosimage: file=cmos.img, rtc_init=time0 #======================================================================= -# other stuff +# MAGIC_BREAK: +# This enables the "magic breakpoint" feature when using the debugger. +# The useless cpu instruction XCHG BX, BX causes Bochs to enter the +# debugger mode. This might be useful for software development. +# +# Example: +# magic_break: enabled=1 #======================================================================= +#magic_break: enabled=1 magic_break: enabled=1 + +#======================================================================= +# PORT_E9_HACK: +# The 0xE9 port doesn't exists in normal ISA architecture. However, we +# define a convention here, to display on the console of the system running +# Bochs anything that is written to it. The idea is to provide debug output +# very early when writing BIOS or OS code for example, without having to +# bother with setting up a serial port or etc. Reading from port 0xE9 will +# will return 0xe9 to let you know if the feature is available. +# Leave this 0 unless you have a reason to use it. +# +# Example: +# port_e9_hack: enabled=1 +#======================================================================= +port_e9_hack: enabled=1 + +#======================================================================= +# DEBUG_SYMBOLS: +# This loads symbols from the specified file for use in Bochs' internal +# debugger. Symbols are loaded into global context. This is equivalent to +# issuing ldsym debugger command at start up. +# +# Example: +# debug_symbols: file="kernel.sym" +# debug_symbols: file="kernel.sym", offset=0x80000000 +#======================================================================= +#debug_symbols: file="kernel.sym" + +#======================================================================= +# other stuff +#======================================================================= #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 +#print_timestamps: enabled=1 #------------------------- # PCI host device mapping @@ -735,11 +1100,12 @@ magic_break: enabled=1 #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. +# USER_PLUGIN: +# Load user-defined plugin. This option is available only if Bochs is +# compiled with plugin support. Maximum 8 different plugins are supported. +# See the example in the Bochs sources how to write a plugin device. #======================================================================= -#ips: 10000000 +#user_plugin: name=testdev #======================================================================= # for Macintosh, use the style of pathnames in the following @@ -749,3 +1115,17 @@ magic_break: enabled=1 # romimage: file=:bios:BIOS-bochs-latest, address=0xf0000 # floppya: 1_44=[fd:], status=inserted #======================================================================= + +#======================================================================= +# 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. +# The 'MEGS' option is deprecated. Use 'MEMORY' option instead. +#======================================================================= +#megs: 256 +#megs: 128 +#megs: 64 +#megs: 32 +#megs: 16 +#megs: 8 diff --git a/roms/ipxe/src/Makefile b/roms/ipxe/src/Makefile index 8cc976ba0..e240f4ced 100644 --- a/roms/ipxe/src/Makefile +++ b/roms/ipxe/src/Makefile @@ -7,6 +7,7 @@ CLEANUP := CFLAGS := ASFLAGS := LDFLAGS := +HOST_CFLAGS := MAKEDEPS := Makefile ############################################################################### @@ -32,6 +33,7 @@ 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 @@ -68,9 +70,12 @@ SRCDIRS += drivers/net/igb SRCDIRS += drivers/net/igbvf SRCDIRS += drivers/net/phantom SRCDIRS += drivers/net/rtl818x -SRCDIRS += drivers/net/ath5k +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 @@ -138,7 +143,8 @@ everything : 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 + bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux \ + bin-i386-linux/tests.linux bin-x86_64-linux/tests.linux ############################################################################### # @@ -160,13 +166,12 @@ 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' +GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null) +ifneq ($(GITVERSION),) +VERSION += ($(GITVERSION)) +endif version : - @$(ECHO) $(VERSION) + @$(ECHO) "$(VERSION)" ############################################################################### # diff --git a/roms/ipxe/src/Makefile.housekeeping b/roms/ipxe/src/Makefile.housekeeping index ba01f16d5..d40f226f6 100644 --- a/roms/ipxe/src/Makefile.housekeeping +++ b/roms/ipxe/src/Makefile.housekeeping @@ -162,9 +162,12 @@ endif # output of "size". Inhibit this. # ifeq ($(CCTYPE),gcc) -CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \ +CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \ + -fno-asynchronous-unwind-tables -x c -c /dev/null \ -o /dev/null >/dev/null 2>&1 -CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm') +CFI_FLAGS := $(shell $(CFI_TEST) && \ + $(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \ + '-fno-unwind-tables -fno-asynchronous-unwind-tables') WORKAROUND_CFLAGS += $(CFI_FLAGS) endif @@ -381,6 +384,7 @@ 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 @@ -411,12 +415,14 @@ 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 ASFLAGS += --fatal-warnings +HOST_CFLAGS += -Werror endif # Function trace recorder state in the last build. This is needed @@ -450,14 +456,20 @@ 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. +# 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') -CFLAGS += -ffunction-sections $(DS_FLAGS) +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 @@ -508,6 +520,150 @@ 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 := +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 := +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 := +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 +# +ifdef KEY +PRIVKEY := $(KEY) # Maintain backwards compatibility +endif +PRIVKEY_LIST := $(BIN)/.private_key.list +ifeq ($(wildcard $(PRIVKEY_LIST)),) +PRIVKEY_OLD := +else +PRIVKEY_OLD := $(shell cat $(PRIVKEY_LIST)) +endif +ifneq ($(PRIVKEY_OLD),$(PRIVKEY)) +$(shell $(ECHO) "$(PRIVKEY)" > $(PRIVKEY_LIST)) +endif + +$(PRIVKEY_LIST) : + +VERYCLEANUP += $(PRIVKEY_LIST) + +# Embedded client private key +# +PRIVKEY_INC := $(BIN)/.private_key.der + +ifdef PRIVKEY +$(PRIVKEY_INC) : $(PRIVKEY) $(PRIVKEY_LIST) + $(Q)$(OPENSSL) rsa -in $< -outform DER -out $@ + +clientcert_DEPS += $(PRIVKEY_INC) +endif + +CLEANUP += $(PRIVKEY_INC) + +clientcert_DEPS += $(PRIVKEY_LIST) + +CFLAGS_clientcert += $(if $(PRIVKEY),-DPRIVATE_KEY="\"$(PRIVKEY_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) + +# Version number +# +CFLAGS_version += -DVERSION_MAJOR=$(VERSION_MAJOR) \ + -DVERSION_MINOR=$(VERSION_MINOR) \ + -DVERSION_PATCH=$(VERSION_PATCH) \ + -DVERSION="\"$(VERSION)\"" +# Make sure the version number gets updated on every git checkout +ifneq ($(GITVERSION),) +$(BIN)/version.o : ../.git/index +endif + # 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. @@ -521,9 +677,9 @@ DEBUG_TARGETS += dbg%.o c s define deps_template @$(ECHO) " [DEPS] $(1)" @$(MKDIR) -p $(BIN)/deps/$(dir $(1)) - @$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ + $(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ -Wno-error -M $(1) -MG -MP | \ - sed 's/\.o\s*:/_DEPS =/' > $(BIN)/deps/$(1).d + sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d endef # rules_template : generate rules for a given source file @@ -549,7 +705,8 @@ define rules_template '\n$(TGT)_OBJS += $$(BIN)/$(3).$(TGT)\n' ) ) \ '\n$(BIN)/deps/$(1).d : $$($(3)_DEPS)\n' \ '\nTAGS : $$($(3)_DEPS)\n' > $(BIN)/rules/$(1).r - @$(PERL) $(PARSEROM) $(1) >> $(BIN)/rules/$(1).r + @$(if $(findstring drivers/,$(1)),\ + $(PERL) $(PARSEROM) $(1) >> $(BIN)/rules/$(1).r) endef # Rule to generate the dependency list file @@ -596,39 +753,6 @@ drivers : roms : @$(ECHO) $(ROMS) -# 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. -# -EMBEDDED_LIST := $(BIN)/.embedded.list -ifeq ($(wildcard $(EMBEDDED_LIST)),) -EMBEDDED_IMAGE_OLD := -else -EMBEDDED_IMAGE_OLD := $(shell cat $(EMBEDDED_LIST)) -endif -ifneq ($(EMBEDDED_IMAGE_OLD),$(EMBEDDED_IMAGE)) -$(shell $(ECHO) "$(EMBEDDED_IMAGE)" > $(EMBEDDED_LIST)) -endif - -$(EMBEDDED_LIST) : - -VERYCLEANUP += $(EMBEDDED_LIST) - -EMBEDDED_FILES := $(subst $(COMMA), ,$(EMBEDDED_IMAGE)) -EMBED_ALL := $(foreach i,$(call seq,1,$(words $(EMBEDDED_FILES))),\ - EMBED ( $(i), \"$(word $(i), $(EMBEDDED_FILES))\",\ - \"$(notdir $(word $(i),$(EMBEDDED_FILES)))\" )) - -$(BIN)/embedded.o : $(EMBEDDED_FILES) $(EMBEDDED_LIST) - -# This file uses .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) - -CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)" - # Generate error usage information # $(BIN)/%.einfo : $(BIN)/%.o @@ -953,13 +1077,13 @@ endif # defined(BIN) # $(NRV2B) : util/nrv2b.c $(MAKEDEPS) $(QM)$(ECHO) " [HOSTCC] $@" - $(Q)$(HOST_CC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG \ - -DBITSIZE=32 -DENDIAN=0 -o $@ $< + $(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) -O2 -o $@ $< + $(Q)$(HOST_CC) $(HOST_CFLAGS) -o $@ $< CLEANUP += $(ZBIN) ############################################################################### @@ -967,23 +1091,25 @@ CLEANUP += $(ZBIN) # The EFI image converter # ELF2EFI_CFLAGS := -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \ - -I$(ZLIB_DIR)/include -idirafter include \ - -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib -L$(ZLIB_DIR)/lib \ + -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) $< $(ELF2EFI_CFLAGS) -DEFI_TARGET_IA32 -O2 -o $@ + $(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) $< $(ELF2EFI_CFLAGS) -DEFI_TARGET_X64 -O2 -o $@ + $(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) -idirafter include -O2 -o $@ $< + $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $< CLEANUP += $(EFIROM) ############################################################################### @@ -992,7 +1118,7 @@ CLEANUP += $(EFIROM) # $(ICCFIX) : util/iccfix.c $(MAKEDEPS) $(QM)$(ECHO) " [HOSTCC] $@" - $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $< + $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $< CLEANUP += $(ICCFIX) ############################################################################### @@ -1001,7 +1127,7 @@ CLEANUP += $(ICCFIX) # $(EINFO) : util/einfo.c $(MAKEDEPS) $(QM)$(ECHO) " [HOSTCC] $@" - $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $< + $(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $< CLEANUP += $(EINFO) ############################################################################### diff --git a/roms/ipxe/src/arch/i386/Makefile b/roms/ipxe/src/arch/i386/Makefile index 3261fff39..8314f26da 100644 --- a/roms/ipxe/src/arch/i386/Makefile +++ b/roms/ipxe/src/arch/i386/Makefile @@ -54,6 +54,8 @@ CFLAGS += -m32 ASFLAGS += --32 ifeq ($(HOST_OS),FreeBSD) LDFLAGS += -m elf_i386_fbsd +else ifeq ($(HOST_OS),OpenBSD) +LDFLAGS += -m elf_i386_obsd else LDFLAGS += -m elf_i386 endif @@ -85,15 +87,9 @@ 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 -# The various xxx_loader.c files are #included into core/loader.c and -# should not be compiled directly. -# -NON_AUTO_SRCS += arch/i386/core/aout_loader.c -NON_AUTO_SRCS += arch/i386/core/freebsd_loader.c -NON_AUTO_SRCS += arch/i386/core/wince_loader.c - # Include common x86 Makefile # MAKEDEPS += arch/x86/Makefile diff --git a/roms/ipxe/src/arch/i386/Makefile.pcbios b/roms/ipxe/src/arch/i386/Makefile.pcbios index 258c5d7d8..e1b226f5a 100644 --- a/roms/ipxe/src/arch/i386/Makefile.pcbios +++ b/roms/ipxe/src/arch/i386/Makefile.pcbios @@ -19,6 +19,7 @@ MEDIA += mrom MEDIA += pxe MEDIA += kpxe MEDIA += kkpxe +MEDIA += kkkpxe MEDIA += lkrn MEDIA += dsk MEDIA += nbi diff --git a/roms/ipxe/src/arch/i386/core/aout_loader.c b/roms/ipxe/src/arch/i386/core/aout_loader.c deleted file mode 100644 index f85620e97..000000000 --- a/roms/ipxe/src/arch/i386/core/aout_loader.c +++ /dev/null @@ -1,144 +0,0 @@ -/* a.out */ -struct exec { - unsigned long a_midmag; /* flags<<26 | mid<<16 | magic */ - unsigned long a_text; /* text segment size */ - unsigned long a_data; /* initialized data size */ - unsigned long a_bss; /* uninitialized data size */ - unsigned long a_syms; /* symbol table size */ - unsigned long a_entry; /* entry point */ - unsigned long a_trsize; /* text relocation size */ - unsigned long a_drsize; /* data relocation size */ -}; - -struct aout_state { - struct exec head; - unsigned long curaddr; - int segment; /* current segment number, -1 for none */ - unsigned long loc; /* start offset of current block */ - unsigned long skip; /* padding to be skipped to current segment */ - unsigned long toread; /* remaining data to be read in the segment */ -}; - -static struct aout_state astate; - -static sector_t aout_download(unsigned char *data, unsigned int len, int eof); -static inline os_download_t aout_probe(unsigned char *data, unsigned int len) -{ - unsigned long start, mid, end, istart, iend; - if (len < sizeof(astate.head)) { - return 0; - } - memcpy(&astate.head, data, sizeof(astate.head)); - if ((astate.head.a_midmag & 0xffff) != 0x010BL) { - return 0; - } - - printf("(a.out"); - aout_freebsd_probe(); - printf(")... "); - /* Check the aout image */ - start = astate.head.a_entry; - mid = (((start + astate.head.a_text) + 4095) & ~4095) + astate.head.a_data; - end = ((mid + 4095) & ~4095) + astate.head.a_bss; - istart = 4096; - iend = istart + (mid - start); - if (!prep_segment(start, mid, end, istart, iend)) - return dead_download; - astate.segment = -1; - astate.loc = 0; - astate.skip = 0; - astate.toread = 0; - return aout_download; -} - -static sector_t aout_download(unsigned char *data, unsigned int len, int eof) -{ - unsigned int offset; /* working offset in the current data block */ - - offset = 0; - -#ifdef AOUT_LYNX_KDI - astate.segment++; - if (astate.segment == 0) { - astate.curaddr = 0x100000; - astate.head.a_entry = astate.curaddr + 0x20; - } - memcpy(phys_to_virt(astate.curaddr), data, len); - astate.curaddr += len; - return 0; -#endif - - do { - if (astate.segment != -1) { - if (astate.skip) { - if (astate.skip >= len - offset) { - astate.skip -= len - offset; - break; - } - offset += astate.skip; - astate.skip = 0; - } - - if (astate.toread) { - if (astate.toread >= len - offset) { - memcpy(phys_to_virt(astate.curaddr), data+offset, - len - offset); - astate.curaddr += len - offset; - astate.toread -= len - offset; - break; - } - memcpy(phys_to_virt(astate.curaddr), data+offset, astate.toread); - offset += astate.toread; - astate.toread = 0; - } - } - - /* Data left, but current segment finished - look for the next - * segment. This is quite simple for a.out files. */ - astate.segment++; - switch (astate.segment) { - case 0: - /* read text */ - astate.curaddr = astate.head.a_entry; - astate.skip = 4096; - astate.toread = astate.head.a_text; - break; - case 1: - /* read data */ - /* skip and curaddr may be wrong, but I couldn't find - * examples where this failed. There is no reasonable - * documentation for a.out available. */ - astate.skip = ((astate.curaddr + 4095) & ~4095) - astate.curaddr; - astate.curaddr = (astate.curaddr + 4095) & ~4095; - astate.toread = astate.head.a_data; - break; - case 2: - /* initialize bss and start kernel */ - astate.curaddr = (astate.curaddr + 4095) & ~4095; - astate.skip = 0; - astate.toread = 0; - memset(phys_to_virt(astate.curaddr), '\0', astate.head.a_bss); - goto aout_startkernel; - default: - break; - } - } while (offset < len); - - astate.loc += len; - - if (eof) { - unsigned long entry; - -aout_startkernel: - entry = astate.head.a_entry; - done(1); - - aout_freebsd_boot(); -#ifdef AOUT_LYNX_KDI - xstart32(entry); -#endif - printf("unexpected a.out variant\n"); - longjmp(restart_etherboot, -2); - } - return 0; -} diff --git a/roms/ipxe/src/arch/i386/core/basemem_packet.c b/roms/ipxe/src/arch/i386/core/basemem_packet.c index d487cce36..06ffa3bbd 100644 --- a/roms/ipxe/src/arch/i386/core/basemem_packet.c +++ b/roms/ipxe/src/arch/i386/core/basemem_packet.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/core/cmdline.c b/roms/ipxe/src/arch/i386/core/cmdline.c deleted file mode 100644 index fa5adb8c6..000000000 --- a/roms/ipxe/src/arch/i386/core/cmdline.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2011 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along 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 passed to iPXE - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** Command line physical address - * - * This can be set by the prefix. - */ -uint32_t __bss16 ( cmdline_phys ); -#define cmdline_phys __use_data16 ( cmdline_phys ) - -/** 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, "CMDLINE 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 = "", - .type = &script_image_type, -}; - -/** - * Initialise command line - * - */ -static void cmdline_init ( void ) { - struct image *image = &cmdline_image; - userptr_t cmdline_user; - char *cmdline; - char *tmp; - size_t len; - - /* Do nothing if no command line was specified */ - if ( ! cmdline_phys ) { - DBGC ( image, "CMDLINE found no command line\n" ); - return; - } - 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 ( image, "CMDLINE could not allocate %zd bytes\n", len ); - /* No way to indicate failure */ - return; - } - cmdline = cmdline_copy; - copy_from_user ( cmdline, cmdline_user, 0, len ); - DBGC ( image, "CMDLINE found \"%s\"\n", cmdline ); - - /* Check for unwanted cruft in the command line */ - while ( isspace ( *cmdline ) ) - cmdline++; - if ( ( tmp = strstr ( cmdline, "BOOT_IMAGE=" ) ) != NULL ) { - DBGC ( image, "CMDLINE stripping \"%s\"\n", tmp ); - *tmp = '\0'; - } - DBGC ( image, "CMDLINE using \"%s\"\n", cmdline ); - - /* Prepare and register image */ - cmdline_image.data = virt_to_user ( cmdline ); - cmdline_image.len = strlen ( cmdline ); - if ( cmdline_image.len ) - register_image ( &cmdline_image ); - - /* Drop our reference to the image */ - image_put ( &cmdline_image ); -} - -/** Command line initialisation function */ -struct init_fn cmdline_init_fn __init_fn ( INIT_NORMAL ) = { - .initialise = cmdline_init, -}; diff --git a/roms/ipxe/src/arch/i386/core/cpu.c b/roms/ipxe/src/arch/i386/core/cpu.c deleted file mode 100644 index c24fa4e69..000000000 --- a/roms/ipxe/src/arch/i386/core/cpu.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -/** @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/roms/ipxe/src/arch/i386/core/freebsd_loader.c b/roms/ipxe/src/arch/i386/core/freebsd_loader.c deleted file mode 100644 index 464f6d939..000000000 --- a/roms/ipxe/src/arch/i386/core/freebsd_loader.c +++ /dev/null @@ -1,377 +0,0 @@ -/* bootinfo */ -#define BOOTINFO_VERSION 1 -#define NODEV (-1) /* non-existent device */ -#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */ -#define PAGE_SIZE (1<= estate.p.phdr32[j].p_offset) && - ((shdr[i].sh_offset + shdr[i].sh_size) <= - (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz))) - { - shdr[i].sh_offset=0; - shdr[i].sh_size=0; - break; - } - } - } - if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0)) - { - symtabindex = i; - symstrindex = shdr[i].sh_link; - } - } - } - } - - /* Check if we have a symbol table index and have not loaded it */ - if ((symtab_load == 0) && (symtabindex >= 0)) - { - /* No symbol table yet? Load it first... */ - - /* This happens to work out in a strange way. - * If we are past the point in the file already, - * we will skip a *large* number of bytes which - * ends up bringing us to the end of the file and - * an old (default) boot. Less code and lets - * the state machine work in a cleaner way but this - * is a nasty side-effect trick... */ - estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset); - - /* And we need to read this many bytes... */ - estate.toread = shdr[symtabindex].sh_size; - - if (estate.toread) - { -#if ELF_DEBUG - printf("db sym, size %lX, curaddr %lX\n", - estate.toread, estate.curaddr); -#endif - /* Save where we are loading this... */ - symtab_load = estate.curaddr; - - *((long *)phys_to_virt(estate.curaddr)) = estate.toread; - estate.curaddr += sizeof(long); - - /* Start to read... */ - return 1; - } - } - else if ((symstr_load == 0) && (symstrindex >= 0)) - { - /* We have already loaded the symbol table, so - * now on to the symbol strings... */ - - - /* Same nasty trick as above... */ - estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset); - - /* And we need to read this many bytes... */ - estate.toread = shdr[symstrindex].sh_size; - - if (estate.toread) - { -#if ELF_DEBUG - printf("db str, size %lX, curaddr %lX\n", - estate.toread, estate.curaddr); -#endif - /* Save where we are loading this... */ - symstr_load = estate.curaddr; - - *((long *)phys_to_virt(estate.curaddr)) = estate.toread; - estate.curaddr += sizeof(long); - - /* Start to read... */ - return 1; - } - } - } - /* all done */ - return 0; -} - -static void elf_freebsd_boot(unsigned long entry) -{ - if (image_type != Elf_FreeBSD) - return; - - memset(&bsdinfo, 0, sizeof(bsdinfo)); - bsdinfo.bi_basemem = meminfo.basememsize; - bsdinfo.bi_extmem = meminfo.memsize; - bsdinfo.bi_memsizes_valid = 1; - bsdinfo.bi_version = BOOTINFO_VERSION; - bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF); - bsdinfo.bi_nfs_diskless = NULL; - bsdinfo.bi_size = sizeof(bsdinfo); -#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */ - if(freebsd_kernel_env[0] != '\0'){ - freebsd_howto |= RB_BOOTINFO; - bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env; - } - - /* Check if we have symbols loaded, and if so, - * made the meta_data needed to pass those to - * the kernel. */ - if ((symtab_load !=0) && (symstr_load != 0)) - { - unsigned long *t; - - bsdinfo.bi_symtab = symtab_load; - - /* End of symbols (long aligned...) */ - /* Assumes size of long is a power of 2... */ - bsdinfo.bi_esymtab = (symstr_load + - sizeof(long) + - *((long *)phys_to_virt(symstr_load)) + - sizeof(long) - 1) & ~(sizeof(long) - 1); - - /* Where we will build the meta data... */ - t = phys_to_virt(bsdinfo.bi_esymtab); - -#if ELF_DEBUG - printf("Metadata at %lX\n",t); -#endif - - /* Set up the pointer to the memory... */ - bsdinfo.bi_modulep = virt_to_phys(t); - - /* The metadata structure is an array of 32-bit - * words where we store some information about the - * system. This is critical, as FreeBSD now looks - * only for the metadata for the extended symbol - * information rather than in the bootinfo. - */ - /* First, do the kernel name and the kernel type */ - /* Note that this assumed x86 byte order... */ - - /* 'kernel\0\0' */ - *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65; - - /* 'elf kernel\0\0' */ - *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65; - - /* Now the symbol start/end - note that they are - * here in local/physical address - the Kernel - * boot process will relocate the addresses. */ - *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab; - *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab; - - *t++=MODINFO_END; *t++=0; /* end of metadata */ - - /* Since we have symbols we need to make - * sure that the kernel knows its own end - * of memory... It is not _end but after - * the symbols and the metadata... */ - bsdinfo.bi_kernend = virt_to_phys(t); - - /* Signal locore.s that we have a valid bootinfo - * structure that was completely filled in. */ - freebsd_howto |= 0x80000000; - } - - xstart32(entry, freebsd_howto, NODEV, 0, 0, 0, - virt_to_phys(&bsdinfo), 0, 0, 0); - longjmp(restart_etherboot, -2); -} -#endif - -#ifdef AOUT_IMAGE -static void aout_freebsd_probe(void) -{ - image_type = Aout; - if (((astate.head.a_midmag >> 16) & 0xffff) == 0) { - /* Some other a.out variants have a different - * value, and use other alignments (e.g. 1K), - * not the 4K used by FreeBSD. */ - image_type = Aout_FreeBSD; - printf("/FreeBSD"); - off = -(astate.head.a_entry & 0xff000000); - astate.head.a_entry += off; - } -} - -static void aout_freebsd_boot(void) -{ - if (image_type == Aout_FreeBSD) { - memset(&bsdinfo, 0, sizeof(bsdinfo)); - bsdinfo.bi_basemem = meminfo.basememsize; - bsdinfo.bi_extmem = meminfo.memsize; - bsdinfo.bi_memsizes_valid = 1; - bsdinfo.bi_version = BOOTINFO_VERSION; - bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF); - bsdinfo.bi_nfs_diskless = NULL; - bsdinfo.bi_size = sizeof(bsdinfo); - xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0, - virt_to_phys(&bsdinfo), 0, 0, 0); - longjmp(restart_etherboot, -2); - } -} -#endif diff --git a/roms/ipxe/src/arch/i386/core/gdbmach.c b/roms/ipxe/src/arch/i386/core/gdbmach.c index 68b37c040..4232c7553 100644 --- a/roms/ipxe/src/arch/i386/core/gdbmach.c +++ b/roms/ipxe/src/arch/i386/core/gdbmach.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/core/linux/linuxprefix.S b/roms/ipxe/src/arch/i386/core/linux/linuxprefix.S new file mode 100644 index 000000000..398d3cb21 --- /dev/null +++ b/roms/ipxe/src/arch/i386/core/linux/linuxprefix.S @@ -0,0 +1,28 @@ +#include + + .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/roms/ipxe/src/arch/i386/core/pic8259.c b/roms/ipxe/src/arch/i386/core/pic8259.c index 0264c0c1b..0a9ea2e03 100644 --- a/roms/ipxe/src/arch/i386/core/pic8259.c +++ b/roms/ipxe/src/arch/i386/core/pic8259.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/core/rdtsc_timer.c b/roms/ipxe/src/arch/i386/core/rdtsc_timer.c index d2a8cc84f..2f31afc66 100644 --- a/roms/ipxe/src/arch/i386/core/rdtsc_timer.c +++ b/roms/ipxe/src/arch/i386/core/rdtsc_timer.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/core/relocate.c b/roms/ipxe/src/arch/i386/core/relocate.c index 47450e757..b9b029443 100644 --- a/roms/ipxe/src/arch/i386/core/relocate.c +++ b/roms/ipxe/src/arch/i386/core/relocate.c @@ -42,7 +42,7 @@ extern char _etextdata[]; */ __asmcall void relocate ( struct i386_all_regs *ix86 ) { struct memory_map memmap; - unsigned long start, end, size, padded_size; + unsigned long start, end, size, padded_size, max; unsigned long new_start, new_end; unsigned i; @@ -57,6 +57,13 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) { "...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. */ @@ -67,18 +74,18 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) { DBG ( "Considering [%llx,%llx)\n", region->start, region->end); - /* Truncate block to MAX_ADDR. This will be less than - * 4GB, which means that we can get away with using - * just 32-bit arithmetic after this stage. + /* 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_ADDR ) { - DBG ( "...starts after MAX_ADDR=%lx\n", MAX_ADDR ); + if ( region->start > max ) { + DBG ( "...starts after max=%lx\n", max ); continue; } r_start = region->start; - if ( region->end > MAX_ADDR ) { - DBG ( "...end truncated to MAX_ADDR=%lx\n", MAX_ADDR ); - r_end = MAX_ADDR; + if ( region->end > max ) { + DBG ( "...end truncated to max=%lx\n", max ); + r_end = max; } else { r_end = region->end; } diff --git a/roms/ipxe/src/arch/i386/core/runtime.c b/roms/ipxe/src/arch/i386/core/runtime.c new file mode 100644 index 000000000..18ca7936e --- /dev/null +++ b/roms/ipxe/src/arch/i386/core/runtime.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2011 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Command line and initrd passed to iPXE at runtime + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** 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 = "", + .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, "" ) ) != 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/roms/ipxe/src/arch/i386/core/video_subr.c b/roms/ipxe/src/arch/i386/core/video_subr.c index 6885ad9af..306c6d56c 100644 --- a/roms/ipxe/src/arch/i386/core/video_subr.c +++ b/roms/ipxe/src/arch/i386/core/video_subr.c @@ -11,6 +11,14 @@ #include #include #include "vga.h" +#include + +/* 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; @@ -97,6 +105,7 @@ static void vga_putc(int byte) 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 ) = { diff --git a/roms/ipxe/src/arch/i386/core/wince_loader.c b/roms/ipxe/src/arch/i386/core/wince_loader.c deleted file mode 100644 index f452b659b..000000000 --- a/roms/ipxe/src/arch/i386/core/wince_loader.c +++ /dev/null @@ -1,273 +0,0 @@ -#define LOAD_DEBUG 0 - -static int get_x_header(unsigned char *data, unsigned long now); -static void jump_2ep(); -static unsigned char ce_signature[] = {'B', '0', '0', '0', 'F', 'F', '\n',}; -static char ** ep; - -#define BOOT_ARG_PTR_LOCATION 0x001FFFFC - -typedef struct _BOOT_ARGS{ - unsigned char ucVideoMode; - unsigned char ucComPort; - unsigned char ucBaudDivisor; - unsigned char ucPCIConfigType; - - unsigned long dwSig; - #define BOOTARG_SIG 0x544F4F42 - unsigned long dwLen; - - unsigned char ucLoaderFlags; - unsigned char ucEshellFlags; - unsigned char ucEdbgAdapterType; - unsigned char ucEdbgIRQ; - - unsigned long dwEdbgBaseAddr; - unsigned long dwEdbgDebugZone; - unsigned long dwDHCPLeaseTime; - unsigned long dwEdbgFlags; - - unsigned long dwEBootFlag; - unsigned long dwEBootAddr; - unsigned long dwLaunchAddr; - - unsigned long pvFlatFrameBuffer; - unsigned short vesaMode; - unsigned short cxDisplayScreen; - unsigned short cyDisplayScreen; - unsigned short cxPhysicalScreen; - unsigned short cyPhysicalScreen; - unsigned short cbScanLineLength; - unsigned short bppScreen; - - unsigned char RedMaskSize; - unsigned char REdMaskPosition; - unsigned char GreenMaskSize; - unsigned char GreenMaskPosition; - unsigned char BlueMaskSize; - unsigned char BlueMaskPosition; -} BOOT_ARGS; - -BOOT_ARGS BootArgs; - -static struct segment_info{ - unsigned long addr; // Section Address - unsigned long size; // Section Size - unsigned long checksum; // Section CheckSum -} X; - -#define PSIZE (1500) //Max Packet Size -#define DSIZE (PSIZE+12) -static unsigned long dbuffer_available =0; -static unsigned long not_loadin =0; -static unsigned long d_now =0; - -unsigned long entry; -static unsigned long ce_curaddr; - - -static sector_t ce_loader(unsigned char *data, unsigned int len, int eof); -static os_download_t wince_probe(unsigned char *data, unsigned int len) -{ - if (strncmp(ce_signature, data, sizeof(ce_signature)) != 0) { - return 0; - } - printf("(WINCE)"); - return ce_loader; -} - -static sector_t ce_loader(unsigned char *data, unsigned int len, int eof) -{ - static unsigned char dbuffer[DSIZE]; - int this_write = 0; - static int firsttime = 1; - - /* - * new packet in, we have to - * [1] copy data to dbuffer, - * - * update... - * [2] dbuffer_available - */ - memcpy( (dbuffer+dbuffer_available), data, len); //[1] - dbuffer_available += len; // [2] - len = 0; - - d_now = 0; - -#if 0 - printf("dbuffer_available =%ld \n", dbuffer_available); -#endif - - if (firsttime) - { - d_now = sizeof(ce_signature); - printf("String Physical Address = %lx \n", - *(unsigned long *)(dbuffer+d_now)); - - d_now += sizeof(unsigned long); - printf("Image Size = %ld [%lx]\n", - *(unsigned long *)(dbuffer+d_now), - *(unsigned long *)(dbuffer+d_now)); - - d_now += sizeof(unsigned long); - dbuffer_available -= d_now; - - d_now = (unsigned long)get_x_header(dbuffer, d_now); - firsttime = 0; - } - - if (not_loadin == 0) - { - d_now = get_x_header(dbuffer, d_now); - } - - while ( not_loadin > 0 ) - { - /* dbuffer do not have enough data to loading, copy all */ -#if LOAD_DEBUG - printf("[0] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[0] d_now = [%ld] \n", d_now); -#endif - - if( dbuffer_available <= not_loadin) - { - this_write = dbuffer_available ; - memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write ); - ce_curaddr += this_write; - not_loadin -= this_write; - - /* reset index and available in the dbuffer */ - dbuffer_available = 0; - d_now = 0; -#if LOAD_DEBUG - printf("[1] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[1] d_now = [%ld], this_write = [%d] \n", - d_now, this_write); -#endif - - // get the next packet... - return (0); - } - - /* dbuffer have more data then loading ... , copy partital.... */ - else - { - this_write = not_loadin; - memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write); - ce_curaddr += this_write; - not_loadin = 0; - - /* reset index and available in the dbuffer */ - dbuffer_available -= this_write; - d_now += this_write; -#if LOAD_DEBUG - printf("[2] not_loadin = [%ld], dbuffer_available = [%ld] \n", - not_loadin, dbuffer_available); - printf("[2] d_now = [%ld], this_write = [%d] \n\n", - d_now, this_write); -#endif - - /* dbuffer not empty, proceed processing... */ - - // don't have enough data to get_x_header.. - if ( dbuffer_available < (sizeof(unsigned long) * 3) ) - { -// printf("we don't have enough data remaining to call get_x. \n"); - memcpy( (dbuffer+0), (dbuffer+d_now), dbuffer_available); - return (0); - } - else - { -#if LOAD_DEBUG - printf("with remaining data to call get_x \n"); - printf("dbuffer available = %ld , d_now = %ld\n", - dbuffer_available, d_now); -#endif - d_now = get_x_header(dbuffer, d_now); - } - } - } - return (0); -} - -static int get_x_header(unsigned char *dbuffer, unsigned long now) -{ - X.addr = *(unsigned long *)(dbuffer + now); - X.size = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)); - X.checksum = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)*2); - - if (X.addr == 0) - { - entry = X.size; - done(1); - printf("Entry Point Address = [%lx] \n", entry); - jump_2ep(); - } - - if (!prep_segment(X.addr, X.addr + X.size, X.addr + X.size, 0, 0)) { - longjmp(restart_etherboot, -2); - } - - ce_curaddr = X.addr; - now += sizeof(unsigned long)*3; - - /* re-calculate dbuffer available... */ - dbuffer_available -= sizeof(unsigned long)*3; - - /* reset index of this section */ - not_loadin = X.size; - -#if 1 - printf("\n"); - printf("\t Section Address = [%lx] \n", X.addr); - printf("\t Size = %d [%lx]\n", X.size, X.size); - printf("\t Checksum = %ld [%lx]\n", X.checksum, X.checksum); -#endif -#if LOAD_DEBUG - printf("____________________________________________\n"); - printf("\t dbuffer_now = %ld \n", now); - printf("\t dbuffer available = %ld \n", dbuffer_available); - printf("\t not_loadin = %ld \n", not_loadin); -#endif - - return now; -} - -static void jump_2ep() -{ - BootArgs.ucVideoMode = 1; - BootArgs.ucComPort = 1; - BootArgs.ucBaudDivisor = 1; - BootArgs.ucPCIConfigType = 1; // do not fill with 0 - - BootArgs.dwSig = BOOTARG_SIG; - BootArgs.dwLen = sizeof(BootArgs); - - if(BootArgs.ucVideoMode == 0) - { - BootArgs.cxDisplayScreen = 640; - BootArgs.cyDisplayScreen = 480; - BootArgs.cxPhysicalScreen = 640; - BootArgs.cyPhysicalScreen = 480; - BootArgs.bppScreen = 16; - BootArgs.cbScanLineLength = 1024; - BootArgs.pvFlatFrameBuffer = 0x800a0000; // ollie say 0x98000000 - } - else if(BootArgs.ucVideoMode != 0xFF) - { - BootArgs.cxDisplayScreen = 0; - BootArgs.cyDisplayScreen = 0; - BootArgs.cxPhysicalScreen = 0; - BootArgs.cyPhysicalScreen = 0; - BootArgs.bppScreen = 0; - BootArgs.cbScanLineLength = 0; - BootArgs.pvFlatFrameBuffer = 0; - } - - ep = phys_to_virt(BOOT_ARG_PTR_LOCATION); - *ep= virt_to_phys(&BootArgs); - xstart32(entry); -} diff --git a/roms/ipxe/src/arch/i386/core/x86_io.c b/roms/ipxe/src/arch/i386/core/x86_io.c deleted file mode 100644 index 2fba0680c..000000000 --- a/roms/ipxe/src/arch/i386/core/x86_io.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along 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 -#include - -/** @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/roms/ipxe/src/arch/i386/drivers/net/undi.c b/roms/ipxe/src/arch/i386/drivers/net/undi.c index 34fd09562..2bc54824c 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undi.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -140,7 +141,7 @@ static struct pci_device_id undipci_nics[] = { PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ), }; -struct pci_driver undipci_driver __pci_driver = { +struct pci_driver undipci_driver __pci_driver_fallback = { .ids = undipci_nics, .id_count = ( sizeof ( undipci_nics ) / sizeof ( undipci_nics[0] ) ), .probe = undipci_probe, diff --git a/roms/ipxe/src/arch/i386/drivers/net/undiload.c b/roms/ipxe/src/arch/i386/drivers/net/undiload.c index c278db795..0edfa35dc 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undiload.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undiload.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/drivers/net/undinet.c b/roms/ipxe/src/arch/i386/drivers/net/undinet.c index 56bd62886..6205c809b 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undinet.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undinet.c @@ -13,12 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include +#include #include #include #include @@ -34,7 +37,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include - /** @file * * UNDI network device driver @@ -63,6 +65,15 @@ struct undi_nic { /** @} */ +/** 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 + +/** Alignment of received frame payload */ +#define UNDI_RX_ALIGN 16 + static void undinet_close ( struct net_device *netdev ); /** Address of UNDI entry point */ @@ -160,6 +171,10 @@ static int undinet_isr_triggered ( void ) { 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 * @@ -169,8 +184,14 @@ static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd ); */ 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; - size_t len = iob_len ( iobuf ); + 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 @@ -183,15 +204,49 @@ static int undinet_transmit ( struct net_device *netdev, * 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_tbd ); + undi_transmit.DestAddr.offset = __from_data16 ( &undinet_destaddr ); undi_transmit.TBD.segment = rm_ds; undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd ); @@ -248,6 +303,7 @@ static void undinet_poll ( struct net_device *netdev ) { struct s_PXENV_UNDI_ISR undi_isr; struct io_buffer *iobuf = NULL; size_t len; + size_t reserve_len; size_t frag_len; size_t max_frag_len; int rc; @@ -295,6 +351,8 @@ static void undinet_poll ( struct net_device *netdev ) { /* Packet fragment received */ len = undi_isr.FrameLength; frag_len = undi_isr.BufferLength; + reserve_len = ( -undi_isr.FrameHeaderLength & + ( UNDI_RX_ALIGN - 1 ) ); if ( ( len == 0 ) || ( len < frag_len ) ) { /* Don't laugh. VMWare does it. */ DBGC ( undinic, "UNDINIC %p reported insane " @@ -303,15 +361,17 @@ static void undinet_poll ( struct net_device *netdev ) { 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; + iobuf = alloc_iob ( reserve_len + 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; + } + iob_reserve ( iobuf, reserve_len ); } max_frag_len = iob_tailroom ( iobuf ); if ( frag_len > max_frag_len ) { @@ -482,12 +542,13 @@ int undinet_probe ( struct undi_device *undi ) { struct undi_nic *undinic; struct s_PXENV_START_UNDI start_undi; struct s_PXENV_UNDI_STARTUP undi_startup; - struct s_PXENV_UNDI_INITIALIZE undi_initialize; + 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 */ @@ -524,12 +585,27 @@ int undinet_probe ( struct undi_device *undi ) { &undi_startup, sizeof ( undi_startup ) ) ) != 0 ) goto err_undi_startup; - memset ( &undi_initialize, 0, sizeof ( undi_initialize ) ); - if ( ( rc = pxeparent_call ( undinet_entry, - PXENV_UNDI_INITIALIZE, - &undi_initialize, - sizeof ( undi_initialize ))) != 0 ) - goto err_undi_initialize; + /* 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; @@ -539,6 +615,7 @@ int undinet_probe ( struct undi_device *undi ) { &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", @@ -558,8 +635,10 @@ int undinet_probe ( struct undi_device *undi ) { 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 ) + 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", diff --git a/roms/ipxe/src/arch/i386/drivers/net/undionly.c b/roms/ipxe/src/arch/i386/drivers/net/undionly.c index c38b574db..028fac5d9 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undionly.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undionly.c @@ -13,16 +13,19 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include +#include #include #include #include @@ -62,15 +65,21 @@ static int undibus_probe ( struct root_device *rootdev ) { } /* Add to device hierarchy */ - strncpy ( undi->dev.name, "UNDI", - ( sizeof ( undi->dev.name ) - 1 ) ); + 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); diff --git a/roms/ipxe/src/arch/i386/drivers/net/undipreload.c b/roms/ipxe/src/arch/i386/drivers/net/undipreload.c index a4b2f4ac7..81d7a80eb 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undipreload.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undipreload.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/drivers/net/undirom.c b/roms/ipxe/src/arch/i386/drivers/net/undirom.c index 2463d9698..b54c6170f 100644 --- a/roms/ipxe/src/arch/i386/drivers/net/undirom.c +++ b/roms/ipxe/src/arch/i386/drivers/net/undirom.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c b/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c index d18e8b809..b23f2c356 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c b/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c index 1ecd07ddd..25c8dad2d 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -23,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #define ATTR_BOLD 0x08 @@ -48,6 +50,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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; @@ -163,6 +171,14 @@ static void bios_putchar ( int character ) { /* 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" @@ -201,6 +217,8 @@ static const char ansi_sequences[] = { 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 */ @@ -311,4 +329,5 @@ struct console_driver bios_console __console_driver = { .putchar = bios_putchar, .getchar = bios_getchar, .iskey = bios_iskey, + .usage = CONSOLE_PCBIOS, }; diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S b/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S index eeed51f89..cea17ef8e 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ) diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c b/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c index ea116fe50..e5f713728 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c @@ -12,7 +12,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c b/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c index cc5fc28f7..c1788b3a3 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c @@ -12,7 +12,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c b/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c index 493d2c201..cf6592264 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c b/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c index c572914f2..5c74b0431 100644 --- a/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c +++ b/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c b/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c index 79585cde8..f86f180ce 100644 --- a/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c +++ b/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/roms/ipxe/src/arch/i386/hci/commands/reboot_cmd.c b/roms/ipxe/src/arch/i386/hci/commands/reboot_cmd.c index d6a1d9a36..74c69c94e 100644 --- a/roms/ipxe/src/arch/i386/hci/commands/reboot_cmd.c +++ b/roms/ipxe/src/arch/i386/hci/commands/reboot_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/roms/ipxe/src/arch/i386/image/bootsector.c b/roms/ipxe/src/arch/i386/image/bootsector.c index f96cf201e..ab3cf94c2 100644 --- a/roms/ipxe/src/arch/i386/image/bootsector.c +++ b/roms/ipxe/src/arch/i386/image/bootsector.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -79,9 +80,22 @@ int call_bootsector ( unsigned int segment, unsigned int offset, "movw %%ss, %%ax\n\t" "movw %%ax, %%cs:saved_ss\n\t" "movw %%sp, %%cs:saved_sp\n\t" - /* Jump to boot sector */ + /* Prepare jump to boot sector */ "pushw %%bx\n\t" "pushw %%di\n\t" + /* Clear all registers */ + "xorl %%eax, %%eax\n\t" + "xorl %%ebx, %%ebx\n\t" + "xorl %%ecx, %%ecx\n\t" + /* %edx contains drive number */ + "xorl %%esi, %%esi\n\t" + "xorl %%edi, %%edi\n\t" + "xorl %%ebp, %%ebp\n\t" + "movw %%ax, %%ds\n\t" + "movw %%ax, %%es\n\t" + "movw %%ax, %%fs\n\t" + "movw %%ax, %%gs\n\t" + /* Jump to boot sector */ "sti\n\t" "lret\n\t" /* Preserved variables */ diff --git a/roms/ipxe/src/arch/i386/image/bzimage.c b/roms/ipxe/src/arch/i386/image/bzimage.c index cc7aecab4..12be17793 100644 --- a/roms/ipxe/src/arch/i386/image/bzimage.c +++ b/roms/ipxe/src/arch/i386/image/bzimage.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -32,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -214,7 +216,8 @@ static void bzimage_update_header ( struct image *image, } else { bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC; bzimg->cmdline_magic.offset = bzimg->rm_cmdline; - bzimg->bzhdr.setup_move_size = bzimg->rm_memsz; + if ( bzimg->version >= 0x0200 ) + bzimg->bzhdr.setup_move_size = bzimg->rm_memsz; } /* Set video mode */ @@ -302,11 +305,10 @@ static int bzimage_parse_cmdline ( struct image *image, * @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 ) { +static void 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 */ @@ -316,8 +318,32 @@ static int bzimage_set_cmdline ( struct image *image, copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline, cmdline, cmdline_len ); DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline ); +} - return 0; +/** + * Parse standalone image command line for cpio parameters + * + * @v image bzImage file + * @v cpio CPIO header + * @v cmdline Command line + */ +static void bzimage_parse_cpio_cmdline ( struct image *image, + struct cpio_header *cpio, + const char *cmdline ) { + char *arg; + char *end; + unsigned int mode; + + /* Look for "mode=" */ + if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { + arg += 5; + mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); + if ( *end && ( *end != ' ' ) ) { + DBGC ( image, "bzImage %p strange \"mode=\"" + "terminator '%c'\n", image, *end ); + } + cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); + } } /** @@ -326,14 +352,17 @@ static int bzimage_set_cmdline ( struct image *image, * @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 + * @ret len Length of loaded image, rounded up to INITRD_ALIGN */ static size_t bzimage_load_initrd ( struct image *image, struct image *initrd, userptr_t address ) { char *filename = initrd->cmdline; + char *cmdline; struct cpio_header cpio; size_t offset = 0; + size_t name_len; + size_t pad_len; /* Do not include kernel image itself as an initrd */ if ( initrd == image ) @@ -341,24 +370,28 @@ static size_t bzimage_load_initrd ( struct image *image, /* 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 ); + cmdline = strchr ( filename, ' ' ); + name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) + : strlen ( filename ) ) + 1 /* NUL */ ); 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 ( cmdline ) { + bzimage_parse_cpio_cmdline ( image, &cpio, + ( cmdline + 1 /* ' ' */ )); + } if ( address ) { copy_to_user ( address, offset, &cpio, sizeof ( cpio ) ); } offset += sizeof ( cpio ); if ( address ) { + memset_user ( address, offset, 0, name_len ); copy_to_user ( address, offset, filename, - name_len ); + ( name_len - 1 /* NUL (or space) */ ) ); } offset += name_len; offset = ( ( offset + 0x03 ) & ~0x03 ); @@ -366,80 +399,146 @@ static size_t bzimage_load_initrd ( struct image *image, /* Copy in initrd image body */ if ( address ) - memcpy_user ( address, offset, initrd->data, 0, initrd->len ); - offset += initrd->len; + memmove_user ( address, offset, initrd->data, 0, 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 ) ); + DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" + "%s%s\n", image, initrd, user_to_phys ( address, 0 ), + user_to_phys ( address, offset ), + user_to_phys ( address, ( offset + initrd->len ) ), + ( filename ? " " : "" ), ( filename ? filename : "" ) ); + DBGC2_MD5A ( image, user_to_phys ( address, offset ), + user_to_virt ( address, offset ), initrd->len ); } + offset += initrd->len; + + /* Round up to multiple of INITRD_ALIGN and zero-pad */ + pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) ); + if ( address ) + memset_user ( address, offset, 0, pad_len ); + offset += pad_len; - /* Round up to 4-byte boundary */ - offset = ( ( offset + 0x03 ) & ~0x03 ); return offset; } /** - * Load initrds, if any + * Check that initrds can be loaded * * @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 ) { +static int bzimage_check_initrds ( struct image *image, + struct bzimage_context *bzimg ) { struct image *initrd; - size_t total_len = 0; - physaddr_t address; + userptr_t bottom; + size_t len = 0; int rc; - /* Add up length of all initrd images */ - for_each_image ( initrd ) - total_len += bzimage_load_initrd ( image, initrd, UNULL ); + /* Calculate total loaded length of initrds */ + for_each_image ( initrd ) { - /* Give up if no initrd images found */ - if ( ! total_len ) - return 0; + /* Skip kernel */ + if ( initrd == image ) + continue; + + /* Calculate length */ + len += bzimage_load_initrd ( image, initrd, UNULL ); + + DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n", + image, initrd, user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ), + ( initrd->cmdline ? " " : "" ), + ( initrd->cmdline ? initrd->cmdline : "" ) ); + DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ), + user_to_virt ( initrd->data, 0 ), initrd->len ); + } + + /* Calculate lowest usable address */ + bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ); - /* Find a suitable start address. Try 1MB boundaries, - * starting from the downloaded kernel image itself and - * working downwards until we hit an available region. + /* Check that total length fits within space available for + * reshuffling. This is a conservative check, since CPIO + * headers are not present during reshuffling, but this + * doesn't hurt and keeps the code simple. */ - 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; + if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) { + DBGC ( image, "bzImage %p failed reshuffle check: %s\n", + image, strerror ( rc ) ); + return rc; } - /* Record initrd location */ - bzimg->ramdisk_image = address; - bzimg->ramdisk_size = total_len; + /* Check that total length fits within kernel's memory limit */ + if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) { + DBGC ( image, "bzImage %p not enough space for initrds\n", + image ); + return -ENOBUFS; + } + + return 0; +} + +/** + * Load initrds, if any + * + * @v image bzImage image + * @v bzimg bzImage context + */ +static void bzimage_load_initrds ( struct image *image, + struct bzimage_context *bzimg ) { + struct image *initrd; + struct image *highest = NULL; + struct image *other; + userptr_t top; + userptr_t dest; + size_t len; + + /* Reshuffle initrds into desired order */ + initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) ); - /* Construct initrd */ - DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n", - image, address, ( address + total_len ) ); + /* Find highest initrd */ for_each_image ( initrd ) { - address += bzimage_load_initrd ( image, initrd, - phys_to_user ( address ) ); + if ( ( highest == NULL ) || + ( userptr_sub ( initrd->data, highest->data ) > 0 ) ) { + highest = initrd; + } } - return 0; + /* Do nothing if there are no initrds */ + if ( ! highest ) + return; + + /* Find highest usable address */ + top = userptr_add ( highest->data, + ( ( highest->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ) ); + if ( user_to_phys ( top, 0 ) > bzimg->mem_limit ) + top = phys_to_user ( bzimg->mem_limit ); + DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n", + image, user_to_phys ( top, 0 ) ); + + /* Load initrds in order */ + for_each_image ( initrd ) { + + /* Calculate cumulative length of following + * initrds (including padding). + */ + len = 0; + for_each_image ( other ) { + if ( other == initrd ) + len = 0; + len += bzimage_load_initrd ( image, other, UNULL ); + } + + /* Load initrd at this address */ + dest = userptr_add ( top, -len ); + bzimage_load_initrd ( image, initrd, dest ); + + /* Record initrd location */ + if ( ! bzimg->ramdisk_image ) { + bzimg->ramdisk_image = user_to_phys ( dest, 0 ); + bzimg->ramdisk_size = len; + } + } } /** @@ -472,33 +571,37 @@ static int bzimage_exec ( struct image *image ) { return rc; } + /* Parse command line for bootloader parameters */ + if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0) + return rc; + + /* Check that initrds can be loaded */ + if ( ( rc = bzimage_check_initrds ( image, &bzimg ) ) != 0 ) + return rc; + + /* Remove kernel from image list (without invalidating image pointer) */ + unregister_image ( image_get ( image ) ); + /* 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; + bzimage_set_cmdline ( image, &bzimg, cmdline ); + + /* Prepare for exiting. Must do this before loading initrds, + * since loading the initrds will corrupt the external heap. + */ + shutdown_boot(); /* Load any initrds */ - if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 ) - return rc; + bzimage_load_initrds ( image, &bzimg ); /* 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 ); diff --git a/roms/ipxe/src/arch/i386/image/com32.c b/roms/ipxe/src/arch/i386/image/com32.c index d6e48ebe1..5cc9a4476 100644 --- a/roms/ipxe/src/arch/i386/image/com32.c +++ b/roms/ipxe/src/arch/i386/image/com32.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/roms/ipxe/src/arch/i386/image/comboot.c b/roms/ipxe/src/arch/i386/image/comboot.c index 0b924cce2..1ec02331d 100644 --- a/roms/ipxe/src/arch/i386/image/comboot.c +++ b/roms/ipxe/src/arch/i386/image/comboot.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** @@ -228,7 +229,7 @@ static int comboot_identify ( struct image *image ) { ++ext; - if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) { + if ( strcasecmp( ext, "cbt" ) ) { DBGC ( image, "COMBOOT %p: unrecognized extension %s\n", image, ext ); return -ENOEXEC; diff --git a/roms/ipxe/src/arch/i386/image/elfboot.c b/roms/ipxe/src/arch/i386/image/elfboot.c index 89e70a3b8..a867a9566 100644 --- a/roms/ipxe/src/arch/i386/image/elfboot.c +++ b/roms/ipxe/src/arch/i386/image/elfboot.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -42,10 +43,11 @@ FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 ); */ 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 ) ) != 0 ) { + if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) { DBGC ( image, "ELF %p could not load: %s\n", image, strerror ( rc ) ); return rc; diff --git a/roms/ipxe/src/arch/i386/image/initrd.c b/roms/ipxe/src/arch/i386/image/initrd.c new file mode 100644 index 000000000..eaba3a645 --- /dev/null +++ b/roms/ipxe/src/arch/i386/image/initrd.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include + +/** @file + * + * Initial ramdisk (initrd) reshuffling + * + */ + +/** Maximum address available for initrd */ +userptr_t initrd_top; + +/** Minimum address available for initrd */ +userptr_t initrd_bottom; + +/** + * Squash initrds as high as possible in memory + * + * @v top Highest possible address + * @ret used Lowest address used by initrds + */ +static userptr_t initrd_squash_high ( userptr_t top ) { + userptr_t current = top; + struct image *initrd; + struct image *highest; + size_t len; + + /* Squash up any initrds already within or below the region */ + while ( 1 ) { + + /* Find the highest image not yet in its final position */ + highest = NULL; + for_each_image ( initrd ) { + if ( ( userptr_sub ( initrd->data, current ) < 0 ) && + ( ( highest == NULL ) || + ( userptr_sub ( initrd->data, + highest->data ) > 0 ) ) ) { + highest = initrd; + } + } + if ( ! highest ) + break; + + /* Move this image to its final position */ + len = ( ( highest->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + current = userptr_sub ( current, len ); + DBGC ( &images, "INITRD squashing %s [%#08lx,%#08lx)->" + "[%#08lx,%#08lx)\n", highest->name, + user_to_phys ( highest->data, 0 ), + user_to_phys ( highest->data, highest->len ), + user_to_phys ( current, 0 ), + user_to_phys ( current, highest->len ) ); + memmove_user ( current, 0, highest->data, 0, highest->len ); + highest->data = current; + } + + /* Copy any remaining initrds (e.g. embedded images) to the region */ + for_each_image ( initrd ) { + if ( userptr_sub ( initrd->data, top ) >= 0 ) { + len = ( ( initrd->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + current = userptr_sub ( current, len ); + DBGC ( &images, "INITRD copying %s [%#08lx,%#08lx)->" + "[%#08lx,%#08lx)\n", initrd->name, + user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ), + user_to_phys ( current, 0 ), + user_to_phys ( current, initrd->len ) ); + memcpy_user ( current, 0, initrd->data, 0, + initrd->len ); + initrd->data = current; + } + } + + return current; +} + +/** + * Swap position of two adjacent initrds + * + * @v low Lower initrd + * @v high Higher initrd + * @v free Free space + * @v free_len Length of free space + */ +static void initrd_swap ( struct image *low, struct image *high, + userptr_t free, size_t free_len ) { + size_t len = 0; + size_t frag_len; + size_t new_len; + + DBGC ( &images, "INITRD swapping %s [%#08lx,%#08lx)<->[%#08lx,%#08lx) " + "%s\n", low->name, user_to_phys ( low->data, 0 ), + user_to_phys ( low->data, low->len ), + user_to_phys ( high->data, 0 ), + user_to_phys ( high->data, high->len ), high->name ); + + /* Round down length of free space */ + free_len &= ~( INITRD_ALIGN - 1 ); + assert ( free_len > 0 ); + + /* Swap image data */ + while ( len < high->len ) { + + /* Calculate maximum fragment length */ + frag_len = ( high->len - len ); + if ( frag_len > free_len ) + frag_len = free_len; + new_len = ( ( len + frag_len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + + /* Swap fragments */ + memcpy_user ( free, 0, high->data, len, frag_len ); + memmove_user ( low->data, new_len, low->data, len, low->len ); + memcpy_user ( low->data, len, free, 0, frag_len ); + len = new_len; + } + + /* Adjust data pointers */ + high->data = low->data; + low->data = userptr_add ( low->data, len ); +} + +/** + * Swap position of any two adjacent initrds not currently in the correct order + * + * @v free Free space + * @v free_len Length of free space + * @ret swapped A pair of initrds was swapped + */ +static int initrd_swap_any ( userptr_t free, size_t free_len ) { + struct image *low; + struct image *high; + size_t padded_len; + userptr_t adjacent; + + /* Find any pair of initrds that can be swapped */ + for_each_image ( low ) { + + /* Calculate location of adjacent image (if any) */ + padded_len = ( ( low->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + adjacent = userptr_add ( low->data, padded_len ); + + /* Search for adjacent image */ + for_each_image ( high ) { + + /* If we have found the adjacent image, swap and exit */ + if ( high->data == adjacent ) { + initrd_swap ( low, high, free, free_len ); + return 1; + } + + /* Stop search if all remaining potential + * adjacent images are already in the correct + * order. + */ + if ( high == low ) + break; + } + } + + /* Nothing swapped */ + return 0; +} + +/** + * Dump initrd locations (for debug) + * + */ +static void initrd_dump ( void ) { + struct image *initrd; + + /* Do nothing unless debugging is enabled */ + if ( ! DBG_LOG ) + return; + + /* Dump initrd locations */ + for_each_image ( initrd ) { + DBGC ( &images, "INITRD %s at [%#08lx,%#08lx)\n", + initrd->name, user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ) ); + DBGC2_MD5A ( &images, user_to_phys ( initrd->data, 0 ), + user_to_virt ( initrd->data, 0 ), initrd->len ); + } +} + +/** + * Reshuffle initrds into desired order at top of memory + * + * @v bottom Lowest address available for initrds + * + * After this function returns, the initrds have been rearranged in + * memory and the external heap structures will have been corrupted. + * Reshuffling must therefore take place immediately prior to jumping + * to the loaded OS kernel; no further execution within iPXE is + * permitted. + */ +void initrd_reshuffle ( userptr_t bottom ) { + userptr_t top; + userptr_t used; + userptr_t free; + size_t free_len; + + /* Calculate limits of available space for initrds */ + top = initrd_top; + if ( userptr_sub ( initrd_bottom, bottom ) > 0 ) + bottom = initrd_bottom; + + /* Debug */ + DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n", + user_to_phys ( bottom, 0 ), user_to_phys ( top, 0 ) ); + initrd_dump(); + + /* Squash initrds as high as possible in memory */ + used = initrd_squash_high ( top ); + + /* Calculate available free space */ + free = bottom; + free_len = userptr_sub ( used, free ); + + /* Bubble-sort initrds into desired order */ + while ( initrd_swap_any ( free, free_len ) ) {} + + /* Debug */ + initrd_dump(); +} + +/** + * Check that there is enough space to reshuffle initrds + * + * @v len Total length of initrds (including padding) + * @v bottom Lowest address available for initrds + * @ret rc Return status code + */ +int initrd_reshuffle_check ( size_t len, userptr_t bottom ) { + userptr_t top; + size_t available; + + /* Calculate limits of available space for initrds */ + top = initrd_top; + if ( userptr_sub ( initrd_bottom, bottom ) > 0 ) + bottom = initrd_bottom; + available = userptr_sub ( top, bottom ); + + /* Allow for a sensible minimum amount of free space */ + len += INITRD_MIN_FREE_LEN; + + /* Check for available space */ + return ( ( len < available ) ? 0 : -ENOBUFS ); +} + +/** + * initrd startup function + * + */ +static void initrd_startup ( void ) { + size_t len; + + /* Record largest memory block available. Do this after any + * allocations made during driver startup (e.g. large host + * memory blocks for Infiniband devices, which may still be in + * use at the time of rearranging if a SAN device is hooked) + * but before any allocations for downloaded images (which we + * can safely reuse when rearranging). + */ + len = largest_memblock ( &initrd_bottom ); + initrd_top = userptr_add ( initrd_bottom, len ); +} + +/** initrd startup function */ +struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = { + .startup = initrd_startup, +}; diff --git a/roms/ipxe/src/arch/i386/image/multiboot.c b/roms/ipxe/src/arch/i386/image/multiboot.c index 15e8fd52b..3d6d2bf34 100644 --- a/roms/ipxe/src/arch/i386/image/multiboot.c +++ b/roms/ipxe/src/arch/i386/image/multiboot.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -37,6 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 ); @@ -139,53 +142,60 @@ static void multiboot_build_memmap ( struct image *image, /** * Add command line in base memory * - * @v imgname Image name - * @v cmdline Command line + * @v image Image * @ret physaddr Physical address of command line */ -physaddr_t multiboot_add_cmdline ( const char *imgname, const char *cmdline ) { - char *mb_cmdline; - - if ( ! cmdline ) - cmdline = ""; - - /* Copy command line to base memory buffer */ - mb_cmdline = ( mb_cmdlines + mb_cmdline_offset ); - mb_cmdline_offset += - ( snprintf ( mb_cmdline, - ( sizeof ( mb_cmdlines ) - mb_cmdline_offset ), - "%s %s", imgname, cmdline ) + 1 ); - - /* Truncate to terminating NUL in buffer if necessary */ - if ( mb_cmdline_offset > sizeof ( mb_cmdlines ) ) - mb_cmdline_offset = ( sizeof ( mb_cmdlines ) - 1 ); +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 ); } /** - * Build multiboot module list + * Add multiboot modules * * @v image Multiboot image - * @v modules Module list to fill, or NULL - * @ret count Number of modules + * @v start Start address for modules + * @v mbinfo Multiboot information structure + * @v modules Multiboot module list + * @ret rc Return status code */ -static unsigned int -multiboot_build_module_list ( struct image *image, - struct multiboot_module *modules, - unsigned int limit ) { +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; - unsigned int count = 0; - unsigned int insert; - physaddr_t start; - physaddr_t end; - unsigned int i; + int rc; /* Add each image as a multiboot module */ for_each_image ( module_image ) { - if ( count >= limit ) { + if ( mbinfo->mods_count >= limit ) { DBGC ( image, "MULTIBOOT %p limit of %d modules " "reached\n", image, limit ); break; @@ -195,38 +205,36 @@ multiboot_build_module_list ( struct image *image, if ( module_image == image ) continue; - /* At least some OSes expect the multiboot modules to - * be in ascending order, so we have to support it. - */ - start = user_to_phys ( module_image->data, 0 ); - end = user_to_phys ( module_image->data, module_image->len ); - for ( insert = 0 ; insert < count ; insert++ ) { - if ( start < modules[insert].mod_start ) - break; + /* 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; } - module = &modules[insert]; - memmove ( ( module + 1 ), module, - ( ( count - insert ) * sizeof ( *module ) ) ); - module->mod_start = start; - module->mod_end = end; - module->string = multiboot_add_cmdline ( module_image->name, - module_image->cmdline ); - module->reserved = 0; - - /* We promise to page-align modules */ - assert ( ( module->mod_start & 0xfff ) == 0 ); - count++; - } + /* Copy module */ + memcpy_user ( phys_to_user ( start ), 0, + module_image->data, 0, module_image->len ); - /* Dump module configuration */ - for ( i = 0 ; i < count ; i++ ) { - DBGC ( image, "MULTIBOOT %p module %d is [%x,%x)\n", - image, i, modules[i].mod_start, - modules[i].mod_end ); + /* 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 count; + return 0; } /** @@ -240,7 +248,7 @@ static struct multiboot_info __bss16 ( mbinfo ); #define mbinfo __use_data16 ( mbinfo ) /** The multiboot bootloader name */ -static char __data16_array ( mb_bootloader_name, [] ) = "iPXE " VERSION; +static char __bss16_array ( mb_bootloader_name, [32] ); #define mb_bootloader_name __use_data16 ( mb_bootloader_name ) /** The multiboot memory map */ @@ -305,11 +313,12 @@ static int multiboot_find_header ( struct image *image, * @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 *entry, physaddr_t *max ) { size_t offset; size_t filesz; size_t memsz; @@ -340,8 +349,9 @@ static int multiboot_load_raw ( struct image *image, /* Copy image to segment */ memcpy_user ( buffer, 0, image->data, offset, filesz ); - /* Record execution entry point */ + /* Record execution entry point and maximum used address */ *entry = hdr->mb.entry_addr; + *max = ( hdr->mb.load_addr + memsz ); return 0; } @@ -351,13 +361,15 @@ static int multiboot_load_raw ( struct image *image, * * @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 ) { +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 ) ) != 0 ) { + if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) { DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n", image, strerror ( rc ) ); return rc; @@ -375,6 +387,7 @@ static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) { 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 */ @@ -396,8 +409,8 @@ static int multiboot_exec ( struct image *image ) { * the ELF header if present, and Solaris relies on this * behaviour. */ - if ( ( ( rc = multiboot_load_elf ( image, &entry ) ) != 0 ) && - ( ( rc = multiboot_load_raw ( image, &hdr, &entry ) ) != 0 ) ) + if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) && + ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 )) return rc; /* Populate multiboot information structure */ @@ -405,12 +418,16 @@ static int multiboot_exec ( struct image *image ) { 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->name, image->cmdline ); - mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules, - ( sizeof(mbmodules) / sizeof(mbmodules[0]) ) ); + mbinfo.cmdline = multiboot_add_cmdline ( image ); mbinfo.mods_addr = virt_to_phys ( mbmodules ); mbinfo.mmap_addr = virt_to_phys ( mbmemmap ); + snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ), + "iPXE %s", product_version ); 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. diff --git a/roms/ipxe/src/arch/i386/image/nbi.c b/roms/ipxe/src/arch/i386/image/nbi.c index c516bb2ec..d3e523e92 100644 --- a/roms/ipxe/src/arch/i386/image/nbi.c +++ b/roms/ipxe/src/arch/i386/image/nbi.c @@ -10,6 +10,7 @@ #include #include #include +#include /** @file * @@ -94,12 +95,6 @@ struct ebinfo { 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 * @@ -281,6 +276,10 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) { * @ret rc Return status code, if image returns */ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) { + struct ebinfo loaderinfo = { + product_major_version, product_minor_version, + 0 + }; int discard_D, discard_S, discard_b; int rc; diff --git a/roms/ipxe/src/arch/i386/image/pxe_image.c b/roms/ipxe/src/arch/i386/image/pxe_image.c index bdccc93d6..4a7d874be 100644 --- a/roms/ipxe/src/arch/i386/image/pxe_image.c +++ b/roms/ipxe/src/arch/i386/image/pxe_image.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -35,6 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 ); +/** PXE command line */ +const char *pxe_cmdline; + /** * Execute PXE image * @@ -62,16 +66,29 @@ static int pxe_exec ( struct image *image ) { image ); return -ENODEV; } + netdev_get ( netdev ); /* Activate PXE */ pxe_activate ( netdev ); + /* Set PXE command line */ + pxe_cmdline = image->cmdline; + /* Start PXE NBP */ rc = pxe_start_nbp(); + /* Clear PXE command line */ + pxe_cmdline = NULL; + /* Deactivate PXE */ pxe_deactivate(); + /* Try to reopen network device. Ignore errors, since the NBP + * may have called PXENV_STOP_UNDI. + */ + netdev_open ( netdev ); + netdev_put ( netdev ); + return rc; } diff --git a/roms/ipxe/src/arch/i386/image/sdi.c b/roms/ipxe/src/arch/i386/image/sdi.c new file mode 100644 index 000000000..df1c3a868 --- /dev/null +++ b/roms/ipxe/src/arch/i386/image/sdi.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * System Deployment Image (SDI) + * + * Based on the MSDN article "RAM boot using SDI in Windows XP + * Embedded with Service Pack 1", available at the time of writing + * from: + * + * http://msdn.microsoft.com/en-us/library/ms838543.aspx + */ + +FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 ); + +/** + * Parse SDI image header + * + * @v image SDI file + * @v sdi SDI header to fill in + * @ret rc Return status code + */ +static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) { + + /* Sanity check */ + if ( image->len < sizeof ( *sdi ) ) { + DBGC ( image, "SDI %p too short for SDI header\n", image ); + return -ENOEXEC; + } + + /* Read in header */ + copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) ); + + /* Check signature */ + if ( sdi->magic != SDI_MAGIC ) { + DBGC ( image, "SDI %p is not an SDI image\n", image ); + return -ENOEXEC; + } + + return 0; +} + +/** + * Execute SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_exec ( struct image *image ) { + struct sdi_header sdi; + uint32_t sdiptr; + int rc; + + /* Parse image header */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + /* Check that image is bootable */ + if ( sdi.boot_size == 0 ) { + DBGC ( image, "SDI %p is not bootable\n", image ); + return -ENOTTY; + } + DBGC ( image, "SDI %p image at %08lx+%08zx\n", + image, user_to_phys ( image->data, 0 ), image->len ); + DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image, + user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size ); + + /* Copy boot code */ + memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0, + image->data, sdi.boot_offset, sdi.boot_size ); + + /* Jump to boot code */ + sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF ); + __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" ) + : : "i" ( SDI_BOOT_SEG ), + "i" ( SDI_BOOT_OFF ), + "d" ( sdiptr ) ); + + /* There is no way for the image to return, since we provide + * no return address. + */ + assert ( 0 ); + + return -ECANCELED; /* -EIMPOSSIBLE */ +} + +/** + * Probe SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_probe ( struct image *image ) { + struct sdi_header sdi; + int rc; + + /* Parse image */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + return 0; +} + +/** SDI image type */ +struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = { + .name = "SDI", + .probe = sdi_probe, + .exec = sdi_exec, +}; diff --git a/roms/ipxe/src/arch/i386/include/bios.h b/roms/ipxe/src/arch/i386/include/bios.h index 70bb73dac..fadb9f1b7 100644 --- a/roms/ipxe/src/arch/i386/include/bios.h +++ b/roms/ipxe/src/arch/i386/include/bios.h @@ -4,6 +4,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define BDA_SEG 0x0040 +#define BDA_EQUIPMENT_WORD 0x0010 #define BDA_FBMS 0x0013 #define BDA_NUM_DRIVES 0x0075 diff --git a/roms/ipxe/src/arch/i386/include/bits/byteswap.h b/roms/ipxe/src/arch/i386/include/bits/byteswap.h index ddbd40edb..f3d30a254 100644 --- a/roms/ipxe/src/arch/i386/include/bits/byteswap.h +++ b/roms/ipxe/src/arch/i386/include/bits/byteswap.h @@ -1,43 +1,70 @@ -#ifndef ETHERBOOT_BITS_BYTESWAP_H -#define ETHERBOOT_BITS_BYTESWAP_H +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H + +/** @file + * + * Byte-order swapping functions + * + */ + +#include FILE_LICENCE ( GPL2_OR_LATER ); -static inline __attribute__ ((always_inline, const)) uint16_t -__bswap_variable_16(uint16_t x) -{ - __asm__("xchgb %b0,%h0\n\t" - : "=q" (x) - : "0" (x)); +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, const)) uint32_t -__bswap_variable_32(uint32_t x) -{ - __asm__("xchgb %b0,%h0\n\t" - "rorl $16,%0\n\t" - "xchgb %b0,%h0" - : "=q" (x) - : "0" (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, const)) uint64_t -__bswap_variable_64(uint64_t x) -{ - union { - uint64_t qword; - uint32_t dword[2]; - } u; - - u.qword = x; - u.dword[0] = __bswap_variable_32(u.dword[0]); - u.dword[1] = __bswap_variable_32(u.dword[1]); - __asm__("xchgl %0,%1" - : "=r" ( u.dword[0] ), "=r" ( u.dword[1] ) - : "0" ( u.dword[0] ), "1" ( u.dword[1] ) ); - return u.qword; +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 /* ETHERBOOT_BITS_BYTESWAP_H */ +#endif /* _BITS_BYTESWAP_H */ diff --git a/roms/ipxe/src/arch/i386/include/bits/cpu.h b/roms/ipxe/src/arch/i386/include/bits/cpu.h deleted file mode 100644 index 83339dddd..000000000 --- a/roms/ipxe/src/arch/i386/include/bits/cpu.h +++ /dev/null @@ -1,86 +0,0 @@ -#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/roms/ipxe/src/arch/i386/include/bits/entropy.h b/roms/ipxe/src/arch/i386/include/bits/entropy.h new file mode 100644 index 000000000..6dcceec6d --- /dev/null +++ b/roms/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 + +#endif /* _BITS_ENTROPY_H */ diff --git a/roms/ipxe/src/arch/i386/include/bits/errfile.h b/roms/ipxe/src/arch/i386/include/bits/errfile.h deleted file mode 100644 index 32b8a085b..000000000 --- a/roms/ipxe/src/arch/i386/include/bits/errfile.h +++ /dev/null @@ -1,42 +0,0 @@ -#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_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/roms/ipxe/src/arch/i386/include/bits/io.h b/roms/ipxe/src/arch/i386/include/bits/io.h deleted file mode 100644 index f3ecf89bb..000000000 --- a/roms/ipxe/src/arch/i386/include/bits/io.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_IO_H -#define _BITS_IO_H - -/** @file - * - * i386-specific I/O API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include - -#endif /* _BITS_IO_H */ diff --git a/roms/ipxe/src/arch/i386/include/bits/time.h b/roms/ipxe/src/arch/i386/include/bits/time.h new file mode 100644 index 000000000..24dd020e9 --- /dev/null +++ b/roms/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 + +#endif /* _BITS_TIME_H */ diff --git a/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h b/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h index 902caff95..184177219 100644 --- a/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h +++ b/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h @@ -33,7 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); '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 ( 6 ) +#define DHCP_ARCH_CLIENT_ARCHITECTURE \ + DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_IA32 ) #define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 3, 10 /* v3.10 */ ) diff --git a/roms/ipxe/src/arch/i386/include/initrd.h b/roms/ipxe/src/arch/i386/include/initrd.h new file mode 100644 index 000000000..c25d0924b --- /dev/null +++ b/roms/ipxe/src/arch/i386/include/initrd.h @@ -0,0 +1,29 @@ +#ifndef _INITRD_H +#define _INITRD_H + +/** @file + * + * Initial ramdisk (initrd) reshuffling + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** Minimum alignment for initrds + * + * Chosen to maximise memcpy() speeds + */ +#define INITRD_ALIGN 4 + +/** Minimum free space required to reshuffle initrds + * + * Chosen to avoid absurdly long reshuffling times + */ +#define INITRD_MIN_FREE_LEN ( 512 * 1024 ) + +extern void initrd_reshuffle ( userptr_t bottom ); +extern int initrd_reshuffle_check ( size_t len, userptr_t bottom ); + +#endif /* _INITRD_H */ diff --git a/roms/ipxe/src/arch/i386/include/int13.h b/roms/ipxe/src/arch/i386/include/int13.h index a14ebb2e9..5d36b6378 100644 --- a/roms/ipxe/src/arch/i386/include/int13.h +++ b/roms/ipxe/src/arch/i386/include/int13.h @@ -45,6 +45,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 /** @} */ @@ -69,6 +71,19 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** 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 */ @@ -217,6 +232,18 @@ struct int13_cdrom_specification { 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 */ @@ -261,7 +288,162 @@ struct master_boot_record { uint16_t magic; } __attribute__ (( packed )); -/** Use natural BIOS drive number */ -#define INT13_USE_NATURAL_DRIVE 0xff +/** 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/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h b/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h index 097945487..689227b70 100644 --- a/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h +++ b/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h @@ -15,4 +15,15 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h b/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h new file mode 100644 index 000000000..72a0f714f --- /dev/null +++ b/roms/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 +#include + +/** 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/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h b/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h new file mode 100644 index 000000000..6c3cf2104 --- /dev/null +++ b/roms/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 + +#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/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h b/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h new file mode 100644 index 000000000..c0dfe3f88 --- /dev/null +++ b/roms/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/roms/ipxe/src/arch/i386/include/ipxe/vmware.h b/roms/ipxe/src/arch/i386/include/ipxe/vmware.h new file mode 100644 index 000000000..2ac65f436 --- /dev/null +++ b/roms/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 + +/** 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/roms/ipxe/src/arch/i386/include/ipxe/x86_io.h b/roms/ipxe/src/arch/i386/include/ipxe/x86_io.h deleted file mode 100644 index a79501e2c..000000000 --- a/roms/ipxe/src/arch/i386/include/ipxe/x86_io.h +++ /dev/null @@ -1,153 +0,0 @@ -#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/roms/ipxe/src/arch/i386/include/librm.h b/roms/ipxe/src/arch/i386/include/librm.h index c6992f643..801f586b8 100644 --- a/roms/ipxe/src/arch/i386/include/librm.h +++ b/roms/ipxe/src/arch/i386/include/librm.h @@ -68,6 +68,12 @@ UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) { return trivial_userptr_add ( userptr, offset ); } +static inline __always_inline off_t +UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr, + userptr_t subtrahend ) { + return trivial_userptr_sub ( userptr, subtrahend ); +} + static inline __always_inline void UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, diff --git a/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h b/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h index 822b3eba9..a36d9cfa1 100644 --- a/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h +++ b/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h @@ -33,7 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); '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 ( 0 ) +#define DHCP_ARCH_CLIENT_ARCHITECTURE \ + DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_X86 ) #define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 2, 1 /* v2.1 */ ) diff --git a/roms/ipxe/src/arch/i386/include/pic8259.h b/roms/ipxe/src/arch/i386/include/pic8259.h index f8e20c4c4..a07e97d30 100644 --- a/roms/ipxe/src/arch/i386/include/pic8259.h +++ b/roms/ipxe/src/arch/i386/include/pic8259.h @@ -9,6 +9,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #ifndef PIC8259_H #define PIC8259_H +#include + /* For segoff_t */ #include "realmode.h" diff --git a/roms/ipxe/src/arch/i386/include/pxe.h b/roms/ipxe/src/arch/i386/include/pxe.h index 909c8d818..0206f683a 100644 --- a/roms/ipxe/src/arch/i386/include/pxe.h +++ b/roms/ipxe/src/arch/i386/include/pxe.h @@ -6,8 +6,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include "pxe_types.h" #include "pxe_api.h" #include +#include -/* Parameter block for pxenv_unknown() */ +/** 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 )); @@ -72,6 +76,45 @@ union u_PXENV_ANY { 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 @@ -144,9 +187,12 @@ struct pcir_header { #define PCIR_SIGNATURE \ ( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) ) - extern struct net_device *pxe_netdev; +extern const char *pxe_cmdline; 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/roms/ipxe/src/arch/i386/include/pxe_api.h b/roms/ipxe/src/arch/i386/include/pxe_api.h index 9b40187ed..e4396efb2 100644 --- a/roms/ipxe/src/arch/i386/include/pxe_api.h +++ b/roms/ipxe/src/arch/i386/include/pxe_api.h @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * As an alternative, at your option, you may use this file under the * following terms, known as the "MIT license": @@ -252,9 +253,6 @@ struct s_PXENV_UNLOAD_STACK { typedef struct s_PXENV_UNLOAD_STACK PXENV_UNLOAD_STACK_t; -extern PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK - *unload_stack ); - /** @} */ /* pxenv_unload_stack */ /** @defgroup pxenv_get_cached_info PXENV_GET_CACHED_INFO @@ -403,9 +401,6 @@ struct bootph { typedef struct bootph BOOTPLAYER_t; -extern PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO - *get_cached_info ); - /** @} */ /* pxenv_get_cached_info */ /** @defgroup pxenv_restart_tftp PXENV_RESTART_TFTP @@ -423,9 +418,6 @@ struct s_PXENV_TFTP_READ_FILE; typedef struct s_PXENV_RESTART_TFTP PXENV_RESTART_TFTP_t; -extern PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE - *restart_tftp ); - /** @} */ /* pxenv_restart_tftp */ /** @defgroup pxenv_start_undi PXENV_START_UNDI @@ -496,8 +488,6 @@ struct s_PXENV_START_UNDI { typedef struct s_PXENV_START_UNDI PXENV_START_UNDI_t; -extern PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ); - /** @} */ /* pxenv_start_undi */ /** @defgroup pxenv_stop_undi PXENV_STOP_UNDI @@ -517,8 +507,6 @@ struct s_PXENV_STOP_UNDI { typedef struct s_PXENV_STOP_UNDI PXENV_STOP_UNDI_t; -extern PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ); - /** @} */ /* pxenv_stop_undi */ /** @defgroup pxenv_start_base PXENV_START_BASE @@ -538,8 +526,6 @@ struct s_PXENV_START_BASE { typedef struct s_PXENV_START_BASE PXENV_START_BASE_t; -extern PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ); - /** @} */ /* pxenv_start_base */ /** @defgroup pxenv_stop_base PXENV_STOP_BASE @@ -559,8 +545,6 @@ struct s_PXENV_STOP_BASE { typedef struct s_PXENV_STOP_BASE PXENV_STOP_BASE_t; -extern PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ); - /** @} */ /* pxenv_stop_base */ /** @} */ /* pxe_preboot_api */ @@ -600,8 +584,6 @@ struct s_PXENV_TFTP_OPEN { typedef struct s_PXENV_TFTP_OPEN PXENV_TFTP_OPEN_t; -extern PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ); - /** @} */ /* pxenv_tftp_open */ /** @defgroup pxenv_tftp_close PXENV_TFTP_CLOSE @@ -621,8 +603,6 @@ struct s_PXENV_TFTP_CLOSE { typedef struct s_PXENV_TFTP_CLOSE PXENV_TFTP_CLOSE_t; -extern PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ); - /** @} */ /* pxenv_tftp_close */ /** @defgroup pxenv_tftp_read PXENV_TFTP_READ @@ -645,8 +625,6 @@ struct s_PXENV_TFTP_READ { typedef struct s_PXENV_TFTP_READ PXENV_TFTP_READ_t; -extern PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ); - /** @} */ /* pxenv_tftp_read */ /** @defgroup pxenv_tftp_read_file PXENV_TFTP_READ_FILE @@ -690,9 +668,6 @@ struct s_PXENV_TFTP_READ_FILE { typedef struct s_PXENV_TFTP_READ_FILE PXENV_TFTP_READ_FILE_t; -extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE - *tftp_read_file ); - /** @} */ /* pxenv_tftp_read_file */ /** @defgroup pxenv_tftp_get_fsize PXENV_TFTP_GET_FSIZE @@ -716,9 +691,6 @@ struct s_PXENV_TFTP_GET_FSIZE { typedef struct s_PXENV_TFTP_GET_FSIZE PXENV_TFTP_GET_FSIZE_t; -extern PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE - *get_fsize ); - /** @} */ /* pxenv_tftp_get_fsize */ /** @} */ /* pxe_tftp_api */ @@ -748,8 +720,6 @@ struct s_PXENV_UDP_OPEN { typedef struct s_PXENV_UDP_OPEN PXENV_UDP_OPEN_t; -extern PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *udp_open ); - /** @} */ /* pxenv_udp_open */ /** @defgroup pxenv_udp_close PXENV_UDP_CLOSE @@ -769,8 +739,6 @@ struct s_PXENV_UDP_CLOSE { typedef struct s_PXENV_UDP_CLOSE PXENV_UDP_CLOSE_t; -extern PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *udp_close ); - /** @} */ /* pxenv_udp_close */ /** @defgroup pxenv_udp_write PXENV_UDP_WRITE @@ -796,8 +764,6 @@ struct s_PXENV_UDP_WRITE { typedef struct s_PXENV_UDP_WRITE PXENV_UDP_WRITE_t; -extern PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *udp_write ); - /** @} */ /* pxenv_udp_write */ /** @defgroup pxenv_udp_read PXENV_UDP_READ @@ -823,8 +789,6 @@ struct s_PXENV_UDP_READ { typedef struct s_PXENV_UDP_READ PXENV_UDP_READ_t; -extern PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *udp_read ); - /** @} */ /* pxenv_udp_read */ /** @} */ /* pxe_udp_api */ @@ -860,9 +824,6 @@ struct s_PXENV_UNDI_STARTUP { typedef struct s_PXENV_UNDI_STARTUP PXENV_UNDI_STARTUP_t; -extern PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP - *undi_startup ); - /** @} */ /* pxenv_undi_startup */ /** @defgroup pxenv_undi_cleanup PXENV_UNDI_CLEANUP @@ -882,9 +843,6 @@ struct s_PXENV_UNDI_CLEANUP { typedef struct s_PXENV_UNDI_CLEANUP PXENV_UNDI_CLEANUP_t; -extern PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP - *undi_cleanup ); - /** @} */ /* pxenv_undi_cleanup */ /** @defgroup pxenv_undi_initialize PXENV_UNDI_INITIALIZE @@ -913,9 +871,6 @@ struct s_PXENV_UNDI_INITIALIZE { typedef struct s_PXENV_UNDI_INITIALIZE PXENV_UNDI_INITIALIZE_t; -extern PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE - *undi_initialize ); - /** @} */ /* pxenv_undi_initialize */ /** @defgroup pxenv_undi_reset_adapter PXENV_UNDI_RESET_ADAPTER @@ -950,9 +905,6 @@ struct s_PXENV_UNDI_RESET { typedef struct s_PXENV_UNDI_RESET PXENV_UNDI_RESET_t; -extern PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET - *undi_reset_adapter ); - /** @} */ /* pxenv_undi_reset_adapter */ /** @defgroup pxenv_undi_shutdown PXENV_UNDI_SHUTDOWN @@ -972,9 +924,6 @@ struct s_PXENV_UNDI_SHUTDOWN { typedef struct s_PXENV_UNDI_SHUTDOWN PXENV_UNDI_SHUTDOWN_t; -extern PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN - *undi_shutdown ); - /** @} */ /* pxenv_undi_shutdown */ /** @defgroup pxenv_undi_open PXENV_UNDI_OPEN @@ -1024,8 +973,6 @@ struct s_PXENV_UNDI_OPEN { typedef struct s_PXENV_UNDI_OPEN PXENV_UNDI_OPEN_t; -extern PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ); - /** @} */ /* pxenv_undi_open */ /** @defgroup pxenv_undi_close PXENV_UNDI_CLOSE @@ -1045,8 +992,6 @@ struct s_PXENV_UNDI_CLOSE { typedef struct s_PXENV_UNDI_CLOSE PXENV_UNDI_CLOSE_t; -extern PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ); - /** @} */ /* pxenv_undi_close */ /** @defgroup pxenv_undi_transmit PXENV_UNDI_TRANSMIT @@ -1122,9 +1067,6 @@ struct s_PXENV_UNDI_TRANSMIT { typedef struct s_PXENV_UNDI_TRANSMIT PXENV_UNDI_TRANSMIT_t; -extern PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT - *undi_transmit ); - /** @} */ /* pxenv_undi_transmit */ /** @defgroup pxenv_undi_set_mcast_address PXENV_UNDI_SET_MCAST_ADDRESS @@ -1146,9 +1088,6 @@ struct s_PXENV_UNDI_SET_MCAST_ADDRESS { typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS PXENV_UNDI_SET_MCAST_ADDRESS_t; -extern PXENV_EXIT_t pxenv_undi_set_mcast_address ( - struct s_PXENV_UNDI_SET_MCAST_ADDRESS *undi_set_mcast_address ); - /** @} */ /* pxenv_undi_set_mcast_address */ /** @defgroup pxenv_undi_set_station_address PXENV_UNDI_SET_STATION_ADDRESS @@ -1169,9 +1108,6 @@ struct s_PXENV_UNDI_SET_STATION_ADDRESS { typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS PXENV_UNDI_SET_STATION_ADDRESS_t; -extern PXENV_EXIT_t pxenv_undi_set_station_address ( - struct s_PXENV_UNDI_SET_STATION_ADDRESS *undi_set_station_address ); - /** @} */ /* pxenv_undi_set_station_address */ /** @defgroup pxenv_undi_set_packet_filter PXENV_UNDI_SET_PACKET_FILTER @@ -1202,9 +1138,6 @@ struct s_PXENV_UNDI_SET_PACKET_FILTER { typedef struct s_PXENV_UNDI_SET_PACKET_FILTER PXENV_UNDI_SET_PACKET_FILTER_t; -extern PXENV_EXIT_t pxenv_undi_set_packet_filter ( - struct s_PXENV_UNDI_SET_PACKET_FILTER *undi_set_packet_filter ); - /** @} */ /* pxenv_undi_set_packet_filter */ /** @defgroup pxenv_undi_get_information PXENV_UNDI_GET_INFORMATION @@ -1248,9 +1181,6 @@ struct s_PXENV_UNDI_GET_INFORMATION { typedef struct s_PXENV_UNDI_GET_INFORMATION PXENV_UNDI_GET_INFORMATION_t; -extern PXENV_EXIT_t pxenv_undi_get_information ( - struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information ); - /** @} */ /* pxenv_undi_get_information */ /** @defgroup pxenv_undi_get_statistics PXENV_UNDI_GET_STATISTICS @@ -1274,9 +1204,6 @@ struct s_PXENV_UNDI_GET_STATISTICS { typedef struct s_PXENV_UNDI_GET_STATISTICS PXENV_UNDI_GET_STATISTICS_t; -extern PXENV_EXIT_t pxenv_undi_get_statistics ( - struct s_PXENV_UNDI_GET_STATISTICS *undi_get_statistics ); - /** @} */ /* pxenv_undi_get_statistics */ /** @defgroup pxenv_undi_clear_statistics PXENV_UNDI_CLEAR_STATISTICS @@ -1296,9 +1223,6 @@ struct s_PXENV_UNDI_CLEAR_STATISTICS { typedef struct s_PXENV_UNDI_CLEAR_STATISTICS PXENV_UNDI_CLEAR_STATISTICS_t; -extern PXENV_EXIT_t pxenv_undi_clear_statistics ( - struct s_PXENV_UNDI_CLEAR_STATISTICS *undi_clear_statistics ); - /** @} */ /* pxenv_undi_clear_statistics */ /** @defgroup pxenv_undi_initiate_diags PXENV_UNDI_INITIATE_DIAGS @@ -1318,9 +1242,6 @@ struct s_PXENV_UNDI_INITIATE_DIAGS { typedef struct s_PXENV_UNDI_INITIATE_DIAGS PXENV_UNDI_INITIATE_DIAGS_t; -extern PXENV_EXIT_t pxenv_undi_initiate_diags ( - struct s_PXENV_UNDI_INITIATE_DIAGS *undi_initiate_diags ); - /** @} */ /* pxenv_undi_initiate_diags */ /** @defgroup pxenv_undi_force_interrupt PXENV_UNDI_FORCE_INTERRUPT @@ -1340,9 +1261,6 @@ struct s_PXENV_UNDI_FORCE_INTERRUPT { typedef struct s_PXENV_UNDI_FORCE_INTERRUPT PXENV_UNDI_FORCE_INTERRUPT_t; -extern PXENV_EXIT_t pxenv_undi_force_interrupt ( - struct s_PXENV_UNDI_FORCE_INTERRUPT *undi_force_interrupt ); - /** @} */ /* pxenv_undi_force_interrupt */ /** @defgroup pxenv_undi_get_mcast_address PXENV_UNDI_GET_MCAST_ADDRESS @@ -1364,9 +1282,6 @@ struct s_PXENV_UNDI_GET_MCAST_ADDRESS { typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS PXENV_UNDI_GET_MCAST_ADDRESS_t; -extern PXENV_EXIT_t pxenv_undi_get_mcast_address ( - struct s_PXENV_UNDI_GET_MCAST_ADDRESS *undi_get_mcast_address ); - /** @} */ /* pxenv_undi_get_mcast_address */ /** @defgroup pxenv_undi_get_nic_type PXENV_UNDI_GET_NIC_TYPE @@ -1427,9 +1342,6 @@ struct s_PXENV_UNDI_GET_NIC_TYPE { typedef struct s_PXENV_UNDI_GET_NIC_TYPE PXENV_UNDI_GET_NIC_TYPE_t; -extern PXENV_EXIT_t pxenv_undi_get_nic_type ( - struct s_PXENV_UNDI_GET_NIC_TYPE *undi_get_nic_type ); - /** @} */ /* pxenv_undi_get_nic_type */ /** @defgroup pxenv_undi_get_iface_info PXENV_UNDI_GET_IFACE_INFO @@ -1488,9 +1400,6 @@ struct s_PXENV_UNDI_GET_IFACE_INFO { typedef struct s_PXENV_UNDI_GET_IFACE_INFO PXENV_UNDI_GET_IFACE_INFO_t; -extern PXENV_EXIT_t pxenv_undi_get_iface_info ( - struct s_PXENV_UNDI_GET_IFACE_INFO *undi_get_iface_info ); - /** @} */ /* pxenv_undi_get_iface_info */ /** @defgroup pxenv_undi_get_state PXENV_UNDI_GET_STATE @@ -1524,9 +1433,6 @@ struct s_PXENV_UNDI_GET_STATE { typedef struct s_PXENV_UNDI_GET_STATE PXENV_UNDI_GET_STATE_t; -extern PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE - *undi_get_state ); - /** @} */ /* pxenv_undi_get_state */ /** @defgroup pxenv_undi_isr PXENV_UNDI_ISR @@ -1595,8 +1501,6 @@ struct s_PXENV_UNDI_ISR { typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t; -extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ); - /** @} */ /* pxenv_undi_isr */ /** @} */ /* pxe_undi_api */ @@ -1608,6 +1512,12 @@ extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ); * @{ */ +/** 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 @@ -1628,8 +1538,6 @@ struct s_PXENV_FILE_OPEN { typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t; -extern PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ); - /** @} */ /* pxenv_file_open */ /** @defgroup pxenv_file_close PXENV_FILE_CLOSE @@ -1650,9 +1558,6 @@ struct s_PXENV_FILE_CLOSE { typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t; -extern PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE - *file_close ); - /** @} */ /* pxenv_file_close */ /** @defgroup pxenv_file_select PXENV_FILE_SELECT @@ -1677,9 +1582,6 @@ struct s_PXENV_FILE_SELECT { typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t; -extern PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT - *file_select ); - /** @} */ /* pxenv_file_select */ /** @defgroup pxenv_file_read PXENV_FILE_READ @@ -1702,8 +1604,6 @@ struct s_PXENV_FILE_READ { typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t; -extern PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ); - /** @} */ /* pxenv_file_read */ /** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE @@ -1725,9 +1625,6 @@ struct s_PXENV_GET_FILE_SIZE { typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t; -extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE - *get_file_size ); - /** @} */ /* pxenv_get_file_size */ /** @defgroup pxenv_file_exec PXENV_FILE_EXEC @@ -1748,8 +1645,6 @@ struct s_PXENV_FILE_EXEC { typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t; -extern PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ); - /** @} */ /* pxenv_file_exec */ /** @defgroup pxenv_file_api_check PXENV_FILE_API_CHECK @@ -1774,8 +1669,6 @@ struct s_PXENV_FILE_API_CHECK { typedef struct s_PXENV_FILE_API_CHECK PXENV_FILE_API_CHECK_t; -extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ); - /** @} */ /* pxenv_file_api_check */ /** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK @@ -1796,10 +1689,29 @@ struct s_PXENV_FILE_EXIT_HOOK { typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t; -extern PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook ); - /** @} */ /* pxenv_file_exit_hook */ +/** @defgroup pxenv_file_cmdline PXENV_FILE_CMDLINE + * + * FILE CMDLINE + * + * @{ + */ + +/** PXE API function code for pxenv_file_cmdline() */ +#define PXENV_FILE_CMDLINE 0x00e8 + +/** Parameter block for pxenv_file_cmdline() */ +struct s_PXENV_FILE_CMDLINE { + PXENV_STATUS_t Status; /**< PXE status code */ + UINT16_t BufferSize; /**< Data buffer size */ + SEGOFF16_t Buffer; /**< Data buffer */ +} __attribute__ (( packed )); + +typedef struct s_PXENV_FILE_CMDLINE PXENV_FILE_CMDLINE_t; + +/** @} */ /* pxe_file_cmdline */ + /** @} */ /* pxe_file_api */ /** @defgroup pxe_loader_api PXE Loader API @@ -1847,8 +1759,6 @@ struct s_UNDI_LOADER { typedef struct s_UNDI_LOADER UNDI_LOADER_t; -extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ); - /** @} */ /* pxe_loader_api */ /** @} */ /* pxe */ diff --git a/roms/ipxe/src/arch/i386/include/rtc.h b/roms/ipxe/src/arch/i386/include/rtc.h new file mode 100644 index 000000000..2a6abbae5 --- /dev/null +++ b/roms/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 + +/** 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/roms/ipxe/src/arch/i386/include/sdi.h b/roms/ipxe/src/arch/i386/include/sdi.h new file mode 100644 index 000000000..fc486402d --- /dev/null +++ b/roms/ipxe/src/arch/i386/include/sdi.h @@ -0,0 +1,39 @@ +#ifndef _SDI_H +#define _SDI_H + +/** @file + * + * System Deployment Image (SDI) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** SDI image header */ +struct sdi_header { + /** Signature */ + uint32_t magic; + /** Version (as an ASCII string) */ + uint32_t version; + /** Reserved */ + uint8_t reserved[8]; + /** Boot code offset */ + uint64_t boot_offset; + /** Boot code size */ + uint64_t boot_size; +} __attribute__ (( packed )); + +/** SDI image signature */ +#define SDI_MAGIC \ + ( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) ) + +/** SDI boot segment */ +#define SDI_BOOT_SEG 0x0000 + +/** SDI boot offset */ +#define SDI_BOOT_OFF 0x7c00 + +/** Constant to binary-OR with physical address of SDI image */ +#define SDI_WTF 0x41 + +#endif /* _SDI_H */ diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c b/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c index cde3d0603..2ecc24ea5 100644 --- a/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c +++ b/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c b/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c index 70c3986b1..3cb8756f7 100644 --- a/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c +++ b/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/int13.c b/roms/ipxe/src/arch/i386/interface/pcbios/int13.c index 392dbd5fb..263f861e4 100644 --- a/roms/ipxe/src/arch/i386/interface/pcbios/int13.c +++ b/roms/ipxe/src/arch/i386/interface/pcbios/int13.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -75,9 +76,9 @@ struct int13_drive { /** Underlying block device interface */ struct interface block; - /** BIOS in-use drive number (0x80-0xff) */ + /** BIOS in-use drive number (0x00-0xff) */ unsigned int drive; - /** BIOS natural drive number (0x80-0xff) + /** 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 @@ -91,6 +92,13 @@ struct int13_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 * @@ -117,6 +125,11 @@ struct int13_drive { */ 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 */ @@ -130,17 +143,85 @@ static struct segoff __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 ); /** - * Number of BIOS drives + * 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) * - * Note that this is the number of drives in the system as a whole - * (i.e. a mirror of the counter at 40:75), rather than a count of the - * number of emulated drives. + * @v int13 Emulated drive + * @ret blocks Number of blocks */ -static uint8_t num_drives; +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 { @@ -319,6 +400,10 @@ static int int13_rw ( struct int13_drive *int13, uint64_t lba, size_t frag_len; int rc; + /* Translate to underlying blocksize */ + lba <<= int13->blksize_shift; + count <<= int13->blksize_shift; + while ( count ) { /* Determine fragment length */ @@ -371,63 +456,245 @@ static int int13_read_capacity ( struct int13_drive *int13 ) { } /** - * Guess INT 13 drive geometry + * 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 ( struct int13_drive *int13 ) { - struct master_boot_record mbr; +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 guessed_heads = 255; - unsigned int guessed_sectors_per_track = 63; - unsigned long blocks; - unsigned long blocks_per_cyl; unsigned int i; int rc; - /* Don't even try when the blksize is invalid for C/H/S access */ - if ( int13->capacity.blksize != INT13_BLKSIZE ) - return 0; + /* Default guess is xx/255/63 */ + *heads = 255; + *sectors = 63; /* Read partition table */ - if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( &mbr ), + 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", + 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 ) ); + DBGC2_HDA ( int13, 0, mbr, sizeof ( *mbr ) ); DBGC ( int13, "INT13 drive %02x has signature %08x\n", - int13->drive, mbr.signature ); + int13->drive, mbr->signature ); - /* Scan through partition table and modify guesses for heads - * and sectors_per_track if we find any used partitions. + /* 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]; + partition = &mbr->partitions[i]; if ( ! partition->type ) continue; - guessed_heads = ( PART_HEAD ( partition->chs_end ) + 1 ); - guessed_sectors_per_track = PART_SECTOR ( partition->chs_end ); + *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, guessed_heads, - guessed_sectors_per_track, ( i + 1 ) ); + "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_capacity ( 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_per_track; + int13->sectors_per_track = guessed_sectors; if ( ! int13->cylinders ) { /* Avoid attempting a 64-bit divide on a 32-bit system */ - blocks = ( ( int13->capacity.blocks <= ULONG_MAX ) ? - int13->capacity.blocks : ULONG_MAX ); + blocks = int13_capacity32 ( int13 ); blocks_per_cyl = ( int13->heads * int13->sectors_per_track ); assert ( blocks_per_cyl != 0 ); int13->cylinders = ( blocks / blocks_per_cyl ); @@ -441,19 +708,40 @@ static int int13_guess_geometry ( struct int13_drive *int13 ) { /** * Update BIOS drive count */ -static void int13_set_num_drives ( void ) { +static void int13_sync_num_drives ( void ) { struct int13_drive *int13; + uint8_t *counter; + uint8_t max_drive; + uint8_t required; - /* Get current drive count */ + /* 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 ) { - if ( num_drives <= ( int13->drive & 0x7f ) ) - num_drives = ( ( int13->drive & 0x7f ) + 1 ); + 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 ); } @@ -461,13 +749,14 @@ static void int13_set_num_drives ( void ) { * 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_num_drives != num_drives ) { - int13_set_num_drives(); - DBG ( "INT13 fixing up number of drives from %d to %d\n", - check_num_drives, num_drives ); + if ( ( check_equipment_word != equipment_word ) || + ( check_num_drives != num_drives ) ) { + int13_sync_num_drives(); } } @@ -535,20 +824,25 @@ static int int13_rw_sectors ( struct int13_drive *int13, int rc; /* Validate blocksize */ - if ( int13->capacity.blksize != INT13_BLKSIZE ) { + if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) { DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) " "for non-extended read/write\n", - int13->drive, int13->capacity.blksize ); + int13->drive, int13_blksize ( int13 ) ); return -INT13_STATUS_INVALID; } - + /* Calculate parameters */ cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch ); - assert ( cylinder < int13->cylinders ); head = ix86->regs.dh; - assert ( head < int13->heads ); sector = ( ix86->regs.cl & 0x3f ); - assert ( ( sector >= 1 ) && ( sector <= int13->sectors_per_track ) ); + 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; @@ -625,10 +919,27 @@ static int int13_get_parameters ( struct int13_drive *int13, 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; - get_real ( ix86->regs.dl, BDA_SEG, BDA_NUM_DRIVES ); + 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; } @@ -645,11 +956,15 @@ static int int13_get_disk_type ( struct int13_drive *int13, uint32_t blocks; DBGC2 ( int13, "Get disk type\n" ); - blocks = ( ( int13->capacity.blocks <= 0xffffffffUL ) ? - int13->capacity.blocks : 0xffffffffUL ); - ix86->regs.cx = ( blocks >> 16 ); - ix86->regs.dx = ( blocks & 0xffff ); - return INT13_DISK_TYPE_HDD; + + 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; + } } /** @@ -698,6 +1013,13 @@ static int int13_extended_rw ( struct int13_drive *int13, 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 ) ) ); @@ -916,14 +1238,14 @@ static int int13_get_extended_parameters ( struct int13_drive *int13, memset ( ¶ms, 0, sizeof ( params ) ); params.flags = INT13_FL_DMA_TRANSPARENT; if ( ( int13->cylinders < 1024 ) && - ( int13->capacity.blocks <= INT13_MAX_CHS_SECTORS ) ) { + ( 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.blocks; - params.sector_size = int13->capacity.blksize; + params.sectors = int13_capacity ( int13 ); + params.sector_size = int13_blksize ( int13 ); memset ( ¶ms.dpte, 0xff, sizeof ( params.dpte ) ); if ( ( rc = int13_device_path_info ( int13, ¶ms.dpi ) ) != 0 ) { DBGC ( int13, "INT13 drive %02x could not provide device " @@ -958,6 +1280,77 @@ static int int13_get_extended_parameters ( struct int13_drive *int13, 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 * @@ -981,12 +1374,17 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) { 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; } - continue; } DBGC2 ( int13, "INT13,%02x (%02x): ", - ix86->regs.ah, int13->drive ); + ix86->regs.ah, bios_drive ); switch ( command ) { case INT13_RESET: @@ -1025,6 +1423,12 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) { 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; @@ -1083,26 +1487,28 @@ static void int13_hook_vector ( void ) { "popw 6(%%bp)\n\t" /* Fix up %dl: * - * INT 13,15 : do nothing + * 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" - "je 2f\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 2f\n\t" - "pushw %%ds\n\t" - "pushw %1\n\t" - "popw %%ds\n\t" - "movb %c2, %%dl\n\t" - "popw %%ds\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 */ - "\n2:\n\t" + "\n3:\n\t" "movw %%bp, %%sp\n\t" "popw %%bp\n\t" "iret\n\t" ) - : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) ); + : : "i" ( int13 ) ); hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper, &int13_vector ); @@ -1116,6 +1522,20 @@ static void int13_unhook_vector ( void ) { &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 * @@ -1140,6 +1560,7 @@ static void int13_block_close ( struct int13_drive *int13, int 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 ), }; @@ -1164,24 +1585,21 @@ static void int13_free ( struct refcnt *refcnt ) { * Hook INT 13 emulated drive * * @v uri URI - * @v drive Requested drive number - * @ret drive Assigned drive number, or negative error + * @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; - uint8_t num_drives; unsigned int natural_drive; + void *scratch; int rc; - /* Calculate drive number */ - get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES ); - natural_drive = ( num_drives | 0x80 ); - if ( drive == INT13_USE_NATURAL_DRIVE ) - drive = natural_drive; - drive |= 0x80; + /* 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 ) { @@ -1209,10 +1627,19 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) { /* Read device capacity */ if ( ( rc = int13_read_capacity ( int13 ) ) != 0 ) - return rc; + 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 ) ) != 0 ) + if ( ( rc = int13_guess_geometry ( int13, scratch ) ) != 0 ) goto err_guess_geometry; DBGC ( int13, "INT13 drive %02x (naturally %02x) registered with C/H/S " @@ -1229,11 +1656,16 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) { list_add ( &int13->list, &int13s ); /* Update BIOS drive count */ - int13_set_num_drives(); + int13_sync_num_drives(); - return int13->drive; + 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 ); @@ -1300,52 +1732,171 @@ static void int13_unhook ( unsigned int drive ) { } /** - * Attempt to boot from an INT 13 drive + * 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 - * - * 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; - int status, signature; - int discard_c, discard_d; - int rc; - - DBG ( "INT13 drive %02x booting\n", drive ); - - /* Use INT 13 to read the boot sector */ +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" - "pushw $0\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" - "xorl %%eax, %%eax\n\t" + "xorw %%ax, %%ax\n\t" "\n1:\n\t" - "movzwl %%es:0x7dfe, %%ebx\n\t" "popw %%es\n\t" ) - : "=a" ( status ), "=b" ( signature ), + : "=a" ( status ), "=b" ( discard_b ), "=c" ( discard_c ), "=d" ( discard_d ) - : "a" ( 0x0201 ), "b" ( 0x7c00 ), + : "a" ( 0x0201 ), "b" ( *address ), "c" ( 1 ), "d" ( drive ) ); - if ( status ) + 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 ) - /* Check signature is correct */ - if ( signature != be16_to_cpu ( 0x55aa ) ) { - DBG ( "INT13 drive %02x invalid disk signature %#04x (should " - "be 0x55aa)\n", drive, cpu_to_be16 ( signature ) ); +/** 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 @@ -1355,7 +1906,8 @@ static int int13_boot ( unsigned int drive ) { get_memmap ( &memmap ); /* Jump to boot sector */ - if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) { + if ( ( rc = call_bootsector ( address.segment, address.offset, + drive ) ) != 0 ) { DBG ( "INT13 drive %02x boot returned: %s\n", drive, strerror ( rc ) ); return rc; @@ -1428,6 +1980,7 @@ static int int13_describe ( unsigned int drive ) { 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 ); diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c index 16736e194..c382e3c36 100644 --- a/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ b/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -30,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** Alignment of external allocated memory */ @@ -52,56 +54,20 @@ 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 long heap_size = 0; - unsigned int i; - - DBG ( "Allocating external heap\n" ); - - get_memmap ( &memmap ); - 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; - } - } +static void init_eheap ( void ) { + userptr_t base; - if ( ! heap_size ) { - DBG ( "No external heap available\n" ); - return -ENOMEM; - } - - DBG ( "External heap grows downwards from %lx\n", - user_to_phys ( top, 0 ) ); - return 0; + heap_size = largest_memblock ( &base ); + bottom = top = userptr_add ( base, heap_size ); + DBG ( "External heap grows downwards from %lx (size %zx)\n", + user_to_phys ( top, 0 ), heap_size ); } /** @@ -110,6 +76,7 @@ static int init_eheap ( void ) { */ static void ecollect_free ( void ) { struct external_memory extmem; + size_t len; /* Walk the free list and collect empty blocks */ while ( bottom != top ) { @@ -119,8 +86,9 @@ static void ecollect_free ( void ) { break; DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ), user_to_phys ( bottom, extmem.size ) ); - bottom = userptr_add ( bottom, - ( extmem.size + sizeof ( extmem ) ) ); + len = ( extmem.size + sizeof ( extmem ) ); + bottom = userptr_add ( bottom, len ); + heap_size += len; } } @@ -138,13 +106,10 @@ 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; - } + /* (Re)initialise external memory allocator if necessary */ + if ( bottom == top ) + init_eheap(); /* Get block properties into extmem */ if ( ptr && ( ptr != UNOWHERE ) ) { @@ -153,7 +118,12 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { 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; @@ -163,6 +133,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { /* 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; @@ -174,8 +148,9 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { user_to_phys ( new, new_size )); memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ? 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 ) { @@ -193,7 +168,8 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { /* Collect any free blocks and update hidden memory region */ ecollect_free(); - hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ), + hide_umalloc ( user_to_phys ( bottom, ( ( bottom == top ) ? + 0 : -sizeof ( extmem ) ) ), user_to_phys ( top, 0 ) ); return ( new_size ? new : UNOWHERE ); diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c b/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c index 511ec6232..61873039f 100644 --- a/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c +++ b/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c b/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c new file mode 100644 index 000000000..fad421c2a --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * RTC-based entropy source + * + */ + +#include +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c b/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c new file mode 100644 index 000000000..67041d4ca --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * RTC-based time source + * + */ + +#include +#include +#include +#include + +/** + * 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c index f32080006..b8e73a061 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -41,73 +42,6 @@ extern void pxe_int_1a ( void ); /** INT 1A hooked flag */ static int int_1a_hooked = 0; -/** A function pointer to hold any PXE API call - * - * Used by pxe_api_call() to avoid large swathes of duplicated code. - */ -union pxenv_call { - PXENV_EXIT_t ( * any ) ( union u_PXENV_ANY * ); - PXENV_EXIT_t ( * unknown ) ( struct s_PXENV_UNKNOWN * ); - PXENV_EXIT_t ( * unload_stack ) ( struct s_PXENV_UNLOAD_STACK * ); - PXENV_EXIT_t ( * get_cached_info ) - ( struct s_PXENV_GET_CACHED_INFO * ); - PXENV_EXIT_t ( * restart_tftp ) ( struct s_PXENV_TFTP_READ_FILE * ); - PXENV_EXIT_t ( * start_undi ) ( struct s_PXENV_START_UNDI * ); - PXENV_EXIT_t ( * stop_undi ) ( struct s_PXENV_STOP_UNDI * ); - PXENV_EXIT_t ( * start_base ) ( struct s_PXENV_START_BASE * ); - PXENV_EXIT_t ( * stop_base ) ( struct s_PXENV_STOP_BASE * ); - PXENV_EXIT_t ( * tftp_open ) ( struct s_PXENV_TFTP_OPEN * ); - PXENV_EXIT_t ( * tftp_close ) ( struct s_PXENV_TFTP_CLOSE * ); - PXENV_EXIT_t ( * tftp_read ) ( struct s_PXENV_TFTP_READ * ); - PXENV_EXIT_t ( * tftp_read_file ) ( struct s_PXENV_TFTP_READ_FILE * ); - PXENV_EXIT_t ( * tftp_get_fsize ) ( struct s_PXENV_TFTP_GET_FSIZE * ); - PXENV_EXIT_t ( * udp_open ) ( struct s_PXENV_UDP_OPEN * ); - PXENV_EXIT_t ( * udp_close ) ( struct s_PXENV_UDP_CLOSE * ); - PXENV_EXIT_t ( * udp_write ) ( struct s_PXENV_UDP_WRITE * ); - PXENV_EXIT_t ( * udp_read ) ( struct s_PXENV_UDP_READ * ); - PXENV_EXIT_t ( * undi_startup ) ( struct s_PXENV_UNDI_STARTUP * ); - PXENV_EXIT_t ( * undi_cleanup ) ( struct s_PXENV_UNDI_CLEANUP * ); - PXENV_EXIT_t ( * undi_initialize ) - ( struct s_PXENV_UNDI_INITIALIZE * ); - PXENV_EXIT_t ( * undi_reset_adapter ) ( struct s_PXENV_UNDI_RESET * ); - PXENV_EXIT_t ( * undi_shutdown ) ( struct s_PXENV_UNDI_SHUTDOWN * ); - PXENV_EXIT_t ( * undi_open ) ( struct s_PXENV_UNDI_OPEN * ); - PXENV_EXIT_t ( * undi_close ) ( struct s_PXENV_UNDI_CLOSE * ); - PXENV_EXIT_t ( * undi_transmit ) ( struct s_PXENV_UNDI_TRANSMIT * ); - PXENV_EXIT_t ( * undi_set_mcast_address ) - ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS * ); - PXENV_EXIT_t ( * undi_set_station_address ) - ( struct s_PXENV_UNDI_SET_STATION_ADDRESS * ); - PXENV_EXIT_t ( * undi_set_packet_filter ) - ( struct s_PXENV_UNDI_SET_PACKET_FILTER * ); - PXENV_EXIT_t ( * undi_get_information ) - ( struct s_PXENV_UNDI_GET_INFORMATION * ); - PXENV_EXIT_t ( * undi_get_statistics ) - ( struct s_PXENV_UNDI_GET_STATISTICS * ); - PXENV_EXIT_t ( * undi_clear_statistics ) - ( struct s_PXENV_UNDI_CLEAR_STATISTICS * ); - PXENV_EXIT_t ( * undi_initiate_diags ) - ( struct s_PXENV_UNDI_INITIATE_DIAGS * ); - PXENV_EXIT_t ( * undi_force_interrupt ) - ( struct s_PXENV_UNDI_FORCE_INTERRUPT * ); - PXENV_EXIT_t ( * undi_get_mcast_address ) - ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS * ); - PXENV_EXIT_t ( * undi_get_nic_type ) - ( struct s_PXENV_UNDI_GET_NIC_TYPE * ); - PXENV_EXIT_t ( * undi_get_iface_info ) - ( struct s_PXENV_UNDI_GET_IFACE_INFO * ); - PXENV_EXIT_t ( * undi_get_state ) ( struct s_PXENV_UNDI_GET_STATE * ); - PXENV_EXIT_t ( * undi_isr ) ( struct s_PXENV_UNDI_ISR * ); - PXENV_EXIT_t ( * file_open ) ( struct s_PXENV_FILE_OPEN * ); - PXENV_EXIT_t ( * file_close ) ( struct s_PXENV_FILE_CLOSE * ); - PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * ); - PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * ); - PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * ); - PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * ); - PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * ); - PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * ); -}; - /** * Handle an unknown PXE API call * @@ -120,6 +54,26 @@ static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) { 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 * @@ -128,220 +82,30 @@ static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) { * @ret ax PXE exit code */ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) { - int opcode = ix86->regs.bx; - userptr_t parameters = real_to_user ( ix86->segs.es, ix86->regs.di ); - size_t param_len; - union u_PXENV_ANY pxenv_any; - union pxenv_call pxenv_call; + 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; - switch ( opcode ) { - case PXENV_UNLOAD_STACK: - pxenv_call.unload_stack = pxenv_unload_stack; - param_len = sizeof ( pxenv_any.unload_stack ); - break; - case PXENV_GET_CACHED_INFO: - pxenv_call.get_cached_info = pxenv_get_cached_info; - param_len = sizeof ( pxenv_any.get_cached_info ); - break; - case PXENV_RESTART_TFTP: - pxenv_call.restart_tftp = pxenv_restart_tftp; - param_len = sizeof ( pxenv_any.restart_tftp ); - break; - case PXENV_START_UNDI: - pxenv_call.start_undi = pxenv_start_undi; - param_len = sizeof ( pxenv_any.start_undi ); - break; - case PXENV_STOP_UNDI: - pxenv_call.stop_undi = pxenv_stop_undi; - param_len = sizeof ( pxenv_any.stop_undi ); - break; - case PXENV_START_BASE: - pxenv_call.start_base = pxenv_start_base; - param_len = sizeof ( pxenv_any.start_base ); - break; - case PXENV_STOP_BASE: - pxenv_call.stop_base = pxenv_stop_base; - param_len = sizeof ( pxenv_any.stop_base ); - break; - case PXENV_TFTP_OPEN: - pxenv_call.tftp_open = pxenv_tftp_open; - param_len = sizeof ( pxenv_any.tftp_open ); - break; - case PXENV_TFTP_CLOSE: - pxenv_call.tftp_close = pxenv_tftp_close; - param_len = sizeof ( pxenv_any.tftp_close ); - break; - case PXENV_TFTP_READ: - pxenv_call.tftp_read = pxenv_tftp_read; - param_len = sizeof ( pxenv_any.tftp_read ); - break; - case PXENV_TFTP_READ_FILE: - pxenv_call.tftp_read_file = pxenv_tftp_read_file; - param_len = sizeof ( pxenv_any.tftp_read_file ); - break; - case PXENV_TFTP_GET_FSIZE: - pxenv_call.tftp_get_fsize = pxenv_tftp_get_fsize; - param_len = sizeof ( pxenv_any.tftp_get_fsize ); - break; - case PXENV_UDP_OPEN: - pxenv_call.udp_open = pxenv_udp_open; - param_len = sizeof ( pxenv_any.udp_open ); - break; - case PXENV_UDP_CLOSE: - pxenv_call.udp_close = pxenv_udp_close; - param_len = sizeof ( pxenv_any.udp_close ); - break; - case PXENV_UDP_WRITE: - pxenv_call.udp_write = pxenv_udp_write; - param_len = sizeof ( pxenv_any.udp_write ); - break; - case PXENV_UDP_READ: - pxenv_call.udp_read = pxenv_udp_read; - param_len = sizeof ( pxenv_any.udp_read ); - break; - case PXENV_UNDI_STARTUP: - pxenv_call.undi_startup = pxenv_undi_startup; - param_len = sizeof ( pxenv_any.undi_startup ); - break; - case PXENV_UNDI_CLEANUP: - pxenv_call.undi_cleanup = pxenv_undi_cleanup; - param_len = sizeof ( pxenv_any.undi_cleanup ); - break; - case PXENV_UNDI_INITIALIZE: - pxenv_call.undi_initialize = pxenv_undi_initialize; - param_len = sizeof ( pxenv_any.undi_initialize ); - break; - case PXENV_UNDI_RESET_ADAPTER: - pxenv_call.undi_reset_adapter = pxenv_undi_reset_adapter; - param_len = sizeof ( pxenv_any.undi_reset_adapter ); - break; - case PXENV_UNDI_SHUTDOWN: - pxenv_call.undi_shutdown = pxenv_undi_shutdown; - param_len = sizeof ( pxenv_any.undi_shutdown ); - break; - case PXENV_UNDI_OPEN: - pxenv_call.undi_open = pxenv_undi_open; - param_len = sizeof ( pxenv_any.undi_open ); - break; - case PXENV_UNDI_CLOSE: - pxenv_call.undi_close = pxenv_undi_close; - param_len = sizeof ( pxenv_any.undi_close ); - break; - case PXENV_UNDI_TRANSMIT: - pxenv_call.undi_transmit = pxenv_undi_transmit; - param_len = sizeof ( pxenv_any.undi_transmit ); - break; - case PXENV_UNDI_SET_MCAST_ADDRESS: - pxenv_call.undi_set_mcast_address = - pxenv_undi_set_mcast_address; - param_len = sizeof ( pxenv_any.undi_set_mcast_address ); - break; - case PXENV_UNDI_SET_STATION_ADDRESS: - pxenv_call.undi_set_station_address = - pxenv_undi_set_station_address; - param_len = sizeof ( pxenv_any.undi_set_station_address ); - break; - case PXENV_UNDI_SET_PACKET_FILTER: - pxenv_call.undi_set_packet_filter = - pxenv_undi_set_packet_filter; - param_len = sizeof ( pxenv_any.undi_set_packet_filter ); - break; - case PXENV_UNDI_GET_INFORMATION: - pxenv_call.undi_get_information = pxenv_undi_get_information; - param_len = sizeof ( pxenv_any.undi_get_information ); - break; - case PXENV_UNDI_GET_STATISTICS: - pxenv_call.undi_get_statistics = pxenv_undi_get_statistics; - param_len = sizeof ( pxenv_any.undi_get_statistics ); - break; - case PXENV_UNDI_CLEAR_STATISTICS: - pxenv_call.undi_clear_statistics = pxenv_undi_clear_statistics; - param_len = sizeof ( pxenv_any.undi_clear_statistics ); - break; - case PXENV_UNDI_INITIATE_DIAGS: - pxenv_call.undi_initiate_diags = pxenv_undi_initiate_diags; - param_len = sizeof ( pxenv_any.undi_initiate_diags ); - break; - case PXENV_UNDI_FORCE_INTERRUPT: - pxenv_call.undi_force_interrupt = pxenv_undi_force_interrupt; - param_len = sizeof ( pxenv_any.undi_force_interrupt ); - break; - case PXENV_UNDI_GET_MCAST_ADDRESS: - pxenv_call.undi_get_mcast_address = - pxenv_undi_get_mcast_address; - param_len = sizeof ( pxenv_any.undi_get_mcast_address ); - break; - case PXENV_UNDI_GET_NIC_TYPE: - pxenv_call.undi_get_nic_type = pxenv_undi_get_nic_type; - param_len = sizeof ( pxenv_any.undi_get_nic_type ); - break; - case PXENV_UNDI_GET_IFACE_INFO: - pxenv_call.undi_get_iface_info = pxenv_undi_get_iface_info; - param_len = sizeof ( pxenv_any.undi_get_iface_info ); - break; - case PXENV_UNDI_ISR: - pxenv_call.undi_isr = pxenv_undi_isr; - param_len = sizeof ( pxenv_any.undi_isr ); - break; - case PXENV_FILE_OPEN: - pxenv_call.file_open = pxenv_file_open; - param_len = sizeof ( pxenv_any.file_open ); - break; - case PXENV_FILE_CLOSE: - pxenv_call.file_close = pxenv_file_close; - param_len = sizeof ( pxenv_any.file_close ); - break; - case PXENV_FILE_SELECT: - pxenv_call.file_select = pxenv_file_select; - param_len = sizeof ( pxenv_any.file_select ); - break; - case PXENV_FILE_READ: - pxenv_call.file_read = pxenv_file_read; - param_len = sizeof ( pxenv_any.file_read ); - break; - case PXENV_GET_FILE_SIZE: - pxenv_call.get_file_size = pxenv_get_file_size; - param_len = sizeof ( pxenv_any.get_file_size ); - break; - case PXENV_FILE_EXEC: - pxenv_call.file_exec = pxenv_file_exec; - param_len = sizeof ( pxenv_any.file_exec ); - break; - case PXENV_FILE_API_CHECK: - pxenv_call.file_api_check = pxenv_file_api_check; - param_len = sizeof ( pxenv_any.file_api_check ); - break; - case PXENV_FILE_EXIT_HOOK: - pxenv_call.file_exit_hook = pxenv_file_exit_hook; - param_len = sizeof ( pxenv_any.file_exit_hook ); - break; - default: - DBG ( "PXENV_UNKNOWN_%hx", opcode ); - pxenv_call.unknown = pxenv_unknown; - param_len = sizeof ( pxenv_any.unknown ); - break; + /* 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 ( &pxenv_any, parameters, 0, param_len ); + copy_from_user ( ¶ms, uparams, 0, call->params_len ); /* Set default status in case child routine fails to do so */ - pxenv_any.Status = PXENV_STATUS_FAILURE; + params.Status = PXENV_STATUS_FAILURE; /* Hand off to relevant API routine */ - DBG ( "[" ); - ret = pxenv_call.any ( &pxenv_any ); - if ( pxenv_any.Status != PXENV_STATUS_SUCCESS ) { - DBG ( " %02x", pxenv_any.Status ); - } - if ( ret != PXENV_EXIT_SUCCESS ) { - DBG ( ret == PXENV_EXIT_FAILURE ? " err" : " ??" ); - } - DBG ( "]" ); - + ret = call->entry ( ¶ms ); + /* Copy modified parameter block back to caller and return */ - copy_to_user ( parameters, 0, &pxenv_any, param_len ); + copy_to_user ( uparams, 0, ¶ms, call->params_len ); ix86->regs.ax = ret; } @@ -351,8 +115,7 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) { * @v ix86 Registers for PXE call * @ret present Zero (PXE stack present) */ -int pxe_api_call_weak ( struct i386_all_regs *ix86 ) -{ +int pxe_api_call_weak ( struct i386_all_regs *ix86 ) { pxe_api_call ( ix86 ); return 0; } @@ -519,3 +282,9 @@ int pxe_start_nbp ( void ) { 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S b/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S index 0d3a57cd3..6274264ff 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c new file mode 100644 index 000000000..9d1896507 --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c @@ -0,0 +1,61 @@ +/** @file + * + * PXE exit hook + * + */ + +/* + * Copyright (C) 2010 Shao Miller . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include + +/** 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c index 267625688..6e9610294 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c @@ -16,8 +16,6 @@ /* * Copyright (C) 2007 Michael Brown . - * Portions (C) 2010 Shao Miller . - * [PXE exit hook logic] * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -31,7 +29,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -49,7 +48,7 @@ FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 ); * @ret s_PXENV_FILE_OPEN::FileHandle Handle of opened file * */ -PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) { +static PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) { userptr_t filename; size_t filename_len; int fd; @@ -91,7 +90,7 @@ PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) { * @ret s_PXENV_FILE_CLOSE::Status PXE status code * */ -PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) { +static PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) { DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle ); @@ -111,7 +110,8 @@ PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) { * @ret s_PXENV_FILE_SELECT::Ready Indication of readiness * */ -PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) { +static PXENV_EXIT_t +pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) { fd_set fdset; int ready; @@ -143,7 +143,7 @@ PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) { * @ret s_PXENV_FILE_READ::BufferSize Length of data read * */ -PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) { +static PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) { userptr_t buffer; ssize_t len; @@ -176,8 +176,8 @@ PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) { * @ret s_PXENV_GET_FILE_SIZE::Status PXE status code * @ret s_PXENV_GET_FILE_SIZE::FileSize Size of file */ -PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE - *get_file_size ) { +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 ); @@ -205,7 +205,7 @@ PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE * @ret s_PXENV_FILE_EXEC::Status PXE status code * */ -PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) { +static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) { userptr_t command; size_t command_len; int rc; @@ -233,8 +233,41 @@ PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) { return PXENV_EXIT_SUCCESS; } -segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 }; -#define pxe_exit_hook __use_data16 ( pxe_exit_hook ) +/** + * FILE CMDLINE + * + * @v file_cmdline Pointer to a struct s_PXENV_FILE_CMDLINE + * @v s_PXENV_FILE_CMDLINE::Buffer Buffer to contain command line + * @v s_PXENV_FILE_CMDLINE::BufferSize Size of buffer + * @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 + * @ret s_PXENV_FILE_EXEC::BufferSize Length of command line (including NUL) + * + */ +static PXENV_EXIT_t +pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) { + userptr_t buffer; + size_t max_len; + size_t len; + + DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n", + file_cmdline->Buffer.segment, file_cmdline->Buffer.offset, + file_cmdline->BufferSize, pxe_cmdline ); + + buffer = real_to_user ( file_cmdline->Buffer.segment, + file_cmdline->Buffer.offset ); + len = file_cmdline->BufferSize; + max_len = ( pxe_cmdline ? + ( strlen ( pxe_cmdline ) + 1 /* NUL */ ) : 0 ); + if ( len > max_len ) + len = max_len; + copy_to_user ( buffer, 0, pxe_cmdline, len ); + file_cmdline->BufferSize = max_len; + + file_cmdline->Status = PXENV_STATUS_SUCCESS; + return PXENV_EXIT_SUCCESS; +} /** * FILE API CHECK @@ -250,57 +283,60 @@ segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 }; * @ret s_PXENV_FILE_API_CHECK::Flags Reserved * */ -PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) { +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; - } else if ( file_api_check->Size < - sizeof(struct s_PXENV_FILE_API_CHECK) ) { + } + + /* 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; - } else { - file_api_check->Status = PXENV_STATUS_SUCCESS; - file_api_check->Size = sizeof(struct s_PXENV_FILE_API_CHECK); - file_api_check->Magic = 0xe9c17b20; - file_api_check->Provider = 0x45585067; /* "iPXE" */ - file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */ - /* Check to see if we have a PXE exit hook */ - if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) - /* Function e7, also */ - file_api_check->APIMask |= 0x00000080; - file_api_check->Flags = 0; /* None defined */ - return PXENV_EXIT_SUCCESS; } -} -/** - * 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 - * - */ -PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK - *file_exit_hook ) { - DBG ( "PXENV_FILE_EXIT_HOOK" ); - - /* Check to see if we have a PXE exit hook */ - if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) { - /* 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; + /* 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 ); } - DBG ( " not NBP" ); - file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; + /* 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_CMDLINE, pxenv_file_cmdline, + struct s_PXENV_FILE_CMDLINE ), + PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check, + struct s_PXENV_FILE_API_CHECK ), +}; diff --git a/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c index 63858be20..695af3b93 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c index 9e4853b01..534352b2b 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c @@ -20,7 +20,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -89,6 +90,26 @@ static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = { [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 ""; + } +} + /* 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 @@ -110,8 +131,9 @@ static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] ); * @ret ... * */ -PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) { - DBG ( "PXENV_UNLOAD_STACK" ); +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; @@ -121,8 +143,8 @@ PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) { * * Status: working */ -PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO - *get_cached_info ) { +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; @@ -130,15 +152,24 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO userptr_t buffer; int rc; - DBG ( "PXENV_GET_CACHED_INFO %d", get_cached_info->PacketType ); + 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 ); - DBG ( " to %04x:%04x+%x", 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 ) { - DBG ( " bad PacketType" ); + DBGC ( &pxe_netdev, " bad PacketType %d\n", + get_cached_info->PacketType ); goto err; } info = &cached_info[idx]; @@ -149,7 +180,8 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO creator = &pxe_dhcp_packet_creators[idx]; if ( ( rc = creator->create ( pxe_netdev, info, sizeof ( *info ) ) ) != 0 ) { - DBG ( " failed to build packet" ); + DBGC ( &pxe_netdev, " failed to build packet: %s\n", + strerror ( rc ) ); goto err; } } @@ -184,23 +216,24 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO get_cached_info->Buffer.segment = rm_ds; get_cached_info->Buffer.offset = __from_data16 ( info ); get_cached_info->BufferSize = sizeof ( *info ); - DBG ( " returning %04x:%04x+%04x['%x']", - get_cached_info->Buffer.segment, - get_cached_info->Buffer.offset, - get_cached_info->BufferSize, - get_cached_info->BufferLimit ); + 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 ) ) - DBG ( " buffer may be too short" ); + 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; @@ -213,11 +246,11 @@ PXENV_EXIT_t pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO * * Status: working */ -PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE - *restart_tftp ) { +static PXENV_EXIT_t +pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE *restart_tftp ) { PXENV_EXIT_t tftp_exit; - DBG ( "PXENV_RESTART_TFTP " ); + DBGC ( &pxe_netdev, "PXENV_RESTART_TFTP\n" ); /* Words cannot describe the complete mismatch between the PXE * specification and any possible version of reality... @@ -236,13 +269,13 @@ PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE * * Status: working */ -PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { +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; - DBG ( "PXENV_START_UNDI %04x:%04x:%04x", - start_undi->AX, start_undi->BX, start_undi->DX ); + 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 @@ -266,11 +299,13 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { /* Look for a matching net device */ netdev = find_netdev_by_location ( bus_type, location ); if ( ! netdev ) { - DBG ( " no net device found" ); + 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; } - DBG ( " using netdev %s", netdev->name ); + DBGC ( &pxe_netdev, "PXENV_START_UNDI found net device %s\n", + netdev->name ); /* Activate PXE */ pxe_activate ( netdev ); @@ -283,8 +318,8 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { * * Status: working */ -PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) { - DBG ( "PXENV_STOP_UNDI" ); +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(); @@ -294,8 +329,8 @@ PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) { /* Check to see if we still have any hooked interrupts */ if ( hooked_bios_interrupts != 0 ) { - DBG ( "PXENV_STOP_UNDI failed: %d interrupts still hooked\n", - hooked_bios_interrupts ); + 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; } @@ -308,8 +343,8 @@ PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) { * * Status: won't implement (requires major structural changes) */ -PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) { - DBG ( "PXENV_START_BASE" ); +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; @@ -319,8 +354,8 @@ PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) { * * Status: working */ -PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) { - DBG ( "PXENV_STOP_BASE" ); +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 @@ -330,3 +365,21 @@ PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) { 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c index 7f0af7a61..aab376e82 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c @@ -19,7 +19,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -233,7 +234,7 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port, * view of the PXE API, it is conceptually impossible to issue any * other PXE API call "if an MTFTP connection is active". */ -PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) { +static PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) { int rc; DBG ( "PXENV_TFTP_OPEN" ); @@ -285,7 +286,7 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) { * 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_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) { +static PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) { DBG ( "PXENV_TFTP_CLOSE" ); pxe_tftp_close ( &pxe_tftp, 0 ); @@ -354,7 +355,7 @@ PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) { * 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 ( struct s_PXENV_TFTP_READ *tftp_read ) { +static PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) { int rc; DBG ( "PXENV_TFTP_READ to %04x:%04x", @@ -531,8 +532,8 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE * a file from a TFTP server listening on the standard TFTP port. * "Consistency" is not a word in Intel's vocabulary. */ -PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE - *tftp_get_fsize ) { +static PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE + *tftp_get_fsize ) { int rc; DBG ( "PXENV_TFTP_GET_FSIZE" ); @@ -562,3 +563,17 @@ PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c index 22af4ca0d..32bc39c8e 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c @@ -28,7 +28,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -159,7 +160,7 @@ static struct pxe_udp_connection pxe_udp = { * parameter. * */ -PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { +static PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { int rc; DBG ( "PXENV_UDP_OPEN" ); @@ -202,7 +203,8 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) { * @ref pxe_x86_pmode16 "implementation note" for more details.) * */ -PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { +static PXENV_EXIT_t +pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { DBG ( "PXENV_UDP_CLOSE\n" ); /* Close UDP connection */ @@ -253,7 +255,8 @@ PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) { * parameter. * */ -PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) { +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, @@ -359,7 +362,7 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) { * expects us to do so, and will fail if we don't. * */ -PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) { +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; @@ -405,3 +408,15 @@ PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) { 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/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c b/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c index 3938207f1..5d2122694 100644 --- a/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c +++ b/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c @@ -19,7 +19,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -58,11 +59,14 @@ struct net_device *pxe_netdev = NULL; * @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 ); } @@ -75,11 +79,14 @@ void pxe_set_netdev ( struct net_device *netdev ) { 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; } @@ -88,6 +95,8 @@ static int pxe_netdev_open ( void ) { * */ static void pxe_netdev_close ( void ) { + + assert ( pxe_netdev != NULL ); netdev_rx_unfreeze ( pxe_netdev ); netdev_irq ( pxe_netdev, 0 ); netdev_close ( pxe_netdev ); @@ -104,7 +113,8 @@ static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) { unsigned int i; for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) { - DBG ( " %s", ll_protocol->ntoa ( mcast->McastAddr[i] ) ); + DBGC ( &pxe_netdev, " %s", + ll_protocol->ntoa ( mcast->McastAddr[i] ) ); } } @@ -112,8 +122,17 @@ static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) { * * Status: working */ -PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) { - DBG ( "PXENV_UNDI_STARTUP\n" ); +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; @@ -123,9 +142,19 @@ PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) { * * Status: working */ -PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) { - DBG ( "PXENV_UNDI_CLEANUP\n" ); +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; @@ -136,10 +165,18 @@ PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) { * * Status: working */ -PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE - *undi_initialize ) { - DBG ( "PXENV_UNDI_INITIALIZE protocolini %08x\n", - undi_initialize->ProtocolIni ); +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; @@ -149,18 +186,27 @@ PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE * * Status: working */ -PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET - *undi_reset_adapter ) { +static PXENV_EXIT_t +pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET *undi_reset_adapter ) { int rc; - DBG ( "PXENV_UNDI_RESET_ADAPTER" ); + DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER" ); pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf ); - DBG ( "\n" ); + 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 ) { - DBG ( "PXENV_UNDI_RESET_ADAPTER could not reopen %s: %s\n", - pxe_netdev->name, strerror ( rc ) ); + 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; } @@ -173,10 +219,19 @@ PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET * * Status: working */ -PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN - *undi_shutdown ) { - DBG ( "PXENV_UNDI_SHUTDOWN\n" ); +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; @@ -187,17 +242,26 @@ PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN * * Status: working */ -PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) { +static PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) { int rc; - DBG ( "PXENV_UNDI_OPEN flag %04x filter %04x", - undi_open->OpenFlag, undi_open->PktFilter ); + 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 ); - DBG ( "\n" ); + 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 ) { - DBG ( "PXENV_UNDI_OPEN could not open %s: %s\n", - pxe_netdev->name, strerror ( rc ) ); + 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; } @@ -210,9 +274,18 @@ PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) { * * Status: working */ -PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) { - DBG ( "PXENV_UNDI_CLOSE\n" ); +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; @@ -223,20 +296,28 @@ PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) { * * Status: working */ -PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT - *undi_transmit ) { +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 = pxe_netdev->ll_protocol; + struct ll_protocol *ll_protocol; char destaddr[MAX_LL_ADDR_LEN]; const void *ll_dest; size_t len; unsigned int i; int rc; - DBG2 ( "PXENV_UNDI_TRANSMIT" ); + /* 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 @@ -254,29 +335,33 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT net_protocol = NULL; break; default: - DBG2 ( " %02x invalid protocol\n", undi_transmit->Protocol ); + DBGC2 ( &pxe_netdev, " %02x invalid protocol\n", + undi_transmit->Protocol ); undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; return PXENV_EXIT_FAILURE; } - DBG2 ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) ); + 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; - DBG2 ( " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset, - 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; - DBG2 ( " %04x:%04x+%x", datablk->TDDataPtr.segment, - datablk->TDDataPtr.offset, 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 ); + iobuf = alloc_iob ( MAX_LL_HEADER_LEN + + ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) ); if ( ! iobuf ) { - DBG2 ( " could not allocate iobuf\n" ); + DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" ); undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES; return PXENV_EXIT_FAILURE; } @@ -295,24 +380,26 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT 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; - DBG2 ( " DEST %s", ll_protocol->ntoa ( ll_dest ) ); + DBGC2 ( &pxe_netdev, " DEST %s", + ll_protocol->ntoa ( ll_dest ) ); } else { ll_dest = pxe_netdev->ll_broadcast; - DBG2 ( " BCAST" ); + 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){ - DBG2 ( " could not add link-layer header: %s\n", - strerror ( rc ) ); + 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; @@ -326,10 +413,10 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT undi_tx_count++; /* Transmit packet */ - DBG2 ( "\n" ); + DBGC2 ( &pxe_netdev, "\n" ); if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) { - DBG2 ( "PXENV_UNDI_TRANSMIT could not transmit: %s\n", - strerror ( rc ) ); + 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; @@ -343,12 +430,21 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT * * Status: working (for NICs that support receive-all-multicast) */ -PXENV_EXIT_t +static PXENV_EXIT_t pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS *undi_set_mcast_address ) { - DBG ( "PXENV_UNDI_SET_MCAST_ADDRESS" ); + DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS" ); pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf ); - DBG ( "\n" ); + 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; @@ -358,19 +454,29 @@ pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS * * Status: working */ -PXENV_EXIT_t +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 = pxe_netdev->ll_protocol; + 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; + } - DBG ( "PXENV_UNDI_SET_STATION_ADDRESS %s", - ll_protocol->ntoa ( undi_set_station_address->StationAddress ) ); + 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 ) ) { - DBG ( " failed: netdev is open\n" ); + DBGC ( &pxe_netdev, " failed: netdev is open\n" ); undi_set_station_address->Status = PXENV_STATUS_UNDI_INVALID_STATE; return PXENV_EXIT_FAILURE; @@ -381,7 +487,7 @@ pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS &undi_set_station_address->StationAddress, ll_protocol->ll_addr_len ); - DBG ( "\n" ); + DBGC ( &pxe_netdev, "\n" ); undi_set_station_address->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; } @@ -391,12 +497,21 @@ pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS * Status: won't implement (would require driver API changes for no * real benefit) */ -PXENV_EXIT_t +static PXENV_EXIT_t pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER *undi_set_packet_filter ) { - DBG ( "PXENV_UNDI_SET_PACKET_FILTER %02x\n", - undi_set_packet_filter->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 @@ -411,22 +526,33 @@ pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER * * Status: working */ -PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION - *undi_get_information ) { - struct device *dev = pxe_netdev->dev; - struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; - size_t ll_addr_len = ll_protocol->ll_addr_len; +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; - DBG ( "PXENV_UNDI_GET_INFORMATION" ); + /* 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_addr_len; - assert ( ll_addr_len <= + 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, @@ -441,10 +567,10 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION undi_get_information->RxBufCt = 1; undi_get_information->TxBufCt = 1; - DBG ( " 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 )); + 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; } @@ -453,20 +579,31 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION * * Status: working */ -PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS - *undi_get_statistics ) { - DBG ( "PXENV_UNDI_GET_STATISTICS" ); +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 ); - DBG ( " 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; } @@ -475,10 +612,20 @@ PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS * * Status: working */ -PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS - *undi_clear_statistics ) { - DBG ( "PXENV_UNDI_CLEAR_STATISTICS\n" ); +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 ) ); @@ -491,9 +638,18 @@ PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS * Status: won't implement (would require driver API changes for no * real benefit) */ -PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS - *undi_initiate_diags ) { - DBG ( "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" ); +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; @@ -504,9 +660,19 @@ PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS * Status: won't implement (would require driver API changes for no * perceptible benefit) */ -PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT - *undi_force_interrupt ) { - DBG ( "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" ); +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; @@ -516,23 +682,35 @@ PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT * * Status: working */ -PXENV_EXIT_t +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 = pxe_netdev->ll_protocol; + struct ll_protocol *ll_protocol; struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr }; int rc; - DBG ( "PXENV_UNDI_GET_MCAST_ADDRESS %s", inet_ntoa ( ip ) ); + /* 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){ - DBG ( " failed: %s\n", strerror ( rc ) ); + DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) ); undi_get_mcast_address->Status = PXENV_STATUS ( rc ); return PXENV_EXIT_FAILURE; } - DBG ( "=>%s\n", - ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) ); + 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; @@ -542,15 +720,24 @@ pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS * * Status: working */ -PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE - *undi_get_nic_type ) { - struct device *dev = pxe_netdev->dev; +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; + } - DBG ( "PXENV_UNDI_GET_NIC_TYPE" ); + 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; @@ -567,13 +754,14 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE * is possible that some NBPs will not provide space * for them, and so we must not fill them in. */ - DBG ( " 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 ); + 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; @@ -585,12 +773,12 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE /* Cheat: remaining fields are probably unnecessary, * and would require adding extra code to isapnp.c. */ - DBG ( " ISAPnP CSN %04x %08x %02x%02x%02x\n", - info->CardSelNum, info->EISA_Dev_ID, - info->Base_Class, info->Sub_Class, info->Prog_Intf ); + 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: - DBG ( " failed: unknown bus type\n" ); + DBGC ( &pxe_netdev, " failed: unknown bus type\n" ); undi_get_nic_type->Status = PXENV_STATUS_FAILURE; return PXENV_EXIT_FAILURE; } @@ -603,9 +791,19 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE * * Status: working */ -PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO - *undi_get_iface_info ) { - DBG ( "PXENV_UNDI_GET_IFACE_INFO" ); +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. @@ -622,44 +820,47 @@ PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO memset ( undi_get_iface_info->Reserved, 0, sizeof(undi_get_iface_info->Reserved) ); - DBG ( " %s %dbps flags %08x\n", undi_get_iface_info->IfaceType, - undi_get_iface_info->LinkSpeed, - undi_get_iface_info->ServiceFlags ); + 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 + * Status: impossible due to opcode collision */ -PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE - *undi_get_state ) { - DBG ( "PXENV_UNDI_GET_STATE failed: unsupported\n" ); - - undi_get_state->Status = PXENV_STATUS_UNSUPPORTED; - return PXENV_EXIT_FAILURE; -}; /* PXENV_UNDI_ISR * * Status: working */ -PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { +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 coloured debug, since UNDI ISR messages are likely to - * be interspersed amongst other UNDI messages. + /* 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 @@ -753,7 +954,8 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { /* Strip link-layer header */ ll_protocol = pxe_netdev->ll_protocol; if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest, - &ll_source, &net_proto )) !=0){ + &ll_source, &net_proto, + &flags ) ) != 0 ) { /* Assume unknown net_proto and no ll_source */ net_proto = 0; ll_source = NULL; @@ -788,14 +990,12 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { undi_isr->Frame.segment = rm_ds; undi_isr->Frame.offset = __from_data16 ( basemem_packet ); undi_isr->ProtType = prottype; - if ( memcmp ( ll_dest, pxe_netdev->ll_addr, - ll_protocol->ll_addr_len ) == 0 ) { - undi_isr->PktType = P_DIRECTED; - } else if ( memcmp ( ll_dest, pxe_netdev->ll_broadcast, - ll_protocol->ll_addr_len ) == 0 ) { + if ( flags & LL_BROADCAST ) { undi_isr->PktType = P_BROADCAST; - } else { + } 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, @@ -820,3 +1020,51 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { 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/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c b/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c index e93307443..8b2a2c880 100644 --- a/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c +++ b/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c index 8fe1572f2..f37286335 100644 --- a/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c +++ b/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c b/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c index 47df64cb9..8fffd0692 100644 --- a/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c +++ b/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S index 4cd882215..69cea02e8 100644 --- a/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S +++ b/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ) diff --git a/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c b/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c index 571ba9e6d..fbf605f33 100644 --- a/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c +++ b/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** @@ -38,12 +39,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include "config/console.h" #include "config/serial.h" /** The "SYSLINUX" version string */ -static char __data16_array ( syslinux_version, [] ) = "\r\niPXE " VERSION; +static char __bss16_array ( syslinux_version, [32] ); #define syslinux_version __use_data16 ( syslinux_version ) /** The "SYSLINUX" copyright string */ @@ -166,6 +168,8 @@ void comboot_force_text_mode ( void ) { * 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; @@ -184,8 +188,7 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) { DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file ); /* Fetch initrd */ - if ( ( rc = imgdownload_string ( initrd_file, NULL, NULL, - register_and_put_image ))!=0){ + if ( ( rc = imgdownload_string ( initrd_file, &initrd ) ) != 0){ DBG ( "COMBOOT: could not fetch initrd: %s\n", strerror ( rc ) ); return rc; @@ -198,14 +201,20 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) { DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file ); - /* Allocate and fetch kernel */ - if ( ( rc = imgdownload_string ( kernel_file, NULL, cmdline, - register_and_replace_image ) ) != 0 ) { + /* 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; } @@ -318,6 +327,10 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) { /* SYSLINUX derivative ID */ ix86->regs.dl = BZI_LOADER_TYPE_IPXE; + /* SYSLINUX version */ + snprintf ( syslinux_version, sizeof ( syslinux_version ), + "\r\niPXE %s", product_version ); + /* SYSLINUX version and copyright strings */ ix86->segs.es = rm_ds; ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) ); diff --git a/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c b/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c new file mode 100644 index 000000000..5e08d9471 --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * VMware GuestInfo settings + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** 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 %d 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/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c b/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c new file mode 100644 index 000000000..390fc5545 --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * VMware GuestRPC mechanism + * + */ + +#include +#include +#include +#include +#include +#include + +/* 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/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c b/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c new file mode 100644 index 000000000..485105200 --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * VMware logfile console + * + */ + +#include +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/arch/i386/interface/vmware/vmware.c b/roms/ipxe/src/arch/i386/interface/vmware/vmware.c new file mode 100644 index 000000000..8074e6118 --- /dev/null +++ b/roms/ipxe/src/arch/i386/interface/vmware/vmware.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * VMware backdoor mechanism + * + * Based on the unofficial documentation at + * + * http://sites.google.com/site/chitchatvmback/backdoor + * + */ + +#include +#include +#include + +/** + * 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/roms/ipxe/src/arch/i386/prefix/exeprefix.S b/roms/ipxe/src/arch/i386/prefix/exeprefix.S index c7e57cee5..acd3f83cd 100644 --- a/roms/ipxe/src/arch/i386/prefix/exeprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/exeprefix.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ @@ -113,7 +114,7 @@ _exe_start: call alloc_basemem xorl %esi, %esi movl $EXE_DECOMPRESS_ADDRESS, %edi - clc + xorl %ebp, %ebp call install_prealloc /* Set up real-mode stack */ diff --git a/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S b/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S new file mode 100644 index 000000000..27ed231e7 --- /dev/null +++ b/roms/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/roms/ipxe/src/arch/i386/prefix/libprefix.S b/roms/ipxe/src/arch/i386/prefix/libprefix.S index 77151a67e..2f8fc4e1a 100644 --- a/roms/ipxe/src/arch/i386/prefix/libprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/libprefix.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ @@ -49,7 +50,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) .section ".prefix.data", "aw", @progbits progress_\@: .asciz "\message" - .size progress_\@, . - progress\@ + .size progress_\@, . - progress_\@ .previous .endm #endif @@ -326,7 +327,6 @@ process_bytes: #ifndef KEEP_IT_REAL /* Preserve registers */ - pushfw pushl %eax pushl %ebp @@ -397,7 +397,6 @@ process_bytes: /* Restore registers and return */ popl %ebp popl %eax - popfw ret #else /* KEEP_IT_REAL */ @@ -614,17 +613,19 @@ install: /* 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 relocation */ - clc + /* 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 @@ -640,7 +641,7 @@ install: * %bx : .data16 segment address * %esi : Image source physical address (or zero for %cs:0000) * %edi : Decompression temporary area physical address (or zero for default) - * CF set : Avoid relocating to top of memory + * %ebp : Maximum end address for relocation (or zero for no maximum) * Corrupts: * none **************************************************************************** @@ -655,27 +656,30 @@ install_prealloc: pushw %ds pushw %es cld /* Sanity: clear the direction flag asap */ - pushfw /* Set up %ds for (read-only) access to .prefix */ pushw %cs popw %ds - /* Copy decompression temporary area physical address to %ebp */ - movl %edi, %ebp + /* Save decompression temporary area physical address */ + pushl %edi - /* Install .text16.early */ + /* Install .text16.early and calculate %ecx as offset to next block */ progress " .text16.early\n" pushl %esi xorl %esi, %esi movw %cs, %si shll $4, %esi + pushl %esi /* Save original %cs:0000 */ 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 %ecx /* Calculate offset to next block */ + subl %esi, %ecx + negl %ecx popl %esi #ifndef KEEP_IT_REAL @@ -730,7 +734,7 @@ payload_death_message: jnz 1f movw %cs, %si shll $4, %esi -1: addl payload_lma, %esi +1: addl %ecx, %esi /* Install .text16.late and .data16 */ progress " .text16.late\n" @@ -747,6 +751,9 @@ payload_death_message: /* 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) @@ -754,7 +761,7 @@ payload_death_message: #else /* Find a suitable decompression temporary area, if none specified */ pushl %eax - testl %ebp, %ebp + 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 @@ -762,14 +769,14 @@ payload_death_message: */ movb $0x88, %ah int $0x15 - movw %ax, %bp - addl $0x400, %ebp - subl $_textdata_memsz_kb, %ebp - shll $10, %ebp + 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, %ebp + cmpl $0x100000, %edi jae 1f - movl $0x100000, %ebp + movl $0x100000, %edi 1: popl %eax /* Install .text and .data to temporary area in high memory, @@ -777,22 +784,17 @@ payload_death_message: * properly. */ progress " .textdata\n" - movl %ebp, %edi + 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) - movl %ebp, %edi lcall *init_librm_vector - /* Skip relocation if CF was set on entry */ - popfw - pushfw - jc skip_relocate - /* 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. @@ -815,7 +817,6 @@ payload_death_message: /* Initialise librm at new location */ progress " init_librm\n" lcall *init_librm_vector -skip_relocate: #endif /* Close access to payload */ @@ -824,7 +825,6 @@ skip_relocate: lcall *close_payload_vector /* Restore registers */ - popfw popw %es popw %ds popal @@ -855,17 +855,6 @@ close_payload_vector: .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 @@ -919,6 +908,10 @@ uninstall: .ascii "PAYL" .long 0 .long 0 + .long _payload_align + .ascii "COPY" + .long _pprefix_lma + .long _pprefix_filesz .long _max_align .ascii PACK_OR_COPY .long _text16_late_lma @@ -932,3 +925,6 @@ uninstall: .long _textdata_lma .long _textdata_filesz .long _max_align + + .weak _payload_align + .equ _payload_align, 1 diff --git a/roms/ipxe/src/arch/i386/prefix/linuxprefix.S b/roms/ipxe/src/arch/i386/prefix/linuxprefix.S deleted file mode 100644 index 398d3cb21..000000000 --- a/roms/ipxe/src/arch/i386/prefix/linuxprefix.S +++ /dev/null @@ -1,28 +0,0 @@ -#include - - .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/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S b/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S index f87ef85a9..768903326 100644 --- a/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S @@ -160,7 +160,7 @@ relocatable_kernel: pad2: .byte 0, 0, 0 cmdline_size: - .long 0 + .long 0x7ff hardware_subarch: .long 0 hardware_subarch_data: @@ -188,16 +188,58 @@ setup_code: We're now at the beginning of the kernel proper. */ run_ipxe: - /* Set up stack just below 0x7c00 */ + /* 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 %es:cmd_line_ptr, %edx + 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 install + call alloc_basemem + xorl %esi, %esi + xorl %edi, %edi + call install_prealloc /* Set up real-mode stack */ movw %bx, %ss @@ -215,6 +257,10 @@ run_ipxe: /* 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 diff --git a/roms/ipxe/src/arch/i386/prefix/mromprefix.S b/roms/ipxe/src/arch/i386/prefix/mromprefix.S index 7bbe44c4e..058663c40 100644 --- a/roms/ipxe/src/arch/i386/prefix/mromprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/mromprefix.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ @@ -30,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define PCI_BAR_EXPROM 0x30 #define ROMPREFIX_EXCLUDE_PAYLOAD 1 +#define ROMPREFIX_MORE_IMAGES 1 #define _rom_start _mrom_start #include "romprefix.S" @@ -46,8 +48,10 @@ FILE_LICENCE ( GPL2_OR_LATER ) * Parameters: * %ds:0000 : Prefix * %esi : Buffer for copy of image source (or zero if no buffer available) + * %ecx : Expected offset within buffer of first payload block * Returns: * %esi : Valid image source address (buffered or unbuffered) + * %ecx : Actual offset within buffer of first payload block * CF set on error */ .section ".text16.early", "awx", @progbits @@ -56,23 +60,25 @@ open_payload: /* Preserve registers */ pushl %eax pushw %bx - pushl %ecx pushl %edx pushl %edi pushw %bp + pushw %es pushw %ds - /* Retrieve bus:dev.fn and image source length from .prefix */ + /* Retrieve bus:dev.fn 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 */ + /* Set up %es for access to flat address space */ + xorw %ax, %ax + movw %ax, %es + + /* Store bus:dev.fn 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 @@ -149,6 +155,18 @@ find_mem_bar: movw $PCI_BAR_EXPROM, %di call pci_write_config_dword + /* Locate our ROM image */ +1: addr32 es cmpw $0xaa55, (%eax) + stc + jne 99f + addr32 es cmpl $_build_id, build_id(%eax) + je 2f + addr32 es movzbl 2(%eax), %ecx + shll $9, %ecx + addl %ecx, %eax + jmp 1b +2: + /* Copy payload to buffer, or set buffer address to BAR address */ testl %esi, %esi jz 1f @@ -159,27 +177,32 @@ find_mem_bar: * 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 movzbl 2(%esi), %ecx + shll $7, %ecx + addr32 es movzbl 2(%esi,%ecx,4), %edx + shll $7, %edx + addl %edx, %ecx 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: + /* Locate first payload block (after the dummy ROM header) */ + addr32 es movzbl 2(%esi), %ecx + shll $9, %ecx + addl $_pprefix_skip, %ecx + clc /* Restore registers and return */ 99: popw %ds + popw %es popw %bp popl %edi popl %edx - popl %ecx popw %bx popl %eax lret @@ -200,11 +223,6 @@ 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 @@ -419,16 +437,68 @@ pci_set_mem_access: ret .size pci_set_mem_access, . - pci_set_mem_access -/* Image source area length (in dwords) +/* Payload prefix * + * We include a dummy ROM header to cover the "hidden" portion of the + * overall ROM image. */ - .section ".prefix", "ax", @progbits -image_source_len_dword: + .globl _payload_align + .equ _payload_align, 512 + .section ".pprefix", "ax", @progbits + .org 0x00 +mromheader: + .word 0xaa55 /* BIOS extension signature */ +mromheader_size: .byte 0 /* Size in 512-byte blocks */ + .org 0x18 + .word mpciheader + .org 0x1a + .word 0 + .size mromheader, . - mromheader + + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "APPB" + .long mromheader_size + .long 512 .long 0 - .size image_source_len_dword, . - image_source_len_dword + .previous + +mpciheader: + .ascii "PCIR" /* Signature */ + .word pci_vendor_id /* Vendor identification */ + .word pci_device_id /* Device identification */ + .word 0x0000 /* Device list pointer */ + .word mpciheader_len /* PCI data structure length */ + .byte 0x03 /* PCI data structure revision */ + .byte 0x02, 0x00, 0x00 /* Class code */ +mpciheader_image_length: + .word 0 /* Image length */ + .word 0x0001 /* Revision level */ + .byte 0xff /* Code type */ + .byte 0x80 /* Last image indicator */ +mpciheader_runtime_length: + .word 0 /* Maximum run-time image length */ + .word 0x0000 /* Configuration utility code header */ + .word 0x0000 /* DMTF CLP entry point */ + .equ mpciheader_len, . - mpciheader + .size mpciheader, . - mpciheader + + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "APPW" + .long mpciheader_image_length + .long 512 + .long 0 + .ascii "APPW" + .long mpciheader_runtime_length + .long 512 + .long 0 + .previous + +/* Fix up additional image source size + * + */ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDL" - .long image_source_len_dword - .long 4 + .ascii "ADPW" + .long extra_size + .long 512 .long 0 .previous diff --git a/roms/ipxe/src/arch/i386/prefix/pxeprefix.S b/roms/ipxe/src/arch/i386/prefix/pxeprefix.S index b7468cdf0..05db9894c 100644 --- a/roms/ipxe/src/arch/i386/prefix/pxeprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/pxeprefix.S @@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define PXENV_UNDI_GET_IFACE_INFO 0x0013 #define PXENV_STOP_UNDI 0x0015 #define PXENV_UNLOAD_STACK 0x0070 +#define PXENV_FILE_CMDLINE 0x00e8 #define PXE_HACK_EB54 0x0001 @@ -19,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) ) #define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) ) +#define PREFIX_STACK_SIZE 2048 + /***************************************************************************** * Entry point: set operating context, print welcome message ***************************************************************************** @@ -46,10 +49,11 @@ _pxe_start: movw %ax, %ds movw $0x40, %ax /* BIOS data segment access */ movw %ax, %fs - /* Set up stack just below 0x7c00 */ - xorw %ax, %ax + /* Set up temporary stack immediately after the iPXE image */ + movw %cs, %ax + addw image_size_pgh, %ax movw %ax, %ss - movl $0x7c00, %esp + movl $PREFIX_STACK_SIZE, %esp /* Clear direction flag, for the sake of sanity */ cld /* Print welcome message */ @@ -60,6 +64,18 @@ _pxe_start: 10: .asciz "PXE->EB:" .previous + /* Image size (for stack placement calculation) */ + .section ".prefix.data", "aw", @progbits +image_size_pgh: + .word 0 + .previous + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "ADDW" + .long image_size_pgh + .long 16 + .long 0 + .previous + /***************************************************************************** * Find us a usable !PXE or PXENV+ entry point ***************************************************************************** @@ -366,6 +382,35 @@ get_iface_type: 99: movb $0x0a, %al call print_character + +/***************************************************************************** + * Check for a command line + ***************************************************************************** + */ +get_cmdline: + /* Issue PXENV_FILE_CMDLINE */ + xorl %esi, %esi + movw %ss, %si + movw %si, ( pxe_parameter_structure + 0x06 ) + movw $PREFIX_STACK_SIZE, ( pxe_parameter_structure + 0x04 ) + movw $0xffff, ( pxe_parameter_structure + 0x02 ) + movw $PXENV_FILE_CMDLINE, %bx + call pxe_call + jc 99f /* Suppress errors; this is an iPXE extension API call */ + /* Check for non-NULL command line */ + movw ( pxe_parameter_structure + 0x02 ), %ax + testw %ax, %ax + jz 99f + /* Record command line */ + shll $4, %esi + addl $PREFIX_STACK_SIZE, %esi + movl %esi, pxe_cmdline +99: + .section ".prefix.data", "aw", @progbits +pxe_cmdline: + .long 0 + .previous + /***************************************************************************** * Leave NIC in a safe state ***************************************************************************** @@ -713,6 +758,9 @@ run_ipxe: movw pxe_ss, %di movl pxe_esp, %ebp + /* Retrieve PXE command line, if any */ + movl pxe_cmdline, %esi + /* Jump to .text16 segment with %ds pointing to .data16 */ movw %bx, %ds pushw %ax @@ -721,11 +769,10 @@ run_ipxe: .section ".text16", "ax", @progbits 1: /* Update the exit hook */ - movw %cs,pxe_exit_hook+2 - push %ax - mov $2f,%ax - mov %ax,pxe_exit_hook - pop %ax + movw %cs, ( pxe_exit_hook + 2 ) + + /* Store command-line pointer */ + movl %esi, cmdline_phys /* Run main program */ pushl $main @@ -743,7 +790,14 @@ run_ipxe: /* Jump to hook if applicable */ ljmpw *pxe_exit_hook -2: /* Check PXE stack magic */ + .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 diff --git a/roms/ipxe/src/arch/i386/prefix/romprefix.S b/roms/ipxe/src/arch/i386/prefix/romprefix.S index dd602ddb7..35d037eff 100644 --- a/roms/ipxe/src/arch/i386/prefix/romprefix.S +++ b/roms/ipxe/src/arch/i386/prefix/romprefix.S @@ -39,6 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER ) #else #define ZINFO_TYPE_ADxB "ADDB" #define ZINFO_TYPE_ADxW "ADDW" +#endif + +/* Allow ROM to be marked as containing multiple images + */ +#if ROMPREFIX_MORE_IMAGES +#define INDICATOR 0x00 +#else +#define INDICATOR 0x80 #endif .text @@ -55,6 +63,8 @@ romheader_size: .byte 0 /* Size in 512-byte blocks */ jmp init /* Initialisation vector */ checksum: .byte 0 + .org 0x10 + .word ipxeheader .org 0x16 .word undiheader .org 0x18 @@ -70,9 +80,6 @@ checksum: .long 0 .previous -build_id: - .long _build_id /* Randomly-generated build ID */ - pciheader: .ascii "PCIR" /* Signature */ .word pci_vendor_id /* Vendor identification */ @@ -85,7 +92,7 @@ pciheader_image_length: .word 0 /* Image length */ .word 0x0001 /* Revision level */ .byte 0x00 /* Code type */ - .byte 0x80 /* Last image indicator */ + .byte INDICATOR /* Last image indicator */ pciheader_runtime_length: .word 0 /* Maximum run-time image length */ .word 0x0000 /* Configuration utility code header */ @@ -104,6 +111,11 @@ pciheader_runtime_length: .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 */ @@ -162,6 +174,25 @@ undiheader: .equ undiheader_len, . - undiheader .size undiheader, . - undiheader +ipxeheader: + .ascii "iPXE" /* Signature */ + .byte ipxeheader_len /* Length of structure */ + .byte 0 /* Checksum */ +shrunk_rom_size: + .byte 0 /* Shrunk size (in 512-byte blocks) */ + .byte 0 /* Reserved */ +build_id: + .long _build_id /* Randomly-generated build ID */ + .equ ipxeheader_len, . - ipxeheader + .size ipxeheader, . - ipxeheader + + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "ADHB" + .long shrunk_rom_size + .long 512 + .long 0 + .previous + /* Initialisation (called once during POST) * * Determine whether or not this is a PnP system via a signature @@ -286,6 +317,7 @@ pnp_scan: 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 @@ -296,6 +328,7 @@ no_pnp: /* Not PnP-compliant - hook INT 19 */ pushw %gs /* %gs contains runtime %cs */ pushw $int19_entry popl %es:( 0x19 * 4 ) +#endif /* NONPNP_HOOK_INT19 */ pnp_done: /* Check for PMM */ @@ -319,14 +352,19 @@ pmm_scan: 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 + /* Allocate image source PMM block. Round up the size to the + * nearest 4kB (8 512-byte sectors) to work around AMI BIOS bugs. + */ + movzbl romheader_size, %ecx + addw extra_size, %cx + addw $0x0007, %cx /* Round up to multiple of 8 512-byte sectors */ + andw $0xfff8, %cx 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 + jz 1f /* Copy ROM to image source PMM block */ pushw %es xorw %ax, %ax @@ -334,8 +372,8 @@ pmm_scan: movl %esi, %edi xorl %esi, %esi movzbl romheader_size, %ecx - shll $9, %ecx - addr32 rep movsb /* PMM presence implies flat real mode */ + shll $7, %ecx + addr32 rep movsl /* PMM presence implies flat real mode */ popw %es /* Shrink ROM */ movb shrunk_rom_size, %al @@ -407,7 +445,7 @@ no_pmm: * picked up by the initial shell prompt, and we will drop * into a shell. */ - stc /* Inhibit relocation */ + movl $0xa0000, %ebp /* Inhibit relocation during POST */ pushw %cs call exec 2: @@ -432,13 +470,13 @@ no_pmm: * %es:0000 : PMM structure * Returns: * %ebx : PMM handle - * %esi : allocated block address, or zero (with CF set) if allocation failed + * %esi : allocated block address, or zero (with ZF set) if allocation failed */ get_pmm: /* Preserve registers */ pushl %eax pushw %di - movw $' ', %di + movw $( ' ' ), %di get_pmm_find: /* Try to find existing block */ pushl %ebx /* PMM handle */ @@ -448,7 +486,10 @@ get_pmm_find: pushw %dx pushw %ax popl %esi - testl %esi, %esi + /* Treat 0xffffffff (not supported) as 0x00000000 (not found) */ + incl %esi + jz get_pmm_allocate + decl %esi jz get_pmm_allocate /* Block found - check acceptability */ call *%bp @@ -467,20 +508,21 @@ get_pmm_allocate: pushw %dx pushw %ax popl %esi - movw $'+', %di /* Indicate allocation attempt */ - testl %esi, %esi - jnz get_pmm_done - stc + movw $( '+' ), %di /* Indicate allocation attempt */ 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 */ + /* Treat 0xffffffff (not supported) as 0x00000000 (allocation + * failed), and set ZF to indicate a zero result. + */ + incl %esi + jz 1f + decl %esi +1: /* Restore registers and return */ popw %di popl %eax ret @@ -566,31 +608,12 @@ image_source: .long 0 .size image_source, . - image_source -/* Image source size (in 512-byte sectors) +/* Additional image source size (in 512-byte sectors) * */ -image_source_size: +extra_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 + .size extra_size, . - extra_size /* Temporary decompression area * @@ -607,7 +630,7 @@ decompress_to: * Called by the PnP BIOS when it wants to boot us. */ bev_entry: - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ pushw %cs call exec lret @@ -642,7 +665,7 @@ int19_entry: /* Leave keypress in buffer and start iPXE. The keypress will * cause the usual initial Ctrl-B prompt to be skipped. */ - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ pushw %cs call exec 1: /* Try to call original INT 19 vector */ @@ -674,9 +697,6 @@ exec: /* Set %ds = %cs */ pushw %cs popw %ds - /* Preserve state of CF */ - lahf - /* Print message as soon as possible */ movw $prodstr, %si xorw %di, %di @@ -686,8 +706,8 @@ exec: /* Set %ds = %cs */ /* Store magic word on BIOS stack and remember BIOS %ss:sp */ pushl $STACK_MAGIC - movw %ss, %dx - movw %sp, %bp + movw %ss, %cx + movw %sp, %dx /* Obtain a reasonably-sized temporary stack */ xorw %bx, %bx @@ -695,10 +715,7 @@ exec: /* Set %ds = %cs */ movw $0x7c00, %sp /* Install iPXE */ - sahf - pushfw call alloc_basemem - popfw movl image_source, %esi movl decompress_to, %edi call install_prealloc @@ -721,14 +738,14 @@ exec: /* Set %ds = %cs */ pushl $main pushw %cs call prot_call - popl %ecx /* discard */ + popl %eax /* discard */ /* Uninstall iPXE */ call uninstall /* Restore BIOS stack */ - movw %dx, %ss - movw %bp, %sp + movw %cx, %ss + movw %dx, %sp /* Check magic word on BIOS stack */ popl %eax diff --git a/roms/ipxe/src/arch/i386/prefix/undiloader.S b/roms/ipxe/src/arch/i386/prefix/undiloader.S index 951b5c1ce..bb3d469be 100644 --- a/roms/ipxe/src/arch/i386/prefix/undiloader.S +++ b/roms/ipxe/src/arch/i386/prefix/undiloader.S @@ -14,6 +14,7 @@ undiloader: /* Save registers */ pushl %esi pushl %edi + pushl %ebp pushw %ds pushw %es pushw %bx @@ -30,7 +31,7 @@ undiloader: movw %es:14(%di), %ax movl image_source, %esi movl decompress_to, %edi - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ call install_prealloc popw %di /* Call UNDI loader C code */ @@ -46,6 +47,7 @@ undiloader: popw %bx popw %es popw %ds + popl %ebp popl %edi popl %esi lret diff --git a/roms/ipxe/src/arch/i386/scripts/i386.lds b/roms/ipxe/src/arch/i386/scripts/i386.lds index c5bc631fa..fb763656c 100644 --- a/roms/ipxe/src/arch/i386/scripts/i386.lds +++ b/roms/ipxe/src/arch/i386/scripts/i386.lds @@ -1,4 +1,4 @@ -/* -*- sh -*- */ +/* -*- ld-script -*- */ /* * Linker script for i386 images @@ -39,8 +39,8 @@ SECTIONS { } .bss.prefix (NOLOAD) : AT ( _end_lma ) { _eprefix = .; } - _prefix_filesz = ABSOLUTE ( _mprefix - _prefix ); - _prefix_memsz = ABSOLUTE ( _eprefix - _prefix ); + _prefix_filesz = ABSOLUTE ( _mprefix ) - ABSOLUTE ( _prefix ); + _prefix_memsz = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix ); /* * The 16-bit (real-mode) code section @@ -63,11 +63,11 @@ SECTIONS { } .bss.text16 (NOLOAD) : AT ( _end_lma ) { _etext16 = .; } - _text16_early_filesz = ABSOLUTE ( _etext16_early - _text16 ); - _text16_early_memsz = ABSOLUTE ( _etext16_early - _text16 ); - _text16_late_filesz = ABSOLUTE ( _mtext16 - _text16_late ); - _text16_late_memsz = ABSOLUTE ( _etext16 - _text16_late ); - _text16_memsz = ABSOLUTE ( _etext16 - _text16 ); + _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 @@ -89,8 +89,8 @@ SECTIONS { *(.stack16.*) _edata16 = .; } - _data16_filesz = ABSOLUTE ( _mdata16 - _data16 ); - _data16_memsz = ABSOLUTE ( _edata16 - _data16 ); + _data16_filesz = ABSOLUTE ( _mdata16 ) - ABSOLUTE ( _data16 ); + _data16_memsz = ABSOLUTE ( _edata16 ) - ABSOLUTE ( _data16 ); /* * The 32-bit sections @@ -118,8 +118,25 @@ SECTIONS { *(.stack.*) _etextdata = .; } - _textdata_filesz = ABSOLUTE ( _mtextdata - _textdata ); - _textdata_memsz = ABSOLUTE ( _etextdata - _textdata ); + _textdata_filesz = ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata ); + _textdata_memsz = ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata ); + + /* + * Payload prefix + * + * If present, this will be placed between .text16.early and .text16.late. + * + */ + .pprefix 0x0 : AT ( _pprefix_lma ) { + _pprefix = .; + KEEP(*(.pprefix)) + KEEP(*(.pprefix.*)) + _mpprefix = .; + } .bss.pprefix (NOLOAD) : AT ( _end_lma ) { + _epprefix = .; + } + _pprefix_filesz = ABSOLUTE ( _mpprefix ) - ABSOLUTE ( _pprefix ); + _pprefix_memsz = ABSOLUTE ( _epprefix ) - ABSOLUTE ( _pprefix ); /* * Compressor information block @@ -134,8 +151,8 @@ SECTIONS { } .bss.zinfo (NOLOAD) : AT ( _end_lma ) { _ezinfo = .; } - _zinfo_filesz = ABSOLUTE ( _mzinfo - _zinfo ); - _zinfo_memsz = ABSOLUTE ( _ezinfo - _zinfo ); + _zinfo_filesz = ABSOLUTE ( _mzinfo ) - ABSOLUTE ( _zinfo ); + _zinfo_memsz = ABSOLUTE ( _ezinfo ) - ABSOLUTE ( _zinfo ); /* * Weak symbols that need zero values if not otherwise defined @@ -187,8 +204,14 @@ SECTIONS { _text16_early_lma = .; . += _text16_early_filesz; + . = ALIGN ( _max_align ); + . = ALIGN ( _payload_align ); + _pprefix_lma = .; + . += _pprefix_filesz; + . = ALIGN ( _max_align ); _payload_lma = .; + _pprefix_skip = ABSOLUTE ( _payload_lma ) - ABSOLUTE ( _pprefix_lma ); _text16_late_lma = .; . += _text16_late_filesz; diff --git a/roms/ipxe/src/arch/i386/transitions/liba20.S b/roms/ipxe/src/arch/i386/transitions/liba20.S index 594d62010..684697525 100644 --- a/roms/ipxe/src/arch/i386/transitions/liba20.S +++ b/roms/ipxe/src/arch/i386/transitions/liba20.S @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ @@ -96,8 +97,11 @@ test_a20_long: .section ".text16.early", "awx", @progbits .code16 enable_a20_bios: - /* Preserve registers */ - pushw %ax + + /* Preserve registers. Be very paranoid, since some BIOSes + * are reported to clobber %ebx + */ + pushal /* Attempt INT 15,2401 */ movw $0x2401, %ax @@ -108,7 +112,7 @@ enable_a20_bios: call test_a20_short 99: /* Restore registers and return */ - popw %ax + popal ret .size enable_a20_bios, . - enable_a20_bios diff --git a/roms/ipxe/src/arch/i386/transitions/librm.S b/roms/ipxe/src/arch/i386/transitions/librm.S index 5eb82b44b..02d25b22c 100644 --- a/roms/ipxe/src/arch/i386/transitions/librm.S +++ b/roms/ipxe/src/arch/i386/transitions/librm.S @@ -97,18 +97,18 @@ init_librm: pushl %eax pushl %ebx - /* Store _virt_offset and set up virtual_cs and virtual_ds segments */ + /* 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, _virt_offset + movl %edi, rm_virt_offset /* Negate virt_offset */ negl %edi - /* Store rm_cs and _text16, set up real_cs segment */ + /* Store rm_cs and text16, set up real_cs segment */ xorl %eax, %eax movw %cs, %ax movw %ax, rm_cs @@ -116,9 +116,9 @@ init_librm: movw $real_cs, %bx call set_seg_base addr32 leal (%eax, %edi), %ebx - movl %ebx, _text16 + movl %ebx, rm_text16 - /* Store rm_ds and _data16, set up real_ds segment */ + /* Store rm_ds and data16, set up real_ds segment */ xorl %eax, %eax movw %ds, %ax movw %ax, %cs:rm_ds @@ -126,7 +126,7 @@ init_librm: movw $real_ds, %bx call set_seg_base addr32 leal (%eax, %edi), %ebx - movl %ebx, _data16 + movl %ebx, rm_data16 /* Set GDT and IDT base */ movl %eax, gdt_base @@ -182,12 +182,12 @@ real_to_prot: movw %cs:rm_ds, %ax movw %ax, %ds - /* Add _virt_offset, _text16 and _data16 to stack to be + /* Add virt_offset, text16 and data16 to stack to be * copied, and also copy the return address. */ - pushl _virt_offset - pushl _text16 - pushl _data16 + 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 */ @@ -197,7 +197,7 @@ real_to_prot: movl %ebp, %eax shll $4, %eax addr32 leal (%eax,%edx), %esi - subl _virt_offset, %esi + subl rm_virt_offset, %esi /* Switch to protected mode */ cli @@ -557,9 +557,9 @@ pm_esp: .long _estack */ /* Internal copies, created by init_librm (which runs in real mode) */ .section ".data16", "aw", @progbits -_virt_offset: .long 0 -_text16: .long 0 -_data16: .long 0 +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 diff --git a/roms/ipxe/src/arch/x86/Makefile b/roms/ipxe/src/arch/x86/Makefile index 37e03aafa..cdd397d40 100644 --- a/roms/ipxe/src/arch/x86/Makefile +++ b/roms/ipxe/src/arch/x86/Makefile @@ -7,6 +7,7 @@ INCDIRS += arch/x86/include SRCDIRS += arch/x86/core SRCDIRS += arch/x86/interface/efi SRCDIRS += arch/x86/prefix +SRCDIRS += arch/x86/hci/commands # breaks building some of the linux-related objects CFLAGS += -Ulinux diff --git a/roms/ipxe/src/arch/x86/core/cpuid.c b/roms/ipxe/src/arch/x86/core/cpuid.c new file mode 100644 index 000000000..96f794095 --- /dev/null +++ b/roms/ipxe/src/arch/x86/core/cpuid.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include + +/** @file + * + * x86 CPU feature detection + * + */ + +/** + * Check whether or not CPUID instruction is supported + * + * @ret is_supported CPUID instruction is supported + */ +static int cpuid_is_supported ( void ) { + unsigned long original; + unsigned long inverted; + + __asm__ ( "pushf\n\t" + "pushf\n\t" + "pop %0\n\t" + "mov %0,%1\n\t" + "xor %2,%1\n\t" + "push %1\n\t" + "popf\n\t" + "pushf\n\t" + "pop %1\n\t" + "popf\n\t" + : "=&r" ( original ), "=&r" ( inverted ) + : "ir" ( CPUID_FLAG ) ); + return ( ( original ^ inverted ) & CPUID_FLAG ); +} + +/** + * Issue CPUID instruction + * + * @v operation CPUID operation + * @v eax Output via %eax + * @v ebx Output via %ebx + * @v ecx Output via %ecx + * @v edx Output via %edx + */ +static inline __attribute__ (( always_inline )) void +cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, + uint32_t *edx ) { + + __asm__ ( "cpuid" + : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx ) + : "0" ( operation ) ); +} + +/** + * Get Intel-defined x86 CPU features + * + * @v features x86 CPU features to fill in + */ +static void x86_intel_features ( struct x86_features *features ) { + uint32_t max_level; + uint32_t discard_a; + uint32_t discard_b; + uint32_t discard_c; + uint32_t discard_d; + + /* Check that features are available via CPUID */ + cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c, + &discard_d ); + if ( max_level < CPUID_FEATURES ) { + DBGC ( features, "CPUID has no Intel-defined features (max " + "level %08x)\n", max_level ); + return; + } + + /* Get features */ + cpuid ( CPUID_FEATURES, &discard_a, &discard_b, + &features->intel.ecx, &features->intel.edx ); + DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n", + features->intel.ecx, features->intel.edx ); + +} + +/** + * Get AMD-defined x86 CPU features + * + * @v features x86 CPU features to fill in + */ +static void x86_amd_features ( struct x86_features *features ) { + uint32_t max_level; + uint32_t discard_a; + uint32_t discard_b; + uint32_t discard_c; + uint32_t discard_d; + + /* Check that features are available via CPUID */ + cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c, + &discard_d ); + if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) { + DBGC ( features, "CPUID has no extended functions\n" ); + return; + } + if ( max_level < CPUID_AMD_FEATURES ) { + DBGC ( features, "CPUID has no AMD-defined features (max " + "level %08x)\n", max_level ); + return; + } + + /* Get features */ + cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b, + &features->amd.ecx, &features->amd.edx ); + DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n", + features->amd.ecx, features->amd.edx ); +} + +/** + * Get x86 CPU features + * + * @v features x86 CPU features to fill in + */ +void x86_features ( struct x86_features *features ) { + + /* Clear all features */ + memset ( features, 0, sizeof ( *features ) ); + + /* Check that CPUID instruction is available */ + if ( ! cpuid_is_supported() ) { + DBGC ( features, "CPUID instruction is not supported\n" ); + return; + } + + /* Get Intel-defined features */ + x86_intel_features ( features ); + + /* Get AMD-defined features */ + x86_amd_features ( features ); +} diff --git a/roms/ipxe/src/arch/x86/core/debugcon.c b/roms/ipxe/src/arch/x86/core/debugcon.c new file mode 100644 index 000000000..b89480aa5 --- /dev/null +++ b/roms/ipxe/src/arch/x86/core/debugcon.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +/** @file + * + * Debug port console + * + * The debug port is supported by bochs (via the "port_e9_hack" + * configuration file directive) and by qemu (via the "-debugcon" + * command-line option). + */ + +#include +#include +#include +#include +#include + +/** Debug port */ +#define DEBUG_PORT 0xe9 + +/** Debug port installation check magic value */ +#define DEBUG_PORT_CHECK 0xe9 + +/* Set default console usage if applicable */ +#if ! ( defined ( CONSOLE_DEBUGCON ) && CONSOLE_EXPLICIT ( CONSOLE_DEBUGCON ) ) +#undef CONSOLE_DEBUGCON +#define CONSOLE_DEBUGCON ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI ) +#endif + +/** + * Print a character to debug port console + * + * @v character Character to be printed + */ +static void debugcon_putchar ( int character ) { + + /* Write character to debug port */ + outb ( character, DEBUG_PORT ); +} + +/** Debug port console driver */ +struct console_driver debugcon_console __console_driver = { + .putchar = debugcon_putchar, + .usage = CONSOLE_DEBUGCON, +}; + +/** + * Initialise debug port console + * + */ +static void debugcon_init ( void ) { + uint8_t check; + + /* Check if console is present */ + check = inb ( DEBUG_PORT ); + if ( check != DEBUG_PORT_CHECK ) { + DBG ( "Debug port not present; disabling console\n" ); + debugcon_console.disabled = 1; + } +} + +/** + * Debug port console initialisation function + */ +struct init_fn debugcon_init_fn __init_fn ( INIT_EARLY ) = { + .initialise = debugcon_init, +}; diff --git a/roms/ipxe/src/arch/x86/core/pcidirect.c b/roms/ipxe/src/arch/x86/core/pcidirect.c index a07f7d4ba..dbc8317b8 100644 --- a/roms/ipxe/src/arch/x86/core/pcidirect.c +++ b/roms/ipxe/src/arch/x86/core/pcidirect.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/x86/core/x86_bigint.c b/roms/ipxe/src/arch/x86/core/x86_bigint.c new file mode 100644 index 000000000..418ac2309 --- /dev/null +++ b/roms/ipxe/src/arch/x86/core/x86_bigint.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include + +/** @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/roms/ipxe/src/arch/x86/core/x86_io.c b/roms/ipxe/src/arch/x86/core/x86_io.c new file mode 100644 index 000000000..9b2d2d935 --- /dev/null +++ b/roms/ipxe/src/arch/x86/core/x86_io.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2008 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include + +/** @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 __unused uint64_t i386_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 __unused void i386_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_INLINE ( x86, writeb ); +PROVIDE_IOAPI_INLINE ( x86, writew ); +PROVIDE_IOAPI_INLINE ( x86, writel ); +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 ); +#ifdef __x86_64__ +PROVIDE_IOAPI_INLINE ( x86, readq ); +PROVIDE_IOAPI_INLINE ( x86, writeq ); +#else +PROVIDE_IOAPI ( x86, readq, i386_readq ); +PROVIDE_IOAPI ( x86, writeq, i386_writeq ); +#endif diff --git a/roms/ipxe/src/arch/x86/core/x86_string.c b/roms/ipxe/src/arch/x86/core/x86_string.c index 5838ebace..d48347c96 100644 --- a/roms/ipxe/src/arch/x86/core/x86_string.c +++ b/roms/ipxe/src/arch/x86/core/x86_string.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** @file @@ -34,7 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v len Length * @ret dest Destination address */ -void * __memcpy ( void *dest, const void *src, size_t len ) { +void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src, + size_t len ) { void *edi = dest; const void *esi = src; int discard_ecx; @@ -43,21 +45,146 @@ void * __memcpy ( void *dest, const void *src, size_t len ) { * 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" ); + __asm__ __volatile__ ( "rep movsl" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len >> 2 ) + : "memory" ); + __asm__ __volatile__ ( "rep movsb" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len & 3 ) + : "memory" ); + return dest; +} + +/** + * Copy memory area backwards + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest, + const void *src, + size_t len ) { + void *edi = ( dest + len - 1 ); + const void *esi = ( src + len - 1 ); + int discard_ecx; + + /* Assume memmove() is not performance-critical, and perform a + * bytewise copy for simplicity. + */ + __asm__ __volatile__ ( "std\n\t" + "rep movsb\n\t" + "cld\n\t" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), + "2" ( len ) + : "memory" ); + return dest; +} + + +/** + * Copy (possibly overlapping) memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __memmove ( void *dest, const void *src, size_t len ) { + + if ( dest <= src ) { + return __memcpy ( dest, src, len ); + } else { + return __memcpy_reverse ( dest, src, len ); } +} + +/** + * Swap memory areas + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * memswap ( void *dest, void *src, size_t len ) { + size_t discard_c; + int discard; + + __asm__ __volatile__ ( "\n1:\n\t" + "dec %2\n\t" + "js 2f\n\t" + "movb (%0,%2), %b3\n\t" + "xchgb (%1,%2), %b3\n\t" + "movb %b3, (%0,%2)\n\t" + "jmp 1b\n\t" + "2:\n\t" + : "=r" ( src ), "=r" ( dest ), + "=&c" ( discard_c ), "=&q" ( discard ) + : "0" ( src ), "1" ( dest ), "2" ( len ) + : "memory" ); + return dest; } + +/** + * Calculate length of string + * + * @v string String + * @ret len Length (excluding NUL) + */ +size_t strlen ( const char *string ) { + const char *discard_D; + size_t len_plus_one; + + __asm__ __volatile__ ( "repne scasb\n\t" + "not %1\n\t" + : "=&D" ( discard_D ), "=&c" ( len_plus_one ) + : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) ); + + return ( len_plus_one - 1 ); +} + +/** + * Compare strings (up to a specified length) + * + * @v str1 First string + * @v str2 Second string + * @v len Maximum length + * @ret diff Difference + */ +int strncmp ( const char *str1, const char *str2, size_t len ) { + const void *discard_S; + const void *discard_D; + size_t discard_c; + int diff; + + __asm__ __volatile__ ( "\n1:\n\t" + "dec %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %b3, %b3\n\t" + "jnz 1b\n\t" + /* Equal */ + "\n2:\n\t" + "xor %3, %3\n\t" + "jmp 4f\n\t" + /* Not equal; CF indicates difference */ + "\n3:\n\t" + "sbb %3, %3\n\t" + "orb $1, %b3\n\t" + "\n4:\n\t" + : "=&S" ( discard_S ), "=&D" ( discard_D ), + "=&c" ( discard_c ), "=&a" ( diff ) + : "0" ( str1 ), "1" ( str2 ), "2" ( len ) ); + + return diff; +} diff --git a/roms/ipxe/src/arch/x86/core/x86_tcpip.c b/roms/ipxe/src/arch/x86/core/x86_tcpip.c new file mode 100644 index 000000000..8a4ce5152 --- /dev/null +++ b/roms/ipxe/src/arch/x86/core/x86_tcpip.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +/** @file + * + * TCP/IP checksum + * + */ + +#include +#include + +extern char x86_tcpip_loop_end[]; + +/** + * 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 + */ +uint16_t x86_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ) { + unsigned long sum = ( ( ~partial ) & 0xffff ); + unsigned long initial_word_count; + unsigned long loop_count; + unsigned long loop_partial_count; + unsigned long final_word_count; + unsigned long final_byte; + unsigned long discard_S; + unsigned long discard_c; + unsigned long discard_a; + unsigned long discard_r1; + unsigned long discard_r2; + + /* Calculate number of initial 16-bit words required to bring + * the main loop into alignment. (We don't care about the + * speed for data aligned to less than 16 bits, since this + * situation won't occur in practice.) + */ + if ( len >= sizeof ( sum ) ) { + initial_word_count = ( ( -( ( intptr_t ) data ) & + ( sizeof ( sum ) - 1 ) ) >> 1 ); + } else { + initial_word_count = 0; + } + len -= ( initial_word_count * 2 ); + + /* Calculate number of iterations of the main loop. This loop + * processes native machine words (32-bit or 64-bit), and is + * unrolled 16 times. We calculate an overall iteration + * count, and a starting point for the first iteration. + */ + loop_count = ( len / ( sizeof ( sum ) * 16 ) ); + loop_partial_count = + ( ( len % ( sizeof ( sum ) * 16 ) ) / sizeof ( sum ) ); + + /* Calculate number of 16-bit words remaining after the main + * loop completes. + */ + final_word_count = ( ( len % sizeof ( sum ) ) / 2 ); + + /* Calculate whether or not a final byte remains at the end */ + final_byte = ( len & 1 ); + + /* Calculate the checksum */ + __asm__ ( /* Calculate position at which to jump into the + * unrolled loop. + */ + "imul $( -x86_tcpip_loop_step_size ), %4\n\t" + "add %5, %4\n\t" + + /* Clear carry flag before starting checksumming */ + "clc\n\t" + + /* Checksum initial words */ + "jmp 2f\n\t" + "\n1:\n\t" + "lodsw\n\t" + "adcw %w2, %w0\n\t" + "\n2:\n\t" + "loop 1b\n\t" + + /* Main "lods;adc" loop, unrolled x16 */ + "mov %12, %3\n\t" + "jmp *%4\n\t" + "\nx86_tcpip_loop_start:\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "\nx86_tcpip_loop_end:\n\t" + "loop x86_tcpip_loop_start\n\t" + ".equ x86_tcpip_loop_step_size, " + " ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) >> 4 )\n\t" + + /* Checksum remaining whole words */ + "mov %13, %3\n\t" + "jmp 2f\n\t" + "\n1:\n\t" + "lodsw\n\t" + "adcw %w2, %w0\n\t" + "\n2:\n\t" + "loop 1b\n\t" + + /* Checksum final byte if applicable */ + "mov %14, %3\n\t" + "loop 1f\n\t" + "adcb (%1), %b0\n\t" + "adcb $0, %h0\n\t" + "\n1:\n\t" + + /* Fold down to a uint16_t */ + "push %0\n\t" + "popw %w0\n\t" + "popw %w2\n\t" + "adcw %w2, %w0\n\t" +#if ULONG_MAX > 0xffffffffUL /* 64-bit only */ + "popw %w2\n\t" + "adcw %w2, %w0\n\t" + "popw %w2\n\t" + "adcw %w2, %w0\n\t" +#endif /* 64-bit only */ + + /* Consume CF */ + "adcw $0, %w0\n\t" + "adcw $0, %w0\n\t" + + : "=&Q" ( sum ), "=&S" ( discard_S ), "=&a" ( discard_a ), + "=&c" ( discard_c ), "=&r" ( discard_r1 ), + "=&r" ( discard_r2 ) + : "0" ( sum ), "1" ( data ), "2" ( 0 ), + "3" ( initial_word_count + 1 ), "4" ( loop_partial_count ), + "5" ( x86_tcpip_loop_end ), "g" ( loop_count + 1 ), + "g" ( final_word_count + 1 ), "g" ( final_byte ) ); + + return ( ~sum & 0xffff ); +} diff --git a/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c b/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c new file mode 100644 index 000000000..981143308 --- /dev/null +++ b/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * x86 CPU feature detection command + * + */ + +/** "cpuid" options */ +struct cpuid_options { + /** Check AMD-defined features (%eax=0x80000001) */ + int amd; + /** Check features defined via %ecx */ + int ecx; +}; + +/** "cpuid" option list */ +static struct option_descriptor cpuid_opts[] = { + OPTION_DESC ( "ext", 'e', no_argument, + struct cpuid_options, amd, parse_flag ), + /* "--amd" retained for backwards compatibility */ + OPTION_DESC ( "amd", 'a', no_argument, + struct cpuid_options, amd, parse_flag ), + OPTION_DESC ( "ecx", 'c', no_argument, + struct cpuid_options, ecx, parse_flag ), +}; + +/** "cpuid" command descriptor */ +static struct command_descriptor cpuid_cmd = + COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1, + "[--ext] [--ecx] " ); + +/** + * The "cpuid" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int cpuid_exec ( int argc, char **argv ) { + struct cpuid_options opts; + struct x86_features features; + struct x86_feature_registers *feature_regs; + uint32_t feature_reg; + unsigned int bit; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &cpuid_cmd, &opts ) ) != 0 ) + return rc; + + /* Parse bit number */ + if ( ( rc = parse_integer ( argv[optind], &bit ) ) != 0 ) + return rc; + + /* Get CPU features */ + x86_features ( &features ); + + /* Extract relevant feature register */ + feature_regs = ( opts.amd ? &features.amd : &features.intel ); + feature_reg = ( opts.ecx ? feature_regs->ecx : feature_regs->edx ); + + /* Check presence of specified feature */ + return ( ( feature_reg & ( 1 << bit ) ) ? 0 : -ENOENT ); +} + +/** x86 CPU feature detection command */ +struct command cpuid_command __command = { + .name = "cpuid", + .exec = cpuid_exec, +}; diff --git a/roms/ipxe/src/arch/x86/include/bits/bigint.h b/roms/ipxe/src/arch/x86/include/bits/bigint.h new file mode 100644 index 000000000..d3449af5a --- /dev/null +++ b/roms/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 +#include + +/** 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/roms/ipxe/src/arch/x86/include/bits/errfile.h b/roms/ipxe/src/arch/x86/include/bits/errfile.h new file mode 100644 index 000000000..7b9f3702e --- /dev/null +++ b/roms/ipxe/src/arch/x86/include/bits/errfile.h @@ -0,0 +1,50 @@ +#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_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) +#define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 ) + +#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 ) + +#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 ) + +/** @} */ + +#endif /* _BITS_ERRFILE_H */ diff --git a/roms/ipxe/src/arch/x86/include/bits/io.h b/roms/ipxe/src/arch/x86/include/bits/io.h new file mode 100644 index 000000000..cb1b67a6f --- /dev/null +++ b/roms/ipxe/src/arch/x86/include/bits/io.h @@ -0,0 +1,14 @@ +#ifndef _BITS_IO_H +#define _BITS_IO_H + +/** @file + * + * x86-specific I/O API implementations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +#endif /* _BITS_IO_H */ diff --git a/roms/ipxe/src/arch/x86/include/bits/string.h b/roms/ipxe/src/arch/x86/include/bits/string.h index f35cdab1c..dce994983 100644 --- a/roms/ipxe/src/arch/x86/include/bits/string.h +++ b/roms/ipxe/src/arch/x86/include/bits/string.h @@ -1,44 +1,46 @@ -#ifndef ETHERBOOT_BITS_STRING_H -#define ETHERBOOT_BITS_STRING_H +#ifndef X86_BITS_STRING_H +#define X86_BITS_STRING_H + /* - * Taken from Linux /usr/include/asm/string.h - * All except memcpy, memmove, memset and memcmp removed. + * Copyright (C) 2007 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * - * Non-standard memswap() function added because it saves quite a bit - * of code (mbrown@fensystems.co.uk). + * You 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. */ -/* - * 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 :-) +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Optimised string operations * - * 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 ); +extern void * __memcpy_reverse ( 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 - +/** + * Copy memory area (where length is a compile-time constant) + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ static inline __attribute__ (( always_inline )) void * __constant_memcpy ( void *dest, const void *src, size_t len ) { union { @@ -150,103 +152,81 @@ __constant_memcpy ( void *dest, const void *src, size_t len ) { return dest; } -#define memcpy( dest, src, len ) \ - ( __builtin_constant_p ( (len) ) ? \ - __constant_memcpy ( (dest), (src), (len) ) : \ - __memcpy ( (dest), (src), (len) ) ) +/** + * Copy memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +static inline __attribute__ (( always_inline )) void * +memcpy ( void *dest, const void *src, size_t len ) { + if ( __builtin_constant_p ( len ) ) { + return __constant_memcpy ( dest, src, len ); + } else { + return __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 + +/** An x86 CPU feature register set */ +struct x86_feature_registers { + /** Features returned via %ecx */ + uint32_t ecx; + /** Features returned via %edx */ + uint32_t edx; +}; + +/** x86 CPU features */ +struct x86_features { + /** Intel-defined features (%eax=0x00000001) */ + struct x86_feature_registers intel; + /** AMD-defined features (%eax=0x80000001) */ + struct x86_feature_registers amd; +}; + +/** CPUID support flag */ +#define CPUID_FLAG 0x00200000UL + +/** Get vendor ID and largest standard function */ +#define CPUID_VENDOR_ID 0x00000000UL + +/** Get standard features */ +#define CPUID_FEATURES 0x00000001UL + +/** Get largest extended function */ +#define CPUID_AMD_MAX_FN 0x80000000UL + +/** Extended function existence check */ +#define CPUID_AMD_CHECK 0x80000000UL + +/** Extended function existence check mask */ +#define CPUID_AMD_CHECK_MASK 0xffff0000UL + +/** Get extended features */ +#define CPUID_AMD_FEATURES 0x80000001UL + +extern void x86_features ( struct x86_features *features ); + +#endif /* _IPXE_CPUID_H */ diff --git a/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h b/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h new file mode 100644 index 000000000..adb00a686 --- /dev/null +++ b/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h @@ -0,0 +1,159 @@ +#ifndef _IPXE_X86_IO_H +#define _IPXE_X86_IO_H + +/** @file + * + * iPXE I/O API for x86 + * + * x86 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 + * under i386, 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 native word size + * + */ + +#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 ); +#ifdef __x86_64__ +X86_READX ( readq, uint64_t ); +#endif + +#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 ); +#ifdef __x86_64__ +X86_WRITEX ( writeq, uint64_t ); +#endif + +/* + * 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/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c b/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c index b6bee6276..b05421fab 100644 --- a/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c +++ b/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c b/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c index a96c5c439..8a31df56d 100644 --- a/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c +++ b/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/x86/prefix/efiprefix.c b/roms/ipxe/src/arch/x86/prefix/efiprefix.c index 1515c6fc4..bfa94d404 100644 --- a/roms/ipxe/src/arch/x86/prefix/efiprefix.c +++ b/roms/ipxe/src/arch/x86/prefix/efiprefix.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/arch/x86_64/Makefile b/roms/ipxe/src/arch/x86_64/Makefile index d2c2ff53d..b687f3407 100644 --- a/roms/ipxe/src/arch/x86_64/Makefile +++ b/roms/ipxe/src/arch/x86_64/Makefile @@ -26,6 +26,18 @@ CFLAGS += -fshort-wchar # CFLAGS += -Ui386 +# Add -maccumulate-outgoing-args if required by this version of gcc +# +ifeq ($(CCTYPE),gcc) +MS_ABI_TEST_CODE := extern void __attribute__ (( ms_abi )) ms_abi(); \ + void sysv_abi ( void ) { ms_abi(); } +MS_ABI_TEST = $(ECHO) '$(MS_ABI_TEST_CODE)' | \ + $(CC) -m64 -mno-accumulate-outgoing-args -x c -c - -o /dev/null \ + >/dev/null 2>&1 +MS_ABI_FLAGS := $(shell $(MS_ABI_TEST) || $(ECHO) '-maccumulate-outgoing-args') +WORKAROUND_CFLAGS += $(MS_ABI_FLAGS) +endif + # x86_64-specific directories containing source files # SRCDIRS += arch/x86_64/prefix diff --git a/roms/ipxe/src/arch/x86_64/core/linux/linuxprefix.S b/roms/ipxe/src/arch/x86_64/core/linux/linuxprefix.S new file mode 100644 index 000000000..ec8a9decd --- /dev/null +++ b/roms/ipxe/src/arch/x86_64/core/linux/linuxprefix.S @@ -0,0 +1,25 @@ +#include + + .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/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h b/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h index 9ed85e8f8..2e472d98a 100644 --- a/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h +++ b/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h @@ -1,22 +1,47 @@ #ifndef _BITS_BYTESWAP_H #define _BITS_BYTESWAP_H +/** @file + * + * Byte-order swapping functions + * + */ + +#include + +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/roms/ipxe/src/arch/x86_64/include/bits/entropy.h b/roms/ipxe/src/arch/x86_64/include/bits/entropy.h new file mode 100644 index 000000000..9c64c833b --- /dev/null +++ b/roms/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/roms/ipxe/src/arch/x86_64/include/bits/errfile.h b/roms/ipxe/src/arch/x86_64/include/bits/errfile.h deleted file mode 100644 index dcda26ba4..000000000 --- a/roms/ipxe/src/arch/x86_64/include/bits/errfile.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BITS_ERRFILE_H -#define _BITS_ERRFILE_H - -/** - * @addtogroup errfile Error file identifiers - * @{ - */ - -/** @} */ - -#endif /* _BITS_ERRFILE_H */ diff --git a/roms/ipxe/src/arch/x86_64/include/bits/io.h b/roms/ipxe/src/arch/x86_64/include/bits/io.h deleted file mode 100644 index 921fdcc05..000000000 --- a/roms/ipxe/src/arch/x86_64/include/bits/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_IO_H -#define _BITS_IO_H - -/** @file - * - * x86_64-specific I/O API implementations - * - */ - -#endif /* _BITS_IO_H */ diff --git a/roms/ipxe/src/arch/x86_64/include/bits/time.h b/roms/ipxe/src/arch/x86_64/include/bits/time.h new file mode 100644 index 000000000..59b355359 --- /dev/null +++ b/roms/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/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h b/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h index af41b195e..9a4790fdc 100644 --- a/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h +++ b/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h @@ -30,10 +30,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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', '7', ':', \ + '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 ( 7 ) +#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 */ ) diff --git a/roms/ipxe/src/arch/x86_64/prefix/linuxprefix.S b/roms/ipxe/src/arch/x86_64/prefix/linuxprefix.S deleted file mode 100644 index 713b9e38d..000000000 --- a/roms/ipxe/src/arch/x86_64/prefix/linuxprefix.S +++ /dev/null @@ -1,25 +0,0 @@ -#include - - .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 _start, . - _start diff --git a/roms/ipxe/src/config/colour.h b/roms/ipxe/src/config/colour.h new file mode 100644 index 000000000..d32d46dc5 --- /dev/null +++ b/roms/ipxe/src/config/colour.h @@ -0,0 +1,32 @@ +#ifndef CONFIG_COLOUR_H +#define CONFIG_COLOUR_H + +/** @file + * + * Display colour configuration + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#define COLOR_NORMAL_FG COLOR_WHITE +#define COLOR_NORMAL_BG COLOR_BLUE + +#define COLOR_SELECT_FG COLOR_WHITE +#define COLOR_SELECT_BG COLOR_RED + +#define COLOR_SEPARATOR_FG COLOR_CYAN +#define COLOR_SEPARATOR_BG COLOR_BLUE + +#define COLOR_EDIT_FG COLOR_BLACK +#define COLOR_EDIT_BG COLOR_CYAN + +#define COLOR_ALERT_FG COLOR_WHITE +#define COLOR_ALERT_BG COLOR_RED + +#define COLOR_URL_FG COLOR_CYAN +#define COLOR_URL_BG COLOR_BLUE + +#include + +#endif /* CONFIG_COLOUR_H */ diff --git a/roms/ipxe/src/config/config.c b/roms/ipxe/src/config/config.c index 2c3555ead..bd1d98856 100644 --- a/roms/ipxe/src/config/config.c +++ b/roms/ipxe/src/config/config.c @@ -71,21 +71,27 @@ REQUIRE_OBJECT ( serial_console ); #ifdef CONSOLE_DIRECT_VGA REQUIRE_OBJECT ( video_subr ); #endif -#ifdef CONSOLE_BTEXT -REQUIRE_OBJECT ( btext ); -#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 +#ifdef CONSOLE_DEBUGCON +REQUIRE_OBJECT ( debugcon ); +#endif /* * Drag in all requested network protocols @@ -122,9 +128,6 @@ REQUIRE_OBJECT ( https ); #ifdef DOWNLOAD_PROTO_FTP REQUIRE_OBJECT ( ftp ); #endif -#ifdef DOWNLOAD_PROTO_TFTM -REQUIRE_OBJECT ( tftm ); -#endif #ifdef DOWNLOAD_PROTO_SLAM REQUIRE_OBJECT ( slam ); #endif @@ -155,18 +158,9 @@ REQUIRE_OBJECT ( nbi ); #ifdef IMAGE_ELF REQUIRE_OBJECT ( elfboot ); #endif -#ifdef IMAGE_FREEBSD -REQUIRE_OBJECT ( freebsd ); -#endif #ifdef IMAGE_MULTIBOOT REQUIRE_OBJECT ( multiboot ); #endif -#ifdef IMAGE_AOUT -REQUIRE_OBJECT ( aout ); -#endif -#ifdef IMAGE_WINCE -REQUIRE_OBJECT ( wince ); -#endif #ifdef IMAGE_PXE REQUIRE_OBJECT ( pxe_image ); #endif @@ -190,6 +184,9 @@ REQUIRE_OBJECT ( comboot_resolv ); #ifdef IMAGE_EFI REQUIRE_OBJECT ( efi_image ); #endif +#ifdef IMAGE_SDI +REQUIRE_OBJECT ( sdi ); +#endif /* * Drag in all requested commands @@ -214,12 +211,18 @@ REQUIRE_OBJECT ( route_cmd ); #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 @@ -241,6 +244,15 @@ REQUIRE_OBJECT ( vlan_cmd ); #ifdef REBOOT_CMD REQUIRE_OBJECT ( reboot_cmd ); #endif +#ifdef CPUID_CMD +REQUIRE_OBJECT ( cpuid_cmd ); +#endif +#ifdef SYNC_CMD +REQUIRE_OBJECT ( sync_cmd ); +#endif +#ifdef NSLOOKUP_CMD +REQUIRE_OBJECT ( nslookup_cmd ); +#endif /* * Drag in miscellaneous objects @@ -274,13 +286,16 @@ REQUIRE_OBJECT ( tap ); #endif /* - * Drag in relevant BOFM entry points + * 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 diff --git a/roms/ipxe/src/config/console.h b/roms/ipxe/src/config/console.h index afc89569c..04be02dc4 100644 --- a/roms/ipxe/src/config/console.h +++ b/roms/ipxe/src/config/console.h @@ -17,12 +17,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONSOLE_PCBIOS /* Default BIOS console */ //#define CONSOLE_SERIAL /* Serial port */ //#define CONSOLE_DIRECT_VGA /* Direct access to VGA card */ -//#define CONSOLE_BTEXT /* Who knows what this does? */ //#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 CONSOLE_DEBUGCON /* Debug port console */ #define KEYBOARD_MAP us +#define LOG_LEVEL LOG_NONE + #include #endif /* CONFIG_CONSOLE_H */ diff --git a/roms/ipxe/src/config/defaults/efi.h b/roms/ipxe/src/config/defaults/efi.h index 693f55ad9..923360ae8 100644 --- a/roms/ipxe/src/config/defaults/efi.h +++ b/roms/ipxe/src/config/defaults/efi.h @@ -8,7 +8,7 @@ */ #define UACCESS_EFI -#define IOAPI_EFI +#define IOAPI_X86 #define PCIAPI_EFI #define CONSOLE_EFI #define TIMER_EFI @@ -17,6 +17,8 @@ #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 */ diff --git a/roms/ipxe/src/config/defaults/linux.h b/roms/ipxe/src/config/defaults/linux.h index 647dc0a53..50897560d 100644 --- a/roms/ipxe/src/config/defaults/linux.h +++ b/roms/ipxe/src/config/defaults/linux.h @@ -14,6 +14,8 @@ #define NAP_LINUX #define SMBIOS_LINUX #define SANBOOT_NULL +#define ENTROPY_LINUX +#define TIME_LINUX #define DRIVERS_LINUX diff --git a/roms/ipxe/src/config/defaults/pcbios.h b/roms/ipxe/src/config/defaults/pcbios.h index 7846f8f07..c52fca972 100644 --- a/roms/ipxe/src/config/defaults/pcbios.h +++ b/roms/ipxe/src/config/defaults/pcbios.h @@ -18,13 +18,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define UMALLOC_MEMTOP #define SMBIOS_PCBIOS #define SANBOOT_PCBIOS +#define ENTROPY_RTC +#define TIME_RTC #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 PXE_STACK /* PXE stack in iPXE - required for PXELINUX */ #define PXE_MENU /* PXE menu booting */ @@ -34,4 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */ #define SANBOOT_PROTO_FCP /* Fibre Channel protocol */ +#define REBOOT_CMD /* Reboot command */ +#define CPUID_CMD /* x86 CPU feature detection command */ + #endif /* CONFIG_DEFAULTS_PCBIOS_H */ diff --git a/roms/ipxe/src/config/entropy.h b/roms/ipxe/src/config/entropy.h new file mode 100644 index 000000000..7de2f6737 --- /dev/null +++ b/roms/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 + +#include + +#endif /* CONFIG_ENTROPY_H */ diff --git a/roms/ipxe/src/config/general.h b/roms/ipxe/src/config/general.h index 9eb886514..9f0bb521b 100644 --- a/roms/ipxe/src/config/general.h +++ b/roms/ipxe/src/config/general.h @@ -58,7 +58,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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_TFTM /* Multicast Trivial File Transfer Protocol */ #undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */ /* @@ -95,15 +94,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ //#define IMAGE_NBI /* NBI image support */ //#define IMAGE_ELF /* ELF image support */ -//#define IMAGE_FREEBSD /* FreeBSD kernel image support */ //#define IMAGE_MULTIBOOT /* MultiBoot image support */ -//#define IMAGE_AOUT /* a.out image support */ -//#define IMAGE_WINCE /* WinCE 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 */ +//#define IMAGE_SDI /* SDI image support */ /* * Command-line commands to include @@ -119,13 +116,23 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define IMAGE_CMD /* Image management commands */ #define DHCP_CMD /* DHCP management commands */ #define SANBOOT_CMD /* SAN boot commands */ +#define MENU_CMD /* Menu commands */ #define LOGIN_CMD /* Login command */ -#undef TIME_CMD /* Time commands */ -#undef DIGEST_CMD /* Image crypto digest commands */ -#undef LOTEST_CMD /* Loopback testing commands */ -#undef VLAN_CMD /* VLAN commands */ -#undef PXE_CMD /* PXE commands */ -#undef REBOOT_CMD /* Reboot command */ +#define SYNC_CMD /* Sync command */ +//#define NSLOOKUP_CMD /* DNS resolving 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 diff --git a/roms/ipxe/src/config/sideband.h b/roms/ipxe/src/config/sideband.h index 5385dd721..52339993e 100644 --- a/roms/ipxe/src/config/sideband.h +++ b/roms/ipxe/src/config/sideband.h @@ -10,5 +10,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */ +//#define VMWARE_SETTINGS /* VMware GuestInfo settings */ + +#include #endif /* CONFIG_SIDEBAND_H */ diff --git a/roms/ipxe/src/config/time.h b/roms/ipxe/src/config/time.h new file mode 100644 index 000000000..0576211fd --- /dev/null +++ b/roms/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 + +#include + +#endif /* CONFIG_TIME_H */ diff --git a/roms/ipxe/src/core/acpi.c b/roms/ipxe/src/core/acpi.c index 223765f76..330f50631 100644 --- a/roms/ipxe/src/core/acpi.c +++ b/roms/ipxe/src/core/acpi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/ansiesc.c b/roms/ipxe/src/core/ansiesc.c index 05bbb8695..32e9d7c9f 100644 --- a/roms/ipxe/src/core/ansiesc.c +++ b/roms/ipxe/src/core/ansiesc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/assert.c b/roms/ipxe/src/core/assert.c new file mode 100644 index 000000000..0791ea7b9 --- /dev/null +++ b/roms/ipxe/src/core/assert.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Assertions + * + */ + +#include + +/** Number of assertion failures triggered */ +unsigned int assertion_failures = 0; diff --git a/roms/ipxe/src/core/base16.c b/roms/ipxe/src/core/base16.c index 14de7957b..1f0e536c5 100644 --- a/roms/ipxe/src/core/base16.c +++ b/roms/ipxe/src/core/base16.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/base64.c b/roms/ipxe/src/core/base64.c index 7514c1fac..bdaf70957 100644 --- a/roms/ipxe/src/core/base64.c +++ b/roms/ipxe/src/core/base64.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -54,11 +55,16 @@ void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) { uint8_t *encoded_bytes = ( ( uint8_t * ) encoded ); size_t raw_bit_len = ( 8 * len ); unsigned int bit; + unsigned int byte; + unsigned int shift; 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 ) ) ) ); + byte = ( bit / 8 ); + shift = ( bit % 8 ); + tmp = ( raw_bytes[byte] << shift ); + if ( ( byte + 1 ) < len ) + tmp |= ( raw_bytes[ byte + 1 ] >> ( 8 - shift ) ); tmp = ( ( tmp >> 2 ) & 0x3f ); *(encoded_bytes++) = base64[tmp]; } diff --git a/roms/ipxe/src/core/basename.c b/roms/ipxe/src/core/basename.c index a481c54f4..b534a7886 100644 --- a/roms/ipxe/src/core/basename.c +++ b/roms/ipxe/src/core/basename.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/bitmap.c b/roms/ipxe/src/core/bitmap.c index e9b6d9041..0d1152327 100644 --- a/roms/ipxe/src/core/bitmap.c +++ b/roms/ipxe/src/core/bitmap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/blockdev.c b/roms/ipxe/src/core/blockdev.c index 182765e30..9d118cb2f 100644 --- a/roms/ipxe/src/core/blockdev.c +++ b/roms/ipxe/src/core/blockdev.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/btext.c b/roms/ipxe/src/core/btext.c deleted file mode 100644 index 4fb7378d9..000000000 --- a/roms/ipxe/src/core/btext.c +++ /dev/null @@ -1,5039 +0,0 @@ -#if 0 - -/* - * Procedures for drawing on the screen early on in the boot process. - * - * Benjamin Herrenschmidt - * - * move to LinuxBIOS by LYH yhlu@tyan.com - * move to Etherboot by LYH - */ - -#include -#include -#include - -#undef __BIG_ENDIAN -#if 0 -#define __LITTLE_ENDIAN -#endif - -#include "btext.h" - -//#define NO_SCROLL - -#ifndef NO_SCROLL -static void scrollscreen(void); -#endif - -static void draw_byte(const unsigned char c, u32 locX, u32 locY); -#if 0 -static void draw_byte_32(const unsigned char *bits, u32 *base, u32 rb); -static void draw_byte_16(const unsigned char *bits, u32 *base, u32 rb); -#endif -static void draw_byte_8(const unsigned char *bits, u32 *base, u32 rb); - -static u32 g_loc_X; -static u32 g_loc_Y; -static u32 g_max_loc_X; -static u32 g_max_loc_Y; - -#define CHAR_256 0 - -#if CHAR_256==1 -#define cmapsz (16*256) -#else -#define cmapsz (16*96) -#endif - -static const unsigned char vga_font[cmapsz]; - -u32 boot_text_mapped; - -boot_infos_t disp_bi; - -#define BTEXT -#define BTDATA - - -/* This function will enable the early boot text when doing OF booting. This - * way, xmon output should work too - */ -static void -btext_setup_display(u32 width, u32 height, u32 depth, u32 pitch, - unsigned long address) -{ - boot_infos_t* bi = &disp_bi; - - g_loc_X = 0; - g_loc_Y = 0; - g_max_loc_X = width / 8; - g_max_loc_Y = height / 16; -// bi->logicalDisplayBase = (unsigned char *)address; - bi->dispDeviceBase = address; - bi->dispDeviceRowBytes = pitch; - bi->dispDeviceDepth = depth; - bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; - boot_text_mapped = 0; -} - -/* Here's a small text engine to use during early boot - * or for debugging purposes - * - * todo: - * - * - build some kind of vgacon with it to enable early printk - * - move to a separate file - * - add a few video driver hooks to keep in sync with display - * changes. - */ - -static void -map_boot_text(void) -{ - boot_infos_t *bi = &disp_bi; - - if (bi->dispDeviceBase == 0) - return; - - boot_text_mapped = 0; - - bi->logicalDisplayBase = phys_to_virt(bi->dispDeviceBase); - - boot_text_mapped = 1; -} - -/* Calc the base address of a given point (x,y) */ -static unsigned char * BTEXT -calc_base(boot_infos_t *bi, u32 x, u32 y) -{ - unsigned char *base; - base = bi->logicalDisplayBase; -#if 0 - /* Ummm... which moron wrote this? */ - if (base == 0) - base = bi->dispDeviceBase; -#endif - base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); - base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; - return base; -} - - -static void BTEXT btext_clearscreen(void) -{ - boot_infos_t* bi = &disp_bi; - u32 *base = (u32 *)calc_base(bi, 0, 0); - u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - u32 i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - u32 *ptr = base; - for(j=width; j; --j) - *(ptr++) = 0; - base += (bi->dispDeviceRowBytes >> 2); - } -} - -#if 0 -__inline__ void dcbst(const void* addr) -{ - __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); -} - -static void BTEXT btext_flushscreen(void) -{ - boot_infos_t* bi = &disp_bi; - u32 *base = (unsigned long *)calc_base(bi, 0, 0); - u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - u32 i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - u32 *ptr = base; - for(j=width; j>0; j-=8) { - dcbst(ptr); - ptr += 8; - } - base += (bi->dispDeviceRowBytes >> 2); - } -} -#endif - - -#ifndef NO_SCROLL -static BTEXT void -scrollscreen(void) -{ - boot_infos_t* bi = &disp_bi; - u32 *src = (u32 *)calc_base(bi,0,16); - u32 *dst = (u32 *)calc_base(bi,0,0); - u32 width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - u32 i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) - { - u32 *src_ptr = src; - u32 *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = *(src_ptr++); - src += (bi->dispDeviceRowBytes >> 2); - dst += (bi->dispDeviceRowBytes >> 2); - } - for (i=0; i<16; i++) - { - u32 *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = 0; - dst += (bi->dispDeviceRowBytes >> 2); - } -} -#endif /* ndef NO_SCROLL */ - -static void BTEXT btext_drawchar(char c) -{ - u32 cline = 0; - - if (!boot_text_mapped) - return; - - switch (c) { - case '\b': - if (g_loc_X > 0) - --g_loc_X; - break; - case '\t': - g_loc_X = (g_loc_X & -8) + 8; - break; - case '\r': - g_loc_X = 0; - break; - case '\n': - g_loc_X = 0; - g_loc_Y++; - cline = 1; - break; - default: - draw_byte(c, g_loc_X++, g_loc_Y); - } - if (g_loc_X >= g_max_loc_X) { - g_loc_X = 0; - g_loc_Y++; - cline = 1; - } -#ifndef NO_SCROLL - while (g_loc_Y >= g_max_loc_Y) { - scrollscreen(); - g_loc_Y--; - } -#else - /* wrap around from bottom to top of screen so we don't - waste time scrolling each line. -- paulus. */ - if (g_loc_Y >= g_max_loc_Y) - g_loc_Y = 0; - if (cline) { - for (x = 0; x < g_max_loc_X; ++x) - draw_byte(' ', x, g_loc_Y); - } -#endif -} -#if 0 -static void BTEXT -btext_drawstring(const char *c) -{ - if (!boot_text_mapped) - return; - while (*c) - btext_drawchar(*c++); -} -static void BTEXT -btext_drawhex(u32 v) -{ - static char hex_table[] = "0123456789abcdef"; - - if (!boot_text_mapped) - return; - btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); - btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); - btext_drawchar(' '); -} -#endif - -static void BTEXT -draw_byte(const unsigned char c, u32 locX, u32 locY) -{ - boot_infos_t* bi = &disp_bi; - unsigned char *base = calc_base(bi, locX << 3, locY << 4); -#if CHAR_256==1 - unsigned const char *font = &vga_font[(((u32)c)) * 16]; -#else - unsigned const char *font = &vga_font[(((u32)c-0x20)) * 16]; -#endif - - u32 rb = bi->dispDeviceRowBytes; - - switch(bi->dispDeviceDepth) { -#if 0 - case 24: - case 32: - draw_byte_32(font, (u32 *)base, rb); - break; - case 15: - case 16: - draw_byte_16(font, (u32 *)base, rb); - break; -#endif - case 8: - draw_byte_8(font, (u32 *)base, rb); - break; - } -} -static u32 expand_bits_8[16] BTDATA = { -#if defined(__BIG_ENDIAN) - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -#elif defined(__LITTLE_ENDIAN) - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -#else -#error FIXME: No endianness?? -#endif -}; -#if 0 -static const u32 expand_bits_16[4] BTDATA = { -#if defined(__BIG_ENDIAN) - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -#elif defined(__LITTLE_ENDIAN) - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -#else -#error FIXME: No endianness?? -#endif -}; -#endif -#if 0 -static void BTEXT -draw_byte_32(const unsigned char *font, u32 *base, u32 rb) -{ - u32 l, bits; - u32 fg = 0xFFFFFFFF; - u32 bg = 0x00000000; - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (-(bits >> 7) & fg) ^ bg; - base[1] = (-((bits >> 6) & 1) & fg) ^ bg; - base[2] = (-((bits >> 5) & 1) & fg) ^ bg; - base[3] = (-((bits >> 4) & 1) & fg) ^ bg; - base[4] = (-((bits >> 3) & 1) & fg) ^ bg; - base[5] = (-((bits >> 2) & 1) & fg) ^ bg; - base[6] = (-((bits >> 1) & 1) & fg) ^ bg; - base[7] = (-(bits & 1) & fg) ^ bg; - base = (u32 *) ((char *)base + rb); - } -} - -static void BTEXT -draw_byte_16(const unsigned char *font, u32 *base, u32 rb) -{ - u32 l, bits; - u32 fg = 0xFFFFFFFF; - u32 bg = 0x00000000; - u32 *eb = expand_bits_16; - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 6] & fg) ^ bg; - base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; - base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; - base[3] = (eb[bits & 3] & fg) ^ bg; - base = (u32 *) ((char *)base + rb); - } -} -#endif -static void BTEXT -draw_byte_8(const unsigned char *font, u32 *base, u32 rb) -{ - u32 l, bits; - u32 fg = 0x0F0F0F0F; - u32 bg = 0x00000000; - u32 *eb = expand_bits_8; - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 4] & fg) ^ bg; - base[1] = (eb[bits & 0xf] & fg) ^ bg; - base = (u32 *) ((char *)base + rb); - } -} - -static void btext_init(void) -{ -#if 0 -// for debug -#define frame_buffer 0xfc000000 -#else - uint32_t frame_buffer;// 0xfc000000 - - struct pci_device dev; - - #warning "pci_find_device_x no longer exists; use find_pci_device instead" - /* pci_find_device_x(0x1002, 0x4752, 0, &dev); */ - if(dev.vendor==0) return; // no fb - - frame_buffer = (uint32_t)dev.membase; -#endif - - btext_setup_display(640, 480, 8, 640,frame_buffer); - btext_clearscreen(); - map_boot_text(); -} -static void btext_putc(int c) -{ - btext_drawchar((unsigned char)c); -} - -struct console_driver btext_console __console_driver = { - .putchar = btext_putc, - .disabled = 1, -}; - -//come from linux/drivers/video/font-8x16.c -/**********************************************/ -/* */ -/* Font file generated by cpi2fnt */ -/* */ -/**********************************************/ - - -static const unsigned char vga_font[cmapsz] BTDATA = { -#if CHAR_256==1 - /* 0 0x00 '^@' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 1 0x01 '^A' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x81, /* 10000001 */ - 0xa5, /* 10100101 */ - 0x81, /* 10000001 */ - 0x81, /* 10000001 */ - 0xbd, /* 10111101 */ - 0x99, /* 10011001 */ - 0x81, /* 10000001 */ - 0x81, /* 10000001 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 2 0x02 '^B' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0xff, /* 11111111 */ - 0xdb, /* 11011011 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xc3, /* 11000011 */ - 0xe7, /* 11100111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 3 0x03 '^C' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x6c, /* 01101100 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0x7c, /* 01111100 */ - 0x38, /* 00111000 */ - 0x10, /* 00010000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 4 0x04 '^D' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x7c, /* 01111100 */ - 0xfe, /* 11111110 */ - 0x7c, /* 01111100 */ - 0x38, /* 00111000 */ - 0x10, /* 00010000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 5 0x05 '^E' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0xe7, /* 11100111 */ - 0xe7, /* 11100111 */ - 0xe7, /* 11100111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 6 0x06 '^F' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x7e, /* 01111110 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 7 0x07 '^G' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 8 0x08 '^H' */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xe7, /* 11100111 */ - 0xc3, /* 11000011 */ - 0xc3, /* 11000011 */ - 0xe7, /* 11100111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - - /* 9 0x09 '^I' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x42, /* 01000010 */ - 0x42, /* 01000010 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 10 0x0a '^J' */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xc3, /* 11000011 */ - 0x99, /* 10011001 */ - 0xbd, /* 10111101 */ - 0xbd, /* 10111101 */ - 0x99, /* 10011001 */ - 0xc3, /* 11000011 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - - /* 11 0x0b '^K' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1e, /* 00011110 */ - 0x0e, /* 00001110 */ - 0x1a, /* 00011010 */ - 0x32, /* 00110010 */ - 0x78, /* 01111000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 12 0x0c '^L' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 13 0x0d '^M' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3f, /* 00111111 */ - 0x33, /* 00110011 */ - 0x3f, /* 00111111 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x70, /* 01110000 */ - 0xf0, /* 11110000 */ - 0xe0, /* 11100000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 14 0x0e '^N' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7f, /* 01111111 */ - 0x63, /* 01100011 */ - 0x7f, /* 01111111 */ - 0x63, /* 01100011 */ - 0x63, /* 01100011 */ - 0x63, /* 01100011 */ - 0x63, /* 01100011 */ - 0x67, /* 01100111 */ - 0xe7, /* 11100111 */ - 0xe6, /* 11100110 */ - 0xc0, /* 11000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 15 0x0f '^O' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xdb, /* 11011011 */ - 0x3c, /* 00111100 */ - 0xe7, /* 11100111 */ - 0x3c, /* 00111100 */ - 0xdb, /* 11011011 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 16 0x10 '^P' */ - 0x00, /* 00000000 */ - 0x80, /* 10000000 */ - 0xc0, /* 11000000 */ - 0xe0, /* 11100000 */ - 0xf0, /* 11110000 */ - 0xf8, /* 11111000 */ - 0xfe, /* 11111110 */ - 0xf8, /* 11111000 */ - 0xf0, /* 11110000 */ - 0xe0, /* 11100000 */ - 0xc0, /* 11000000 */ - 0x80, /* 10000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 17 0x11 '^Q' */ - 0x00, /* 00000000 */ - 0x02, /* 00000010 */ - 0x06, /* 00000110 */ - 0x0e, /* 00001110 */ - 0x1e, /* 00011110 */ - 0x3e, /* 00111110 */ - 0xfe, /* 11111110 */ - 0x3e, /* 00111110 */ - 0x1e, /* 00011110 */ - 0x0e, /* 00001110 */ - 0x06, /* 00000110 */ - 0x02, /* 00000010 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 18 0x12 '^R' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 19 0x13 '^S' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 20 0x14 '^T' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7f, /* 01111111 */ - 0xdb, /* 11011011 */ - 0xdb, /* 11011011 */ - 0xdb, /* 11011011 */ - 0x7b, /* 01111011 */ - 0x1b, /* 00011011 */ - 0x1b, /* 00011011 */ - 0x1b, /* 00011011 */ - 0x1b, /* 00011011 */ - 0x1b, /* 00011011 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 21 0x15 '^U' */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0x60, /* 01100000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x0c, /* 00001100 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 22 0x16 '^V' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 23 0x17 '^W' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 24 0x18 '^X' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 25 0x19 '^Y' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 26 0x1a '^Z' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0xfe, /* 11111110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 27 0x1b '^[' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xfe, /* 11111110 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 28 0x1c '^\' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 29 0x1d '^]' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x28, /* 00101000 */ - 0x6c, /* 01101100 */ - 0xfe, /* 11111110 */ - 0x6c, /* 01101100 */ - 0x28, /* 00101000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 30 0x1e '^^' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x38, /* 00111000 */ - 0x7c, /* 01111100 */ - 0x7c, /* 01111100 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 31 0x1f '^_' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0x7c, /* 01111100 */ - 0x7c, /* 01111100 */ - 0x38, /* 00111000 */ - 0x38, /* 00111000 */ - 0x10, /* 00010000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ -#endif - /* 32 0x20 ' ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 33 0x21 '!' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 34 0x22 '"' */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x24, /* 00100100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 35 0x23 '#' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0xfe, /* 11111110 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0xfe, /* 11111110 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 36 0x24 '$' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc2, /* 11000010 */ - 0xc0, /* 11000000 */ - 0x7c, /* 01111100 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x86, /* 10000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 37 0x25 '%' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc2, /* 11000010 */ - 0xc6, /* 11000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc6, /* 11000110 */ - 0x86, /* 10000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 38 0x26 '&' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 39 0x27 ''' */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 40 0x28 '(' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 41 0x29 ')' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 42 0x2a '*' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0xff, /* 11111111 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 43 0x2b '+' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 44 0x2c ',' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 45 0x2d '-' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 46 0x2e '.' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 47 0x2f '/' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x02, /* 00000010 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0x80, /* 10000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 48 0x30 '0' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 49 0x31 '1' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x38, /* 00111000 */ - 0x78, /* 01111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 50 0x32 '2' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 51 0x33 '3' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x3c, /* 00111100 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 52 0x34 '4' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0c, /* 00001100 */ - 0x1c, /* 00011100 */ - 0x3c, /* 00111100 */ - 0x6c, /* 01101100 */ - 0xcc, /* 11001100 */ - 0xfe, /* 11111110 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x1e, /* 00011110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 53 0x35 '5' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xfc, /* 11111100 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 54 0x36 '6' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xfc, /* 11111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 55 0x37 '7' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 56 0x38 '8' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 57 0x39 '9' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7e, /* 01111110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 58 0x3a ':' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 59 0x3b ';' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 60 0x3c '<' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x06, /* 00000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 61 0x3d '=' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 62 0x3e '>' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 63 0x3f '?' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 64 0x40 '@' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xde, /* 11011110 */ - 0xde, /* 11011110 */ - 0xde, /* 11011110 */ - 0xdc, /* 11011100 */ - 0xc0, /* 11000000 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 65 0x41 'A' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 66 0x42 'B' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfc, /* 11111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0xfc, /* 11111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 67 0x43 'C' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0xc2, /* 11000010 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc2, /* 11000010 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 68 0x44 'D' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xf8, /* 11111000 */ - 0x6c, /* 01101100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x6c, /* 01101100 */ - 0xf8, /* 11111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 69 0x45 'E' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x66, /* 01100110 */ - 0x62, /* 01100010 */ - 0x68, /* 01101000 */ - 0x78, /* 01111000 */ - 0x68, /* 01101000 */ - 0x60, /* 01100000 */ - 0x62, /* 01100010 */ - 0x66, /* 01100110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 70 0x46 'F' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x66, /* 01100110 */ - 0x62, /* 01100010 */ - 0x68, /* 01101000 */ - 0x78, /* 01111000 */ - 0x68, /* 01101000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xf0, /* 11110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 71 0x47 'G' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0xc2, /* 11000010 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xde, /* 11011110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x66, /* 01100110 */ - 0x3a, /* 00111010 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 72 0x48 'H' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 73 0x49 'I' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 74 0x4a 'J' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1e, /* 00011110 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 75 0x4b 'K' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xe6, /* 11100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x6c, /* 01101100 */ - 0x78, /* 01111000 */ - 0x78, /* 01111000 */ - 0x6c, /* 01101100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0xe6, /* 11100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 76 0x4c 'L' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xf0, /* 11110000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x62, /* 01100010 */ - 0x66, /* 01100110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 77 0x4d 'M' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xee, /* 11101110 */ - 0xfe, /* 11111110 */ - 0xfe, /* 11111110 */ - 0xd6, /* 11010110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 78 0x4e 'N' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xe6, /* 11100110 */ - 0xf6, /* 11110110 */ - 0xfe, /* 11111110 */ - 0xde, /* 11011110 */ - 0xce, /* 11001110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 79 0x4f 'O' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 80 0x50 'P' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfc, /* 11111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xf0, /* 11110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 81 0x51 'Q' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xd6, /* 11010110 */ - 0xde, /* 11011110 */ - 0x7c, /* 01111100 */ - 0x0c, /* 00001100 */ - 0x0e, /* 00001110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 82 0x52 'R' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfc, /* 11111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x6c, /* 01101100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0xe6, /* 11100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 83 0x53 'S' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x60, /* 01100000 */ - 0x38, /* 00111000 */ - 0x0c, /* 00001100 */ - 0x06, /* 00000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 84 0x54 'T' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x5a, /* 01011010 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 85 0x55 'U' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 86 0x56 'V' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x10, /* 00010000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 87 0x57 'W' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xfe, /* 11111110 */ - 0xee, /* 11101110 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 88 0x58 'X' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x7c, /* 01111100 */ - 0x38, /* 00111000 */ - 0x38, /* 00111000 */ - 0x7c, /* 01111100 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 89 0x59 'Y' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 90 0x5a 'Z' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0x86, /* 10000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc2, /* 11000010 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 91 0x5b '[' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 92 0x5c '\' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x80, /* 10000000 */ - 0xc0, /* 11000000 */ - 0xe0, /* 11100000 */ - 0x70, /* 01110000 */ - 0x38, /* 00111000 */ - 0x1c, /* 00011100 */ - 0x0e, /* 00001110 */ - 0x06, /* 00000110 */ - 0x02, /* 00000010 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 93 0x5d ']' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 94 0x5e '^' */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 95 0x5f '_' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 96 0x60 '`' */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 97 0x61 'a' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 98 0x62 'b' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xe0, /* 11100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x78, /* 01111000 */ - 0x6c, /* 01101100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 99 0x63 'c' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 100 0x64 'd' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1c, /* 00011100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x3c, /* 00111100 */ - 0x6c, /* 01101100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 101 0x65 'e' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 102 0x66 'f' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1c, /* 00011100 */ - 0x36, /* 00110110 */ - 0x32, /* 00110010 */ - 0x30, /* 00110000 */ - 0x78, /* 01111000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 103 0x67 'g' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x7c, /* 01111100 */ - 0x0c, /* 00001100 */ - 0xcc, /* 11001100 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - - /* 104 0x68 'h' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xe0, /* 11100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x6c, /* 01101100 */ - 0x76, /* 01110110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0xe6, /* 11100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 105 0x69 'i' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 106 0x6a 'j' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x00, /* 00000000 */ - 0x0e, /* 00001110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - - /* 107 0x6b 'k' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xe0, /* 11100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x66, /* 01100110 */ - 0x6c, /* 01101100 */ - 0x78, /* 01111000 */ - 0x78, /* 01111000 */ - 0x6c, /* 01101100 */ - 0x66, /* 01100110 */ - 0xe6, /* 11100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 108 0x6c 'l' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 109 0x6d 'm' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xec, /* 11101100 */ - 0xfe, /* 11111110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 110 0x6e 'n' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xdc, /* 11011100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 111 0x6f 'o' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 112 0x70 'p' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xdc, /* 11011100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xf0, /* 11110000 */ - 0x00, /* 00000000 */ - - /* 113 0x71 'q' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x7c, /* 01111100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x1e, /* 00011110 */ - 0x00, /* 00000000 */ - - /* 114 0x72 'r' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xdc, /* 11011100 */ - 0x76, /* 01110110 */ - 0x66, /* 01100110 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xf0, /* 11110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 115 0x73 's' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0x60, /* 01100000 */ - 0x38, /* 00111000 */ - 0x0c, /* 00001100 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 116 0x74 't' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0xfc, /* 11111100 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x36, /* 00110110 */ - 0x1c, /* 00011100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 117 0x75 'u' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 118 0x76 'v' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 119 0x77 'w' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xd6, /* 11010110 */ - 0xfe, /* 11111110 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 120 0x78 'x' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x38, /* 00111000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 121 0x79 'y' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7e, /* 01111110 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0xf8, /* 11111000 */ - 0x00, /* 00000000 */ - - /* 122 0x7a 'z' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xcc, /* 11001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 123 0x7b '{' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0e, /* 00001110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x70, /* 01110000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x0e, /* 00001110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 124 0x7c '|' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 125 0x7d '}' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x70, /* 01110000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x0e, /* 00001110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 126 0x7e '~' */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 127 0x7f '' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ -#if CHAR_256256==1 - /* 128 0x80 '€' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0xc2, /* 11000010 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc2, /* 11000010 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 129 0x81 '' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 130 0x82 '‚' */ - 0x00, /* 00000000 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 131 0x83 'ƒ' */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 132 0x84 '„' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 133 0x85 '…' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 134 0x86 '†' */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 135 0x87 '‡' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x18, /* 00011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 136 0x88 'ˆ' */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 137 0x89 '‰' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 138 0x8a 'Š' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 139 0x8b '‹' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 140 0x8c 'Œ' */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 141 0x8d '' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 142 0x8e 'Ž' */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 143 0x8f '' */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 144 0x90 '' */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x66, /* 01100110 */ - 0x62, /* 01100010 */ - 0x68, /* 01101000 */ - 0x78, /* 01111000 */ - 0x68, /* 01101000 */ - 0x62, /* 01100010 */ - 0x66, /* 01100110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 145 0x91 '‘' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xec, /* 11101100 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x7e, /* 01111110 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0x6e, /* 01101110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 146 0x92 '’' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3e, /* 00111110 */ - 0x6c, /* 01101100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xfe, /* 11111110 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xce, /* 11001110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 147 0x93 '“' */ - 0x00, /* 00000000 */ - 0x10, /* 00010000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 148 0x94 '”' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 149 0x95 '•' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 150 0x96 '–' */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x78, /* 01111000 */ - 0xcc, /* 11001100 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 151 0x97 '—' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 152 0x98 '˜' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7e, /* 01111110 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x78, /* 01111000 */ - 0x00, /* 00000000 */ - - /* 153 0x99 '™' */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 154 0x9a 'š' */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 155 0x9b '›' */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 156 0x9c 'œ' */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x64, /* 01100100 */ - 0x60, /* 01100000 */ - 0xf0, /* 11110000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xe6, /* 11100110 */ - 0xfc, /* 11111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 157 0x9d '' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 158 0x9e 'ž' */ - 0x00, /* 00000000 */ - 0xf8, /* 11111000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xf8, /* 11111000 */ - 0xc4, /* 11000100 */ - 0xcc, /* 11001100 */ - 0xde, /* 11011110 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 159 0x9f 'Ÿ' */ - 0x00, /* 00000000 */ - 0x0e, /* 00001110 */ - 0x1b, /* 00011011 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xd8, /* 11011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 160 0xa0 ' ' */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0x0c, /* 00001100 */ - 0x7c, /* 01111100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 161 0xa1 '¡' */ - 0x00, /* 00000000 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 162 0xa2 '¢' */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 163 0xa3 '£' */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x00, /* 00000000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 164 0xa4 '¤' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x00, /* 00000000 */ - 0xdc, /* 11011100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 165 0xa5 '¥' */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x00, /* 00000000 */ - 0xc6, /* 11000110 */ - 0xe6, /* 11100110 */ - 0xf6, /* 11110110 */ - 0xfe, /* 11111110 */ - 0xde, /* 11011110 */ - 0xce, /* 11001110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 166 0xa6 '¦' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x3e, /* 00111110 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 167 0xa7 '§' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 168 0xa8 '¨' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x7c, /* 01111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 169 0xa9 '©' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 170 0xaa 'ª' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 171 0xab '«' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0xe0, /* 11100000 */ - 0x62, /* 01100010 */ - 0x66, /* 01100110 */ - 0x6c, /* 01101100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xdc, /* 11011100 */ - 0x86, /* 10000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x3e, /* 00111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 172 0xac '¬' */ - 0x00, /* 00000000 */ - 0x60, /* 01100000 */ - 0xe0, /* 11100000 */ - 0x62, /* 01100010 */ - 0x66, /* 01100110 */ - 0x6c, /* 01101100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x66, /* 01100110 */ - 0xce, /* 11001110 */ - 0x9a, /* 10011010 */ - 0x3f, /* 00111111 */ - 0x06, /* 00000110 */ - 0x06, /* 00000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 173 0xad '­' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 174 0xae '®' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x36, /* 00110110 */ - 0x6c, /* 01101100 */ - 0xd8, /* 11011000 */ - 0x6c, /* 01101100 */ - 0x36, /* 00110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 175 0xaf '¯' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xd8, /* 11011000 */ - 0x6c, /* 01101100 */ - 0x36, /* 00110110 */ - 0x6c, /* 01101100 */ - 0xd8, /* 11011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 176 0xb0 '°' */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - 0x11, /* 00010001 */ - 0x44, /* 01000100 */ - - /* 177 0xb1 '±' */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - 0x55, /* 01010101 */ - 0xaa, /* 10101010 */ - - /* 178 0xb2 '²' */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - 0xdd, /* 11011101 */ - 0x77, /* 01110111 */ - - /* 179 0xb3 '³' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 180 0xb4 '´' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 181 0xb5 'µ' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 182 0xb6 '¶' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xf6, /* 11110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 183 0xb7 '·' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 184 0xb8 '¸' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 185 0xb9 '¹' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xf6, /* 11110110 */ - 0x06, /* 00000110 */ - 0xf6, /* 11110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 186 0xba 'º' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 187 0xbb '»' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x06, /* 00000110 */ - 0xf6, /* 11110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 188 0xbc '¼' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xf6, /* 11110110 */ - 0x06, /* 00000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 189 0xbd '½' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 190 0xbe '¾' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 191 0xbf '¿' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xf8, /* 11111000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 192 0xc0 'À' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 193 0xc1 'Á' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 194 0xc2 'Â' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 195 0xc3 'Ã' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 196 0xc4 'Ä' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 197 0xc5 'Å' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xff, /* 11111111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 198 0xc6 'Æ' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 199 0xc7 'Ç' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x37, /* 00110111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 200 0xc8 'È' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x37, /* 00110111 */ - 0x30, /* 00110000 */ - 0x3f, /* 00111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 201 0xc9 'É' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3f, /* 00111111 */ - 0x30, /* 00110000 */ - 0x37, /* 00110111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 202 0xca 'Ê' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xf7, /* 11110111 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 203 0xcb 'Ë' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0xf7, /* 11110111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 204 0xcc 'Ì' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x37, /* 00110111 */ - 0x30, /* 00110000 */ - 0x37, /* 00110111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 205 0xcd 'Í' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 206 0xce 'Î' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xf7, /* 11110111 */ - 0x00, /* 00000000 */ - 0xf7, /* 11110111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 207 0xcf 'Ï' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 208 0xd0 'Ð' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 209 0xd1 'Ñ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 210 0xd2 'Ò' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 211 0xd3 'Ó' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x3f, /* 00111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 212 0xd4 'Ô' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 213 0xd5 'Õ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 214 0xd6 'Ö' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3f, /* 00111111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 215 0xd7 '×' */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0xff, /* 11111111 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - - /* 216 0xd8 'Ø' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xff, /* 11111111 */ - 0x18, /* 00011000 */ - 0xff, /* 11111111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 217 0xd9 'Ù' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xf8, /* 11111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 218 0xda 'Ú' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1f, /* 00011111 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 219 0xdb 'Û' */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - - /* 220 0xdc 'Ü' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - - /* 221 0xdd 'Ý' */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - 0xf0, /* 11110000 */ - - /* 222 0xde 'Þ' */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - 0x0f, /* 00001111 */ - - /* 223 0xdf 'ß' */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0xff, /* 11111111 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 224 0xe0 'à' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xdc, /* 11011100 */ - 0x76, /* 01110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 225 0xe1 'á' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x78, /* 01111000 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xcc, /* 11001100 */ - 0xd8, /* 11011000 */ - 0xcc, /* 11001100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xcc, /* 11001100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 226 0xe2 'â' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0xc0, /* 11000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 227 0xe3 'ã' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 228 0xe4 'ä' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 229 0xe5 'å' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 230 0xe6 'æ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x7c, /* 01111100 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0x00, /* 00000000 */ - - /* 231 0xe7 'ç' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 232 0xe8 'è' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 233 0xe9 'é' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xfe, /* 11111110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 234 0xea 'ê' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0xee, /* 11101110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 235 0xeb 'ë' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1e, /* 00011110 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x3e, /* 00111110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x66, /* 01100110 */ - 0x3c, /* 00111100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 236 0xec 'ì' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0xdb, /* 11011011 */ - 0xdb, /* 11011011 */ - 0xdb, /* 11011011 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 237 0xed 'í' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x03, /* 00000011 */ - 0x06, /* 00000110 */ - 0x7e, /* 01111110 */ - 0xdb, /* 11011011 */ - 0xdb, /* 11011011 */ - 0xf3, /* 11110011 */ - 0x7e, /* 01111110 */ - 0x60, /* 01100000 */ - 0xc0, /* 11000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 238 0xee 'î' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x1c, /* 00011100 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x7c, /* 01111100 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x1c, /* 00011100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 239 0xef 'ï' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 01111100 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0xc6, /* 11000110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 240 0xf0 'ð' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0xfe, /* 11111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 241 0xf1 'ñ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x7e, /* 01111110 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 242 0xf2 'ò' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x06, /* 00000110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 243 0xf3 'ó' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x30, /* 00110000 */ - 0x60, /* 01100000 */ - 0x30, /* 00110000 */ - 0x18, /* 00011000 */ - 0x0c, /* 00001100 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 244 0xf4 'ô' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0e, /* 00001110 */ - 0x1b, /* 00011011 */ - 0x1b, /* 00011011 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - - /* 245 0xf5 'õ' */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0xd8, /* 11011000 */ - 0x70, /* 01110000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 246 0xf6 'ö' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 247 0xf7 '÷' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x00, /* 00000000 */ - 0x76, /* 01110110 */ - 0xdc, /* 11011100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 248 0xf8 'ø' */ - 0x00, /* 00000000 */ - 0x38, /* 00111000 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x38, /* 00111000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 249 0xf9 'ù' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 250 0xfa 'ú' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 00011000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 251 0xfb 'û' */ - 0x00, /* 00000000 */ - 0x0f, /* 00001111 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0x0c, /* 00001100 */ - 0xec, /* 11101100 */ - 0x6c, /* 01101100 */ - 0x6c, /* 01101100 */ - 0x3c, /* 00111100 */ - 0x1c, /* 00011100 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 252 0xfc 'ü' */ - 0x00, /* 00000000 */ - 0x6c, /* 01101100 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x36, /* 00110110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 253 0xfd 'ý' */ - 0x00, /* 00000000 */ - 0x3c, /* 00111100 */ - 0x66, /* 01100110 */ - 0x0c, /* 00001100 */ - 0x18, /* 00011000 */ - 0x32, /* 00110010 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 254 0xfe 'þ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x7e, /* 01111110 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 255 0xff 'ÿ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ -#endif -}; - -#endif diff --git a/roms/ipxe/src/core/console.c b/roms/ipxe/src/core/console.c index f27edf468..a26a3ef63 100644 --- a/roms/ipxe/src/core/console.c +++ b/roms/ipxe/src/core/console.c @@ -7,6 +7,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); +/** Current console usage */ +int console_usage = CONSOLE_USAGE_STDOUT; + /** * Write a single character to each console device. * @@ -26,7 +29,9 @@ void putchar ( int character ) { putchar ( '\r' ); for_each_table_entry ( console, CONSOLES ) { - if ( ( ! console->disabled ) && console->putchar ) + if ( ( ! console->disabled ) && + ( console_usage & console->usage ) && + console->putchar ) console->putchar ( character ); } } diff --git a/roms/ipxe/src/core/cpio.c b/roms/ipxe/src/core/cpio.c index 5b7b3aa1d..3a5f4d2b6 100644 --- a/roms/ipxe/src/core/cpio.c +++ b/roms/ipxe/src/core/cpio.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/ctype.c b/roms/ipxe/src/core/ctype.c index 6185bb2fa..c812346a0 100644 --- a/roms/ipxe/src/core/ctype.c +++ b/roms/ipxe/src/core/ctype.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/cwuri.c b/roms/ipxe/src/core/cwuri.c index 893e2050b..5865552a0 100644 --- a/roms/ipxe/src/core/cwuri.c +++ b/roms/ipxe/src/core/cwuri.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/debug.c b/roms/ipxe/src/core/debug.c index 73e74d9c3..627d5d9a1 100644 --- a/roms/ipxe/src/core/debug.c +++ b/roms/ipxe/src/core/debug.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -21,17 +22,38 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include +/** + * 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 ) { - printf ( "\nPress a key..." ); + dbg_printf ( "\nPress a key..." ); getchar(); - printf ( "\r \r" ); + dbg_printf ( "\r \r" ); } /** @@ -39,9 +61,9 @@ void dbg_pause ( void ) { * */ void dbg_more ( void ) { - printf ( "---more---" ); + dbg_printf ( "---more---" ); getchar(); - printf ( "\r \r" ); + dbg_printf ( "\r \r" ); } /** @@ -58,27 +80,27 @@ static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data, unsigned int i; uint8_t byte; - printf ( "%08lx :", ( dispaddr + offset ) ); + dbg_printf ( "%08lx :", ( dispaddr + offset ) ); for ( i = offset ; i < ( offset + 16 ) ; i++ ) { if ( i >= len ) { - printf ( " " ); + dbg_printf ( " " ); continue; } - printf ( "%c%02x", - ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] ); + dbg_printf ( "%c%02x", + ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] ); } - printf ( " : " ); + dbg_printf ( " : " ); for ( i = offset ; i < ( offset + 16 ) ; i++ ) { if ( i >= len ) { - printf ( " " ); + dbg_printf ( " " ); continue; } byte = bytes[i]; if ( ( byte < 0x20 ) || ( byte >= 0x7f ) ) byte = '.'; - printf ( "%c", byte ); + dbg_printf ( "%c", byte ); } - printf ( "\n" ); + dbg_printf ( "\n" ); } /** @@ -158,8 +180,8 @@ static int dbg_autocolour ( unsigned long stream ) { * @v stream Message stream ID */ void dbg_autocolourise ( unsigned long stream ) { - printf ( "\033[%dm", - ( stream ? ( 31 + dbg_autocolour ( stream ) ) : 0 ) ); + dbg_printf ( "\033[%dm", + ( stream ? ( 31 + dbg_autocolour ( stream ) ) : 0 ) ); } /** @@ -167,5 +189,5 @@ void dbg_autocolourise ( unsigned long stream ) { * */ void dbg_decolourise ( void ) { - printf ( "\033[0m" ); + dbg_printf ( "\033[0m" ); } diff --git a/roms/ipxe/src/core/debug_md5.c b/roms/ipxe/src/core/debug_md5.c index 6214f6117..f049ac757 100644 --- a/roms/ipxe/src/core/debug_md5.c +++ b/roms/ipxe/src/core/debug_md5.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/device.c b/roms/ipxe/src/core/device.c index dc182e032..330f95c5a 100644 --- a/roms/ipxe/src/core/device.c +++ b/roms/ipxe/src/core/device.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/downloader.c b/roms/ipxe/src/core/downloader.c index 4dc0aa02a..4f3fc2c81 100644 --- a/roms/ipxe/src/core/downloader.c +++ b/roms/ipxe/src/core/downloader.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -21,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -73,6 +75,15 @@ static void downloader_free ( struct refcnt *refcnt ) { */ 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 ); @@ -101,7 +112,7 @@ static int downloader_ensure_size ( struct downloader *downloader, if ( ! new_buffer ) { DBGC ( downloader, "Downloader %p could not extend buffer to " "%zd bytes\n", downloader, len ); - return -ENOBUFS; + return -ENOSPC; } downloader->image->data = new_buffer; downloader->image->len = len; @@ -173,6 +184,8 @@ static int downloader_xfer_deliver ( struct downloader *downloader, done: free_iob ( iobuf ); + if ( rc != 0 ) + downloader_finished ( downloader, rc ); return rc; } diff --git a/roms/ipxe/src/core/edd.c b/roms/ipxe/src/core/edd.c index 8ba24b17f..d574ea6c0 100644 --- a/roms/ipxe/src/core/edd.c +++ b/roms/ipxe/src/core/edd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/exec.c b/roms/ipxe/src/core/exec.c index 18d3477ec..843a51db7 100644 --- a/roms/ipxe/src/core/exec.c +++ b/roms/ipxe/src/core/exec.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -31,6 +32,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include +#include +#include #include /** @file @@ -55,18 +60,22 @@ static int stop_state; int execv ( const char *command, char * const argv[] ) { struct command *cmd; int argc; + int rc; /* Count number of arguments */ for ( argc = 0 ; argv[argc] ; argc++ ) {} /* An empty command is deemed to do nothing, successfully */ - if ( command == NULL ) - return 0; + if ( command == NULL ) { + rc = 0; + goto done; + } /* Sanity checks */ if ( argc == 0 ) { DBG ( "%s: empty argument list\n", command ); - return -EINVAL; + rc = -EINVAL; + goto done; } /* Reset getopt() library ready for use by the command. This @@ -78,12 +87,24 @@ int execv ( const char *command, char * const argv[] ) { /* Hand off to command implementation */ for_each_table_entry ( cmd, COMMANDS ) { - if ( strcmp ( command, cmd->name ) == 0 ) - return cmd->exec ( argc, ( char ** ) argv ); + if ( strcmp ( command, cmd->name ) == 0 ) { + rc = cmd->exec ( argc, ( char ** ) argv ); + goto done; + } } printf ( "%s: command not found\n", command ); - return -ENOEXEC; + rc = -ENOEXEC; + + done: + /* Store error number, if an error occurred */ + if ( rc ) { + errno = rc; + if ( errno < 0 ) + errno = -errno; + } + + return rc; } /** @@ -354,7 +375,7 @@ char * concat_args ( char **args ) { ptr = string; for ( arg = args ; *arg ; arg++ ) { ptr += sprintf ( ptr, "%s%s", - ( ( ptr == string ) ? "" : " " ), *arg ); + ( ( arg == args ) ? "" : " " ), *arg ); } assert ( ptr < ( string + len ) ); @@ -490,3 +511,91 @@ 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, + " " ); + +/** + * "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, "" ); + +/** + * "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/roms/ipxe/src/core/fnrec.c b/roms/ipxe/src/core/fnrec.c index 05d63aaa8..3453c8b6a 100644 --- a/roms/ipxe/src/core/fnrec.c +++ b/roms/ipxe/src/core/fnrec.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/gdbserial.c b/roms/ipxe/src/core/gdbserial.c index ed217add0..6f78c88bf 100644 --- a/roms/ipxe/src/core/gdbserial.c +++ b/roms/ipxe/src/core/gdbserial.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/gdbstub.c b/roms/ipxe/src/core/gdbstub.c index 34e6a0373..cbe328f9f 100644 --- a/roms/ipxe/src/core/gdbstub.c +++ b/roms/ipxe/src/core/gdbstub.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/gdbudp.c b/roms/ipxe/src/core/gdbudp.c index 9cb6572b7..5977547c8 100644 --- a/roms/ipxe/src/core/gdbudp.c +++ b/roms/ipxe/src/core/gdbudp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/getkey.c b/roms/ipxe/src/core/getkey.c index d692b1bc8..d69cfb44b 100644 --- a/roms/ipxe/src/core/getkey.c +++ b/roms/ipxe/src/core/getkey.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -23,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -45,6 +47,7 @@ static int getchar_timeout ( unsigned long timeout ) { step(); if ( iskey() ) return getchar(); + cpu_nap(); } return -1; diff --git a/roms/ipxe/src/core/getopt.c b/roms/ipxe/src/core/getopt.c index b67da0c13..abc1edd6c 100644 --- a/roms/ipxe/src/core/getopt.c +++ b/roms/ipxe/src/core/getopt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -239,6 +240,11 @@ int getopt_long ( int argc, char * const argv[], const char *optstring, /* 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 ) ) diff --git a/roms/ipxe/src/core/hw.c b/roms/ipxe/src/core/hw.c index aca558099..91736a652 100644 --- a/roms/ipxe/src/core/hw.c +++ b/roms/ipxe/src/core/hw.c @@ -26,15 +26,7 @@ static void hw_finished ( struct hw *hw, int rc ) { process_del ( &hw->process ); } -static struct interface_operation hw_xfer_operations[] = { - INTF_OP ( intf_close, struct hw *, hw_finished ), -}; - -static struct interface_descriptor hw_xfer_desc = - INTF_DESC ( struct hw, xfer, hw_xfer_operations ); - -static void hw_step ( struct process *process ) { - struct hw *hw = container_of ( process, struct hw, process ); +static void hw_step ( struct hw *hw ) { int rc; if ( xfer_window ( &hw->xfer ) ) { @@ -43,6 +35,17 @@ static void hw_step ( struct process *process ) { } } +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; @@ -52,7 +55,7 @@ static int hw_open ( struct interface *xfer, struct uri *uri __unused ) { return -ENOMEM; ref_init ( &hw->refcnt, NULL ); intf_init ( &hw->xfer, &hw_xfer_desc, &hw->refcnt ); - process_init ( &hw->process, hw_step, &hw->refcnt ); + process_init ( &hw->process, &hw_process_desc, &hw->refcnt ); /* Attach parent interface, mortalise self, and return */ intf_plug_plug ( &hw->xfer, xfer ); diff --git a/roms/ipxe/src/core/image.c b/roms/ipxe/src/core/image.c index 86c264c26..4101ff3b5 100644 --- a/roms/ipxe/src/core/image.c +++ b/roms/ipxe/src/core/image.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -25,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -36,12 +38,28 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* 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 * @@ -50,48 +68,70 @@ struct image *current_image; 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 ); - DBGC ( image, "IMAGE %s freed\n", image->name ); } /** * Allocate executable image * + * @v uri URI, or NULL * @ret image Executable image */ -struct image * alloc_image ( void ) { +struct image * alloc_image ( struct uri *uri ) { + const char *name; struct image *image; + int rc; + /* Allocate image */ image = zalloc ( sizeof ( *image ) ); - if ( image ) { - ref_init ( &image->refcnt, free_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 URI + * Set image name * * @v image Image - * @v URI New image URI - * - * If no name is set, the name will be updated to the base name of the - * URI path (if any). + * @v name New image name + * @ret rc Return status code */ -void image_set_uri ( struct image *image, struct uri *uri ) { - const char *path = uri->path; +int image_set_name ( struct image *image, const char *name ) { + char *name_copy; - /* Replace URI reference */ - uri_put ( image->uri ); - image->uri = uri_get ( uri ); + /* Duplicate name */ + name_copy = strdup ( name ); + if ( ! name_copy ) + return -ENOMEM; - /* Set name if none already specified */ - if ( path && ( ! image->name[0] ) ) - image_set_name ( image, basename ( ( char * ) path ) ); + /* Replace existing name */ + free ( image->name ); + image->name = name_copy; + + return 0; } /** @@ -121,11 +161,14 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) { */ 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[0] ) { - snprintf ( image->name, sizeof ( image->name ), "img%d", - imgindex++ ); + 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 @@ -152,6 +195,10 @@ int register_image ( struct image *image ) { */ void unregister_image ( struct image *image ) { + /* Do nothing unless image is registered */ + if ( ! ( image->flags & IMAGE_REGISTERED ) ) + return; + DBGC ( image, "IMAGE %s unregistered\n", image->name ); list_del ( &image->list ); image->flags &= ~IMAGE_REGISTERED; @@ -217,17 +264,13 @@ int image_probe ( struct image *image ) { */ int image_exec ( struct image *image ) { struct image *saved_current_image; - struct image *replacement; + struct image *replacement = NULL; struct uri *old_cwuri; int rc; /* Sanity check */ assert ( image->flags & IMAGE_REGISTERED ); - /* Check that this image can be executed */ - if ( ( rc = image_probe ( image ) ) != 0 ) - return rc; - /* Switch current working directory to be that of the image itself */ old_cwuri = uri_get ( cwuri ); churi ( image->uri ); @@ -241,6 +284,20 @@ int image_exec ( struct image *image ) { */ current_image = image_get ( image ); + /* Check that this image can be selected for execution */ + if ( ( rc = image_select ( image ) ) != 0 ) + goto err; + + /* 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 ); + rc = -EACCES_UNTRUSTED; + goto err; + } + + /* 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", @@ -248,6 +305,15 @@ int image_exec ( struct image *image ) { /* 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 @@ -257,6 +323,19 @@ int image_exec ( struct image *image ) { if ( replacement ) assert ( replacement->flags & IMAGE_REGISTERED ); + err: + /* Unregister image if applicable */ + if ( image->flags & IMAGE_AUTO_UNREGISTER ) + unregister_image ( image ); + + /* Debug message for tail-recursion. Placed here because the + * image_put() may end up freeing the image. + */ + if ( replacement ) { + DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n", + image->name, replacement->name ); + } + /* Drop temporary reference to the original image */ image_put ( image ); @@ -268,12 +347,8 @@ int image_exec ( struct image *image ) { uri_put ( old_cwuri ); /* Tail-recurse into replacement image, if one exists */ - if ( replacement ) { - DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n", - image->name, replacement->name ); - if ( ( rc = image_exec ( replacement ) ) != 0 ) - return rc; - } + if ( replacement ) + return image_exec ( replacement ); return rc; } @@ -302,6 +377,10 @@ int image_replace ( struct image *replacement ) { 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 ); @@ -351,3 +430,27 @@ struct image * image_find_selected ( void ) { } 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/roms/ipxe/src/core/init.c b/roms/ipxe/src/core/init.c index 4dc706f63..562744194 100644 --- a/roms/ipxe/src/core/init.c +++ b/roms/ipxe/src/core/init.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/interface.c b/roms/ipxe/src/core/interface.c index c69875ea6..97caac804 100644 --- a/roms/ipxe/src/core/interface.c +++ b/roms/ipxe/src/core/interface.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/iobuf.c b/roms/ipxe/src/core/iobuf.c index d776d606e..afc91d150 100644 --- a/roms/ipxe/src/core/iobuf.c +++ b/roms/ipxe/src/core/iobuf.c @@ -13,12 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -29,36 +31,81 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/** + * Allocate I/O buffer with specified alignment and offset + * + * @v len Required length of buffer + * @v align Physical alignment + * @v offset Offset from physical alignment + * @ret iobuf I/O buffer, or NULL if none available + * + * @c align will be rounded up to the nearest power of two. + */ +struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) { + struct io_buffer *iobuf; + void *data; + + /* Align buffer length to ensure that struct io_buffer is aligned */ + len = ( len + __alignof__ ( *iobuf ) - 1 ) & + ~( __alignof__ ( *iobuf ) - 1 ); + + /* Round up alignment to the nearest power of two */ + align = ( 1 << fls ( align - 1 ) ); + + /* Allocate buffer plus descriptor as a single unit, unless + * doing so will push the total size over the alignment + * boundary. + */ + if ( ( len + sizeof ( *iobuf ) ) <= align ) { + + /* Allocate memory for buffer plus descriptor */ + data = malloc_dma_offset ( len + sizeof ( *iobuf ), align, + offset ); + if ( ! data ) + return NULL; + iobuf = ( data + len ); + + } else { + + /* Allocate memory for buffer */ + data = malloc_dma_offset ( len, align, offset ); + if ( ! data ) + return NULL; + + /* Allocate memory for descriptor */ + iobuf = malloc ( sizeof ( *iobuf ) ); + if ( ! iobuf ) { + free_dma ( data, len ); + return NULL; + } + } + + /* Populate descriptor */ + iobuf->head = iobuf->data = iobuf->tail = data; + iobuf->end = ( data + len ); + + return iobuf; +} + /** * 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. + * The I/O buffer will be physically aligned on its own size (rounded + * up to the nearest power of two). */ 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; + /* Align buffer on its own size to avoid potential problems + * with boundary-crossing DMA. + */ + return alloc_iob_raw ( len, len, 0 ); } /** @@ -67,12 +114,29 @@ struct io_buffer * alloc_iob ( size_t len ) { * @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 ) ); + size_t len; + + /* Allow free_iob(NULL) to be valid */ + if ( ! iobuf ) + return; + + /* Sanity checks */ + assert ( iobuf->head <= iobuf->data ); + assert ( iobuf->data <= iobuf->tail ); + assert ( iobuf->tail <= iobuf->end ); + + /* Free buffer */ + len = ( iobuf->end - iobuf->head ); + if ( iobuf->end == iobuf ) { + + /* Descriptor is inline */ + free_dma ( iobuf->head, ( len + sizeof ( *iobuf ) ) ); + + } else { + + /* Descriptor is detached */ + free_dma ( iobuf->head, len ); + free ( iobuf ); } } @@ -94,3 +158,45 @@ int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { return -ENOBUFS; } +/** + * Concatenate I/O buffers into a single buffer + * + * @v list List of I/O buffers + * @ret iobuf Concatenated I/O buffer, or NULL on allocation failure + * + * After a successful concatenation, the list will be empty. + */ +struct io_buffer * iob_concatenate ( struct list_head *list ) { + struct io_buffer *iobuf; + struct io_buffer *tmp; + struct io_buffer *concatenated; + size_t len = 0; + + /* If the list contains only a single entry, avoid an + * unnecessary additional allocation. + */ + if ( list_is_singular ( list ) ) { + iobuf = list_first_entry ( list, struct io_buffer, list ); + INIT_LIST_HEAD ( list ); + return iobuf; + } + + /* Calculate total length */ + list_for_each_entry ( iobuf, list, list ) + len += iob_len ( iobuf ); + + /* Allocate new I/O buffer */ + concatenated = alloc_iob_raw ( len, __alignof__ ( *iobuf ), 0 ); + if ( ! concatenated ) + return NULL; + + /* Move data to new I/O buffer */ + list_for_each_entry_safe ( iobuf, tmp, list, list ) { + list_del ( &iobuf->list ); + memcpy ( iob_put ( concatenated, iob_len ( iobuf ) ), + iobuf->data, iob_len ( iobuf ) ); + free_iob ( iobuf ); + } + + return concatenated; +} diff --git a/roms/ipxe/src/core/job.c b/roms/ipxe/src/core/job.c index ac4e43e7b..64d184ec3 100644 --- a/roms/ipxe/src/core/job.c +++ b/roms/ipxe/src/core/job.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/linebuf.c b/roms/ipxe/src/core/linebuf.c index f152bccb0..8fb2f86a7 100644 --- a/roms/ipxe/src/core/linebuf.c +++ b/roms/ipxe/src/core/linebuf.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/lineconsole.c b/roms/ipxe/src/core/lineconsole.c new file mode 100644 index 000000000..1b6791cf3 --- /dev/null +++ b/roms/ipxe/src/core/lineconsole.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Line-based console + * + */ + +#include +#include +#include +#include + +/** + * 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/roms/ipxe/src/core/list.c b/roms/ipxe/src/core/list.c new file mode 100644 index 000000000..77579d69a --- /dev/null +++ b/roms/ipxe/src/core/list.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +/** @file + * + * Linked lists + * + */ + +#include + +void extern_list_add ( struct list_head *new, struct list_head *head ) { + inline_list_add ( new, head ); +} + +void extern_list_add_tail ( struct list_head *new, struct list_head *head ) { + inline_list_add_tail ( new, head ); +} + +void extern_list_del ( struct list_head *list ) { + inline_list_del ( list ); +} + +int extern_list_empty ( const struct list_head *list ) { + return inline_list_empty ( list ); +} + +int extern_list_is_singular ( const struct list_head *list ) { + return inline_list_is_singular ( list ); +} + +int extern_list_is_last ( const struct list_head *list, + const struct list_head *head ) { + return inline_list_is_last ( list, head ); +} + +void extern_list_cut_position ( struct list_head *new, + struct list_head *list, + struct list_head *entry ) { + inline_list_cut_position ( new, list, entry ); +} + +void extern_list_splice ( const struct list_head *list, + struct list_head *entry ) { + inline_list_splice ( list, entry ); +} + +void extern_list_splice_tail ( const struct list_head *list, + struct list_head *entry ) { + inline_list_splice_tail ( list, entry ); +} + +void extern_list_splice_init ( struct list_head *list, + struct list_head *entry ) { + inline_list_splice_init ( list, entry ); +} + +void extern_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ) { + inline_list_splice_tail_init ( list, entry ); +} + +int extern_list_contains ( struct list_head *entry, + struct list_head *head ) { + return inline_list_contains ( entry, head ); +} diff --git a/roms/ipxe/src/core/log.c b/roms/ipxe/src/core/log.c new file mode 100644 index 000000000..f160b4fc8 --- /dev/null +++ b/roms/ipxe/src/core/log.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * System logger + * + */ + +#include +#include +#include + +/** + * 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/roms/ipxe/src/core/main.c b/roms/ipxe/src/core/main.c index 9fd4a76ff..7b7755c94 100644 --- a/roms/ipxe/src/core/main.c +++ b/roms/ipxe/src/core/main.c @@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -48,7 +49,9 @@ static int shell_banner ( void ) { if ( BANNER_TIMEOUT <= 0 ) return 0; - return ( prompt ( "\nPress Ctrl-B for the iPXE command line...", + /* Prompt user */ + printf ( "\n" ); + return ( prompt ( "Press Ctrl-B for the iPXE command line...", ( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 ); } @@ -80,10 +83,10 @@ __asmcall int main ( void ) { * do so. * */ - printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE " VERSION + printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE %s" NORMAL " -- Open Source Network Boot Firmware -- " CYAN "http://ipxe.org" NORMAL "\n" - "Features:" ); + "Features:", product_version ); for_each_table_entry ( feature, FEATURES ) printf ( " %s", feature->name ); printf ( "\n" ); diff --git a/roms/ipxe/src/core/malloc.c b/roms/ipxe/src/core/malloc.c index d694f5559..56ca7edc6 100644 --- a/roms/ipxe/src/core/malloc.c +++ b/roms/ipxe/src/core/malloc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -91,9 +92,9 @@ size_t freemem; /** * Heap size * - * Currently fixed at 128kB. + * Currently fixed at 512kB. */ -#define HEAP_SIZE ( 128 * 1024 ) +#define HEAP_SIZE ( 512 * 1024 ) /** The heap itself */ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); @@ -105,11 +106,36 @@ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); static inline void valgrind_make_blocks_defined ( void ) { struct memory_block *block; - if ( RUNNING_ON_VALGRIND > 0 ) { - VALGRIND_MAKE_MEM_DEFINED ( &free_blocks, - sizeof ( free_blocks ) ); - list_for_each_entry ( block, &free_blocks, list ) - VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *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 ) ); } } @@ -119,14 +145,45 @@ static inline void valgrind_make_blocks_defined ( void ) { */ static inline void valgrind_make_blocks_noaccess ( void ) { struct memory_block *block; - struct memory_block *tmp; + 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 ) { - if ( RUNNING_ON_VALGRIND > 0 ) { - list_for_each_entry_safe ( block, tmp, &free_blocks, list ) - VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) ); - VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, - sizeof ( free_blocks ) ); + /* 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 ) ); } /** @@ -136,12 +193,26 @@ static inline void valgrind_make_blocks_noaccess ( void ) { */ static unsigned int discard_cache ( void ) { struct cache_discarder *discarder; - unsigned int discarded = 0; + unsigned int discarded; for_each_table_entry ( discarder, CACHE_DISCARDERS ) { - discarded += discarder->discard(); + discarded = discarder->discard(); + if ( discarded ) + return discarded; } - return discarded; + return 0; +} + +/** + * Discard all cached data + * + */ +static void discard_all_cache ( void ) { + unsigned int discarded; + + do { + discarded = discard_cache(); + } while ( discarded ); } /** @@ -149,6 +220,7 @@ static unsigned int discard_cache ( void ) { * * @v size Requested size * @v align Physical alignment + * @v offset Offset from physical alignment * @ret ptr Memory block, or NULL * * Allocates a memory block @b physically aligned as requested. No @@ -156,7 +228,7 @@ static unsigned int discard_cache ( void ) { * * @c align must be a power of two. @c size may not be zero. */ -void * alloc_memblock ( size_t size, size_t align ) { +void * alloc_memblock ( size_t size, size_t align, size_t offset ) { struct memory_block *block; size_t align_mask; size_t pre_size; @@ -173,12 +245,13 @@ void * alloc_memblock ( size_t size, size_t align ) { 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 ); + DBG ( "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset ); 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; + pre_size = ( ( offset - 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" @@ -347,7 +420,7 @@ void * realloc ( void *old_ptr, size_t new_size ) { if ( new_size ) { new_total_size = ( new_size + offsetof ( struct autosized_block, data ) ); - new_block = alloc_memblock ( new_total_size, 1 ); + new_block = alloc_memblock ( new_total_size, 1, 0 ); if ( ! new_block ) return NULL; VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) ); @@ -458,6 +531,19 @@ 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 /** diff --git a/roms/ipxe/src/core/memblock.c b/roms/ipxe/src/core/memblock.c new file mode 100644 index 000000000..1fd89b871 --- /dev/null +++ b/roms/ipxe/src/core/memblock.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +/** @file + * + * Largest memory block + * + */ + +#include +#include +#include +#include + +/** + * Find largest usable memory region + * + * @ret start Start of region + * @ret len Length of region + */ +size_t largest_memblock ( userptr_t *start ) { + struct memory_map memmap; + struct memory_region *region; + physaddr_t max = ~( ( physaddr_t ) 0 ); + physaddr_t region_start; + physaddr_t region_end; + size_t region_len; + unsigned int i; + size_t len = 0; + + /* Avoid returning uninitialised data on error */ + *start = UNULL; + + /* Scan through all memory regions */ + get_memmap ( &memmap ); + for ( i = 0 ; i < memmap.count ; i++ ) { + region = &memmap.regions[i]; + DBG ( "Considering [%llx,%llx)\n", region->start, region->end ); + + /* Truncate block to maximum physical address */ + if ( region->start > max ) { + DBG ( "...starts after maximum address %lx\n", max ); + continue; + } + region_start = region->start; + if ( region->end > max ) { + DBG ( "...end truncated to maximum address %lx\n", max); + region_end = 0; /* =max, given the wraparound */ + } else { + region_end = region->end; + } + region_len = ( region_end - region_start ); + + /* Use largest block */ + if ( region_len > len ) { + DBG ( "...new best block found\n" ); + *start = phys_to_user ( region_start ); + len = region_len; + } + } + + return len; +} diff --git a/roms/ipxe/src/core/menu.c b/roms/ipxe/src/core/menu.c new file mode 100644 index 000000000..8d42e1f83 --- /dev/null +++ b/roms/ipxe/src/core/menu.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Menu selection + * + */ + +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/core/misc.c b/roms/ipxe/src/core/misc.c index 8f56e1fb4..11342481a 100644 --- a/roms/ipxe/src/core/misc.c +++ b/roms/ipxe/src/core/misc.c @@ -35,8 +35,17 @@ int inet_aton ( const char *cp, struct in_addr *inp ) { 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 ) { @@ -47,6 +56,9 @@ unsigned long strtoul ( const char *p, char **endp, int base ) { p++; } + if ( negative ) + ret = -ret; + if ( endp ) *endp = ( char * ) p; diff --git a/roms/ipxe/src/core/monojob.c b/roms/ipxe/src/core/monojob.c index 7431f88a3..d262f70b2 100644 --- a/roms/ipxe/src/core/monojob.c +++ b/roms/ipxe/src/core/monojob.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -53,37 +54,52 @@ struct interface monojob = INTF_INIT ( monojob_intf_desc ); /** * Wait for single foreground job to complete * - * @v string Job description to display + * @v string Job description to display, or NULL to be silent * @ret rc Job final status code */ int monojob_wait ( const char *string ) { struct job_progress progress; int key; int rc; + unsigned long last_keycheck; unsigned long last_progress; + unsigned long now; unsigned long elapsed; unsigned long completed; unsigned long total; unsigned int percentage; int shown_percentage = 0; - printf ( "%s...", string ); + if ( string ) + printf ( "%s...", string ); monojob_rc = -EINPROGRESS; - last_progress = currticks(); + last_keycheck = last_progress = currticks(); while ( monojob_rc == -EINPROGRESS ) { + + /* Allow job to progress */ step(); - if ( iskey() ) { - key = getchar(); - switch ( key ) { - case CTRL_C: - monojob_close ( &monojob, -ECANCELED ); - break; - default: - break; + now = currticks(); + + /* Check for keypresses. This can be time-consuming, + * so check only once per clock tick. + */ + if ( now != last_keycheck ) { + if ( iskey() ) { + key = getchar(); + switch ( key ) { + case CTRL_C: + monojob_close ( &monojob, -ECANCELED ); + break; + default: + break; + } } + last_keycheck = now; } - elapsed = ( currticks() - last_progress ); - if ( elapsed >= TICKS_PER_SEC ) { + + /* Display progress, if applicable */ + elapsed = ( now - last_progress ); + if ( string && ( elapsed >= TICKS_PER_SEC ) ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); job_progress ( &monojob, &progress ); @@ -98,7 +114,7 @@ int monojob_wait ( const char *string ) { printf ( "." ); shown_percentage = 0; } - last_progress = currticks(); + last_progress = now; } } rc = monojob_rc; @@ -106,10 +122,13 @@ int monojob_wait ( const char *string ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); - if ( rc ) { - printf ( " %s\n", strerror ( rc ) ); - } else { - printf ( " ok\n" ); + if ( string ) { + if ( rc ) { + printf ( " %s\n", strerror ( rc ) ); + } else { + printf ( " ok\n" ); + } } + return rc; } diff --git a/roms/ipxe/src/core/null_sanboot.c b/roms/ipxe/src/core/null_sanboot.c index 9cdb16290..18c0dea84 100644 --- a/roms/ipxe/src/core/null_sanboot.c +++ b/roms/ipxe/src/core/null_sanboot.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -38,6 +39,7 @@ 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 ); diff --git a/roms/ipxe/src/core/null_time.c b/roms/ipxe/src/core/null_time.c new file mode 100644 index 000000000..506c70b52 --- /dev/null +++ b/roms/ipxe/src/core/null_time.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Nonexistent time source + * + */ + +#include + +PROVIDE_TIME_INLINE ( null, time_now ); diff --git a/roms/ipxe/src/core/nvo.c b/roms/ipxe/src/core/nvo.c index ea58badef..5383fe5c3 100644 --- a/roms/ipxe/src/core/nvo.c +++ b/roms/ipxe/src/core/nvo.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -191,8 +192,8 @@ static int nvo_save ( struct nvo_block *nvo ) { * @v setting Setting * @ret applies Setting applies within this settings block */ -static int nvo_applies ( struct settings *settings __unused, - struct setting *setting ) { +int nvo_applies ( struct settings *settings __unused, + struct setting *setting ) { return dhcpopt_applies ( setting->tag ); } @@ -295,7 +296,8 @@ int register_nvo ( struct nvo_block *nvo, struct settings *parent ) { goto err_load; /* Register settings */ - if ( ( rc = register_settings ( &nvo->settings, parent, "nvo" ) ) != 0 ) + if ( ( rc = register_settings ( &nvo->settings, parent, + NVO_SETTINGS_NAME ) ) != 0 ) goto err_register; DBGC ( nvo, "NVO %p registered\n", nvo ); diff --git a/roms/ipxe/src/core/open.c b/roms/ipxe/src/core/open.c index b026efcd9..b479c2975 100644 --- a/roms/ipxe/src/core/open.c +++ b/roms/ipxe/src/core/open.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/parseopt.c b/roms/ipxe/src/core/parseopt.c index 24a576244..659d20ee9 100644 --- a/roms/ipxe/src/core/parseopt.c +++ b/roms/ipxe/src/core/parseopt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -26,7 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include +#include #include /** @file @@ -40,6 +41,17 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 * @@ -75,7 +87,7 @@ int parse_integer ( const char *text, unsigned int *value ) { *value = strtoul ( text, &endp, 0 ); if ( *endp ) { printf ( "\"%s\": invalid integer value\n", text ); - return -EINVAL; + return -EINVAL_INTEGER; } return 0; @@ -104,21 +116,22 @@ int parse_netdev ( const char *text, struct net_device **netdev ) { } /** - * Parse image name + * Parse menu name * * @v text Text - * @ret image Image + * @ret menu Menu * @ret rc Return status code */ -int parse_image ( const char *text, struct image **image ) { +int parse_menu ( const char *text, struct menu **menu ) { - /* Sanity check */ - assert ( text != NULL ); - - /* Find network device */ - *image = find_image ( text ); - if ( ! *image ) { - printf ( "\"%s\": no such image\n", text ); + /* 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; } @@ -140,6 +153,25 @@ int parse_flag ( const char *text __unused, int *flag ) { 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 * @@ -152,16 +184,16 @@ void print_usage ( struct command_descriptor *cmd, char **argv ) { } /** - * Parse command-line options + * Reparse command-line options * * @v argc Argument count * @v argv Argument list * @v cmd Command descriptor - * @v opts Options + * @v opts Options (already initialised with default values) * @ret rc Return status code */ -int parse_options ( int argc, char **argv, struct command_descriptor *cmd, - void *opts ) { +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 */ ]; @@ -193,9 +225,6 @@ int parse_options ( int argc, char **argv, struct command_descriptor *cmd, DBGC ( cmd, "Command \"%s\" has options \"%s\", %d-%d args, len %d\n", argv[0], shortopts, cmd->min_args, cmd->max_args, cmd->len ); - /* Clear options */ - memset ( opts, 0, cmd->len ); - /* Parse options */ while ( ( c = getopt_long ( argc, argv, shortopts, longopts, NULL ) ) >= 0 ) { @@ -205,10 +234,13 @@ int parse_options ( int argc, char **argv, struct command_descriptor *cmd, 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; + return -EINVAL_MISSING_ARGUMENT; default: /* Search for an option to parse */ for ( i = 0 ; i < cmd->num_options ; i++ ) { @@ -233,3 +265,21 @@ int parse_options ( int argc, char **argv, struct command_descriptor *cmd, 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/roms/ipxe/src/core/pcmcia.c b/roms/ipxe/src/core/pcmcia.c index 2d8ceb6f5..5fd21f4a9 100644 --- a/roms/ipxe/src/core/pcmcia.c +++ b/roms/ipxe/src/core/pcmcia.c @@ -34,7 +34,6 @@ FILE_LICENCE ( GPL2_ONLY ); #define CODE_STATUS "alpha" #define CODE_VERSION "0.1.3" #include -#include #include int sockets; /* AHTODO: Phase this out! */ diff --git a/roms/ipxe/src/core/pending.c b/roms/ipxe/src/core/pending.c new file mode 100644 index 000000000..c2671a688 --- /dev/null +++ b/roms/ipxe/src/core/pending.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include + +/** @file + * + * Pending operations + * + */ + +/** Total count of pending operations */ +static int pending_total; + +/** + * Mark an operation as pending + * + * @v pending Pending operation + */ +void pending_get ( struct pending_operation *pending ) { + + pending->count++; + pending_total++; + DBGC ( pending, "PENDING %p incremented to %d (total %d)\n", + pending, pending->count, pending_total ); +} + +/** + * Mark an operation as no longer pending + * + * @v pending Pending operation + */ +void pending_put ( struct pending_operation *pending ) { + + if ( pending->count ) { + pending_total--; + pending->count--; + DBGC ( pending, "PENDING %p decremented to %d (total %d)\n", + pending, pending->count, pending_total ); + } +} + +/** + * Wait for pending operations to complete + * + * @v timeout Timeout period, in ticks (0=indefinite) + * @ret rc Return status code + */ +int pending_wait ( unsigned long timeout ) { + unsigned long start = currticks(); + + do { + if ( pending_total == 0 ) + return 0; + step(); + } while ( ( timeout == 0 ) || ( ( currticks() - start ) < timeout ) ); + + return -ETIMEDOUT; +} diff --git a/roms/ipxe/src/core/posix_io.c b/roms/ipxe/src/core/posix_io.c index 38bd727b0..8460d0f51 100644 --- a/roms/ipxe/src/core/posix_io.c +++ b/roms/ipxe/src/core/posix_io.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/process.c b/roms/ipxe/src/core/process.c index a32978564..d341a2c37 100644 --- a/roms/ipxe/src/core/process.c +++ b/roms/ipxe/src/core/process.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -33,6 +34,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** 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 * @@ -43,13 +54,13 @@ static LIST_HEAD ( run_queue ); */ void process_add ( struct process *process ) { if ( ! process_running ( process ) ) { - DBGC ( process, "PROCESS %p (%p) starting\n", - process, process->step ); + 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 ( process, "PROCESS %p (%p) already started\n", - process, process->step ); + DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT + " already started\n", PROC_DBG ( process ) ); } } @@ -63,14 +74,14 @@ void process_add ( struct process *process ) { */ void process_del ( struct process *process ) { if ( process_running ( process ) ) { - DBGC ( process, "PROCESS %p (%p) stopping\n", - process, process->step ); + 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 ( process, "PROCESS %p (%p) already stopped\n", - process, process->step ); + DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT + " already stopped\n", PROC_DBG ( process ) ); } } @@ -82,17 +93,25 @@ void process_del ( struct process *process ) { */ void step ( void ) { struct process *process; + struct process_descriptor *desc; + void *object; if ( ( process = list_first_entry ( &run_queue, struct process, list ) ) ) { - list_del ( &process->list ); - list_add_tail ( &process->list, &run_queue ); ref_get ( process->refcnt ); /* Inhibit destruction mid-step */ - DBGC2 ( process, "PROCESS %p (%p) executing\n", - process, process->step ); - process->step ( process ); - DBGC2 ( process, "PROCESS %p (%p) finished executing\n", - process, process->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 */ } } diff --git a/roms/ipxe/src/core/refcnt.c b/roms/ipxe/src/core/refcnt.c index 6117d741d..68a86120e 100644 --- a/roms/ipxe/src/core/refcnt.c +++ b/roms/ipxe/src/core/refcnt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/resolv.c b/roms/ipxe/src/core/resolv.c index 91f0c15ce..86f19ee2d 100644 --- a/roms/ipxe/src/core/resolv.c +++ b/roms/ipxe/src/core/resolv.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -86,16 +87,16 @@ struct numeric_resolv { int rc; }; -static void numeric_step ( struct process *process ) { - struct numeric_resolv *numeric = - container_of ( process, struct numeric_resolv, process ); +static void numeric_step ( struct numeric_resolv *numeric ) { - process_del ( process ); 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; @@ -107,7 +108,8 @@ static int numeric_resolv ( struct interface *resolv, return -ENOMEM; ref_init ( &numeric->refcnt, NULL ); intf_init ( &numeric->resolv, &null_intf_desc, &numeric->refcnt ); - process_init ( &numeric->process, numeric_step, &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", diff --git a/roms/ipxe/src/core/serial.c b/roms/ipxe/src/core/serial.c index a5551b136..8f5a159c4 100644 --- a/roms/ipxe/src/core/serial.c +++ b/roms/ipxe/src/core/serial.c @@ -93,6 +93,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define uart_writeb(val,addr) outb((val),(addr)) #endif +/* Boolean for the state of serial driver initialization */ +int serial_initialized = 0; + /* * void serial_putc(int ch); * Write character `ch' to port UART_BASE. @@ -207,7 +210,6 @@ static void serial_init ( void ) { /* Set clear to send, so flow control works... */ uart_writeb((1<<1), UART_BASE + UART_MCR); - /* Flush the input buffer. */ do { /* rx buffer reg @@ -217,6 +219,9 @@ static void serial_init ( void ) { /* line status reg */ status = uart_readb(UART_BASE + UART_LSR); } while(status & UART_LSR_DR); + + /* Note that serial support has been initialized */ + serial_initialized = 1; out: return; } diff --git a/roms/ipxe/src/core/serial_console.c b/roms/ipxe/src/core/serial_console.c index b05a06b17..3852a308c 100644 --- a/roms/ipxe/src/core/serial_console.c +++ b/roms/ipxe/src/core/serial_console.c @@ -1,6 +1,7 @@ #include #include #include +#include /** @file * @@ -8,12 +9,21 @@ * */ +/* 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; + /* + * Check if serial driver initialization is done. + * If so, it's time to enable the serial console. + */ + if ( serial_initialized ) + serial_console.disabled = 0; } struct console_driver serial_console __console_driver = { @@ -21,6 +31,7 @@ struct console_driver serial_console __console_driver = { .getchar = serial_getc, .iskey = serial_ischar, .disabled = 1, + .usage = CONSOLE_SERIAL, }; /** diff --git a/roms/ipxe/src/core/settings.c b/roms/ipxe/src/core/settings.c index 0a8c5f68e..656ae19fe 100644 --- a/roms/ipxe/src/core/settings.c +++ b/roms/ipxe/src/core/settings.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -31,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -178,6 +180,11 @@ int generic_settings_fetch ( struct settings *settings, if ( len > generic->data_len ) len = generic->data_len; memcpy ( data, generic_setting_data ( generic ), len ); + + /* Set setting type, if not yet specified */ + if ( ! setting->type ) + setting->type = generic->setting.type; + return generic->data_len; } @@ -258,8 +265,8 @@ static void autovivified_settings_free ( struct refcnt *refcnt ) { * @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 * find_child_settings ( struct settings *parent, + const char *name ) { struct settings *settings; /* Treat empty name as meaning "this block" */ @@ -612,8 +619,12 @@ static int fetch_setting_and_origin ( struct settings *settings, if ( setting_applies ( settings, setting ) && ( ( ret = settings->op->fetch ( settings, setting, data, len ) ) >= 0 ) ) { + /* Record origin, if applicable */ if ( origin ) *origin = settings; + /* Default to string setting type, if not yet specified */ + if ( ! setting->type ) + setting->type = &setting_type_string; return ret; } @@ -676,6 +687,46 @@ 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 * @@ -776,6 +827,41 @@ int fetch_ipv4_setting ( struct settings *settings, struct setting *setting, 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 * @@ -786,30 +872,20 @@ int fetch_ipv4_setting ( struct settings *settings, struct setting *setting, */ int fetch_int_setting ( struct settings *settings, struct setting *setting, long *value ) { - union { - uint8_t u8[ sizeof ( long ) ]; - int8_t s8[ sizeof ( long ) ]; - } buf; + unsigned long dummy; + long tmp; int len; - int i; /* Avoid returning uninitialised data on error */ *value = 0; /* Fetch raw (network-ordered, variable-length) setting */ - len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) ); + len = fetch_setting ( settings, setting, &tmp, sizeof ( tmp ) ); if ( len < 0 ) return len; - if ( len > ( int ) sizeof ( buf ) ) - return -ERANGE; - - /* Convert to host-ordered signed long */ - *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L ); - for ( i = 0 ; i < len ; i++ ) { - *value = ( ( *value << 8 ) | buf.u8[i] ); - } - return len; + /* Extract numeric value */ + return numeric_setting_value ( &tmp, len, value, &dummy ); } /** @@ -822,22 +898,20 @@ int fetch_int_setting ( struct settings *settings, struct setting *setting, */ int fetch_uint_setting ( struct settings *settings, struct setting *setting, unsigned long *value ) { - long svalue; + signed long dummy; + long tmp; int len; /* Avoid returning uninitialised data on error */ *value = 0; - /* Fetch as a signed long */ - len = fetch_int_setting ( settings, setting, &svalue ); + /* Fetch raw (network-ordered, variable-length) setting */ + len = fetch_setting ( settings, setting, &tmp, sizeof ( tmp ) ); if ( len < 0 ) return len; - /* Mask off sign-extended bits */ - assert ( len <= ( int ) sizeof ( long ) ); - *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) ); - - return len; + /* Extract numeric value */ + return numeric_setting_value ( &tmp, len, &dummy, value ); } /** @@ -929,27 +1003,83 @@ int setting_cmp ( struct setting *a, struct setting *b ) { */ /** - * Store value of typed setting + * 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 type Settings type * @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. Avoid imposing the burden of - * checking for NULL values on each typed setting's storef() - * method. - */ - if ( ! value ) + /* NULL value or empty string implies deletion */ + if ( ( ! value ) || ( ! value[0] ) ) return delete_setting ( settings, setting ); - - return setting->type->storef ( settings, setting, value ); + + /* 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 * @@ -1011,6 +1141,7 @@ static struct setting_type * find_setting_type ( const char *name ) { * @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 default_type Default type to use, if none specified * @v tmp_name Buffer for copy of setting name * @ret rc Return status code * @@ -1026,6 +1157,7 @@ parse_setting_name ( const char *name, struct settings * ( * get_child ) ( struct settings *, const char * ), struct settings **settings, struct setting *setting, + struct setting_type *default_type, char *tmp_name ) { char *settings_name; char *setting_name; @@ -1036,7 +1168,7 @@ parse_setting_name ( const char *name, *settings = &settings_root; memset ( setting, 0, sizeof ( *setting ) ); setting->name = ""; - setting->type = &setting_type_string; + setting->type = default_type; /* Split name into "[settings_name/]setting_name[:type_name]" */ strcpy ( tmp_name, name ); @@ -1105,14 +1237,45 @@ int setting_name ( struct settings *settings, struct setting *setting, setting->name, setting->type->name ); } +/** + * Store value of named setting + * + * @v name Name of setting + * @v default_type Default type to use, if none specified + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +int store_named_setting ( const char *name, struct setting_type *default_type, + const void *data, size_t len ) { + 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, default_type, + tmp_name ) ) != 0 ) + return rc; + + /* Store setting */ + if ( ( rc = store_setting ( settings, &setting, data, len ) ) != 0 ) + return rc; + + return 0; +} + /** * Parse and store value of named setting * * @v name Name of setting + * @v default_type Default type to use, if none specified * @v value Formatted setting data, or NULL * @ret rc Return status code */ -int storef_named_setting ( const char *name, const char *value ) { +int storef_named_setting ( const char *name, struct setting_type *default_type, + const char *value ) { struct settings *settings; struct setting setting; char tmp_name[ strlen ( name ) + 1 ]; @@ -1120,7 +1283,8 @@ int storef_named_setting ( const char *name, const char *value ) { /* Parse setting name */ if ( ( rc = parse_setting_name ( name, autovivify_child_settings, - &settings, &setting, tmp_name )) != 0) + &settings, &setting, default_type, + tmp_name ) ) != 0 ) return rc; /* Store setting */ @@ -1151,8 +1315,8 @@ int fetchf_named_setting ( const char *name, int rc; /* Parse setting name */ - if ( ( rc = parse_setting_name ( name, find_child_settings, - &settings, &setting, tmp_name )) != 0) + if ( ( rc = parse_setting_name ( name, find_child_settings, &settings, + &setting, NULL, tmp_name ) ) != 0 ) return rc; /* Fetch setting */ @@ -1168,6 +1332,45 @@ int fetchf_named_setting ( const char *name, return len; } +/** + * Fetch and format copy of value of named setting + * + * @v name Name of setting + * @v data Buffer to allocate and fill with formatted value + * @ret len Length of formatted value, 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 fetchf_named_setting_copy ( const char *name, char **data ) { + int len; + int check_len; + + /* Avoid returning uninitialised data on error */ + *data = NULL; + + /* Fetch formatted value length, and return success if non-existent */ + len = fetchf_named_setting ( name, NULL, 0, NULL, 0 ); + if ( len < 0 ) + return 0; + + /* Allocate buffer */ + *data = malloc ( len + 1 /* NUL */ ); + if ( ! *data ) + return -ENOMEM; + + /* Fetch formatted value */ + check_len = fetchf_named_setting ( name, NULL, 0, *data, + ( len + 1 /* NUL */ ) ); + assert ( check_len == len ); + return len; +} + /****************************************************************************** * * Setting types @@ -1176,302 +1379,334 @@ int fetchf_named_setting ( const char *name, */ /** - * Parse and store value of string setting + * Parse string setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 storef_string ( struct settings *settings, struct setting *setting, - const char *value ) { - return store_setting ( settings, setting, value, strlen ( value ) ); +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; } /** - * Fetch and format value of string setting + * Format string setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_string ( struct settings *settings, struct setting *setting, - char *buf, size_t len ) { - return fetch_string_setting ( settings, setting, buf, len ); +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", - .storef = storef_string, - .fetchf = fetchf_string, + .parse = parse_string_setting, + .format = format_string_setting, }; /** - * Parse and store value of URI-encoded string setting + * Parse URI-encoded string setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 storef_uristring ( struct settings *settings, - struct setting *setting, - const char *value ) { - char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */ - size_t len; +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 ) ); - len = uri_decode ( value, buf, sizeof ( buf ) ); - return store_setting ( settings, setting, buf, len ); + /* Copy to output buffer (excluding NUL) */ + if ( len > raw_len ) + len = raw_len; + memcpy ( buf, tmp, len ); + + return raw_len; } /** - * Fetch and format value of URI-encoded string setting + * Format URI-encoded string setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_uristring ( struct settings *settings, - struct setting *setting, - char *buf, size_t len ) { - ssize_t raw_len; +static int format_uristring_setting ( const void *raw, size_t raw_len, + char *buf, size_t len ) { + char tmp[ raw_len + 1 /* NUL */ ]; - /* We need to always retrieve the full raw string to know the - * length of the encoded string. - */ - raw_len = fetch_setting ( settings, setting, NULL, 0 ); - if ( raw_len < 0 ) - return raw_len; - - { - char raw_buf[ raw_len + 1 ]; - - fetch_string_setting ( settings, setting, raw_buf, - sizeof ( raw_buf ) ); - return uri_encode ( raw_buf, buf, len, URI_FRAGMENT ); - } + /* 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", - .storef = storef_uristring, - .fetchf = fetchf_uristring, + .parse = parse_uristring_setting, + .format = format_uristring_setting, }; /** - * Parse and store value of IPv4 address setting + * Parse IPv4 address setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 storef_ipv4 ( struct settings *settings, struct setting *setting, - const char *value ) { +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; - return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) ); + + /* Copy to buffer */ + if ( len > sizeof ( ipv4 ) ) + len = sizeof ( ipv4 ); + memcpy ( buf, &ipv4, len ); + + return ( sizeof ( ipv4 ) ); } /** - * Fetch and format value of IPv4 address setting + * Format IPv4 address setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_ipv4 ( struct settings *settings, struct setting *setting, - char *buf, size_t len ) { - struct in_addr ipv4; - int raw_len; +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 = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0) - return raw_len; - return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) ); + 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", - .storef = storef_ipv4, - .fetchf = fetchf_ipv4, + .parse = parse_ipv4_setting, + .format = format_ipv4_setting, }; /** - * Parse and store value of integer setting + * Parse integer setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer * @v size Integer size, in bytes - * @ret rc Return status code + * @ret len Length of raw value, or negative error */ -static int storef_int ( struct settings *settings, struct setting *setting, - const char *value, unsigned int size ) { +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; - return store_setting ( settings, setting, - &u.bytes[ sizeof ( u ) - size ], size ); + + /* Copy to buffer */ + if ( len > size ) + len = size; + memcpy ( buf, &u.bytes[ sizeof ( u ) - size ], len ); + + return size; } /** - * Parse and store value of 8-bit integer setting + * Parse 8-bit integer setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer * @v size Integer size, in bytes - * @ret rc Return status code + * @ret len Length of raw value, or negative error */ -static int storef_int8 ( struct settings *settings, struct setting *setting, - const char *value ) { - return storef_int ( settings, setting, value, 1 ); +static int parse_int8_setting ( const char *value, void *buf, size_t len ) { + return parse_int_setting ( value, buf, len, sizeof ( uint8_t ) ); } /** - * Parse and store value of 16-bit integer setting + * Parse 16-bit integer setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer * @v size Integer size, in bytes - * @ret rc Return status code + * @ret len Length of raw value, or negative error */ -static int storef_int16 ( struct settings *settings, struct setting *setting, - const char *value ) { - return storef_int ( settings, setting, value, 2 ); +static int parse_int16_setting ( const char *value, void *buf, size_t len ) { + return parse_int_setting ( value, buf, len, sizeof ( uint16_t ) ); } /** - * Parse and store value of 32-bit integer setting + * Parse 32-bit integer setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer * @v size Integer size, in bytes - * @ret rc Return status code + * @ret len Length of raw value, or negative error */ -static int storef_int32 ( struct settings *settings, struct setting *setting, - const char *value ) { - return storef_int ( settings, setting, value, 4 ); +static int parse_int32_setting ( const char *value, void *buf, size_t len ) { + return parse_int_setting ( value, buf, len, sizeof ( uint32_t ) ); } /** - * Fetch and format value of signed integer setting + * Format signed integer setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_int ( struct settings *settings, struct setting *setting, - char *buf, size_t len ) { - long value; - int rc; +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; - if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 ) - return rc; + /* 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 ); } /** - * Fetch and format value of unsigned integer setting + * Format unsigned integer setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_uint ( struct settings *settings, struct setting *setting, - char *buf, size_t len ) { +static int format_uint_setting ( const void *raw, size_t raw_len, char *buf, + size_t len ) { + signed long dummy; unsigned long value; - int rc; + int check_len; - if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 ) - return rc; + /* 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", - .storef = storef_int8, - .fetchf = fetchf_int, + .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", - .storef = storef_int16, - .fetchf = fetchf_int, + .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", - .storef = storef_int32, - .fetchf = fetchf_int, + .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", - .storef = storef_int8, - .fetchf = fetchf_uint, + .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", - .storef = storef_int16, - .fetchf = fetchf_uint, + .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", - .storef = storef_int32, - .fetchf = fetchf_uint, + .parse = parse_int32_setting, + .format = format_uint_setting, }; /** - * Parse and store value of hex string setting + * Parse hex string setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 storef_hex ( struct settings *settings, struct setting *setting, - const char *value ) { +static int parse_hex_setting ( const char *value, void *buf, size_t len ) { char *ptr = ( char * ) value; - uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */ - unsigned int len = 0; + uint8_t *bytes = buf; + unsigned int count = 0; + uint8_t byte; while ( 1 ) { - bytes[len++] = strtoul ( ptr, &ptr, 16 ); + byte = strtoul ( ptr, &ptr, 16 ); + if ( count++ < len ) + *bytes++ = byte; switch ( *ptr ) { case '\0' : - return store_setting ( settings, setting, bytes, len ); + return count; case ':' : case '-' : ptr++; @@ -1483,128 +1718,112 @@ static int storef_hex ( struct settings *settings, struct setting *setting, } /** - * Fetch and format value of hex string setting + * Format hex string setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_hex ( struct settings *settings, struct setting *setting, - char *buf, size_t len, const char *delimiter ) { - int raw_len; - int check_len; +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; - int i; - - raw_len = fetch_setting_len ( settings, setting ); - if ( raw_len < 0 ) - return raw_len; - - { - uint8_t raw[raw_len]; - - check_len = fetch_setting ( settings, setting, raw, - sizeof ( raw ) ); - if ( check_len < 0 ) - return check_len; - assert ( check_len == raw_len ); - - 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 : "" ), - raw[i] ); - } - return used; + 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; } /** - * Fetch and format value of hex string setting (using colon delimiter) + * Format hex string setting value (using colon delimiter) * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_hex_colon ( struct settings *settings, - struct setting *setting, - char *buf, size_t len ) { - return fetchf_hex ( settings, setting, buf, len, ":" ); +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, ":" ); } /** - * Fetch and format value of hex string setting (using hyphen delimiter) + * Format hex string setting value (using hyphen delimiter) * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_hex_hyphen ( struct settings *settings, - struct setting *setting, - char *buf, size_t len ) { - return fetchf_hex ( settings, setting, buf, len, "-" ); +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", - .storef = storef_hex, - .fetchf = fetchf_hex_colon, + .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", - .storef = storef_hex, - .fetchf = fetchf_hex_hyphen, + .parse = parse_hex_setting, + .format = format_hex_hyphen_setting, }; /** - * Parse and store value of UUID setting + * Parse UUID setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 storef_uuid ( struct settings *settings __unused, - struct setting *setting __unused, - const char *value __unused ) { +static int parse_uuid_setting ( const char *value __unused, + void *buf __unused, size_t len __unused ) { return -ENOTSUP; } /** - * Fetch and format value of UUID setting + * Format UUID setting value * - * @v settings Settings block, or NULL to search all blocks - * @v setting Setting to fetch + * @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 fetchf_uuid ( struct settings *settings, struct setting *setting, - char *buf, size_t len ) { - union uuid uuid; - int raw_len; +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; - if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0) - return raw_len; - return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) ); + /* Format value */ + return snprintf ( buf, len, "%s", uuid_ntoa ( uuid ) ); } /** UUID setting type */ struct setting_type setting_type_uuid __setting_type = { .name = "uuid", - .storef = storef_uuid, - .fetchf = fetchf_uuid, + .parse = parse_uuid_setting, + .format = format_uuid_setting, }; /****************************************************************************** @@ -1703,6 +1922,22 @@ struct setting hostname_setting __setting ( SETTING_HOST ) = { .type = &setting_type_string, }; +/** Domain name setting */ +struct setting domain_setting __setting ( SETTING_IPv4_EXTRA ) = { + .name = "domain", + .description = "DNS domain", + .tag = DHCP_DOMAIN_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", @@ -1742,3 +1977,122 @@ struct setting priority_setting __setting ( SETTING_MISC ) = { .tag = DHCP_EB_PRIORITY, .type = &setting_type_int8, }; + +/****************************************************************************** + * + * Built-in settings block + * + ****************************************************************************** + */ + +/** Built-in setting tag magic */ +#define BUILTIN_SETTING_TAG_MAGIC 0xb1 + +/** + * Construct built-in setting tag + * + * @v id Unique identifier + * @ret tag Setting tag + */ +#define BUILTIN_SETTING_TAG( id ) ( ( BUILTIN_SETTING_TAG_MAGIC << 24 ) | (id) ) + +/** "errno" setting tag */ +#define BUILTIN_SETTING_TAG_ERRNO BUILTIN_SETTING_TAG ( 0x01 ) + +/** Error number setting */ +struct setting errno_setting __setting ( SETTING_MISC ) = { + .name = "errno", + .description = "Last error", + .tag = BUILTIN_SETTING_TAG_ERRNO, + .type = &setting_type_uint32, +}; + +/** + * Fetch error number 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 errno_fetch ( struct settings *settings __unused, + struct setting *setting __unused, + void *data, size_t len ) { + uint32_t content; + + /* Return current error */ + content = htonl ( errno ); + if ( len > sizeof ( content ) ) + len = sizeof ( content ); + memcpy ( data, &content, len ); + return sizeof ( content ); +} + +/** + * Fetch built-in 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 builtin_fetch ( struct settings *settings __unused, + struct setting *setting, + void *data, size_t len ) { + + if ( setting_cmp ( setting, &errno_setting ) == 0 ) { + return errno_fetch ( settings, setting, data, len ); + } else { + return -ENOENT; + } +} + +/** + * Check applicability of built-in setting + * + * @v settings Settings block + * @v setting Setting + * @ret applies Setting applies within this settings block + */ +static int builtin_applies ( struct settings *settings __unused, + struct setting *setting ) { + unsigned int tag_magic; + + /* Check tag magic */ + tag_magic = ( setting->tag >> 24 ); + return ( tag_magic == BUILTIN_SETTING_TAG_MAGIC ); +} + +/** Built-in settings operations */ +static struct settings_operations builtin_settings_operations = { + .applies = builtin_applies, + .fetch = builtin_fetch, +}; + +/** Built-in settings */ +static struct settings builtin_settings = { + .refcnt = NULL, + .tag_magic = BUILTIN_SETTING_TAG ( 0 ), + .siblings = LIST_HEAD_INIT ( builtin_settings.siblings ), + .children = LIST_HEAD_INIT ( builtin_settings.children ), + .op = &builtin_settings_operations, +}; + +/** Initialise built-in settings */ +static void builtin_init ( void ) { + int rc; + + if ( ( rc = register_settings ( &builtin_settings, NULL, + "builtin" ) ) != 0 ) { + DBG ( "Could not register built-in settings: %s\n", + strerror ( rc ) ); + return; + } +} + +/** Built-in settings initialiser */ +struct init_fn builtin_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = builtin_init, +}; diff --git a/roms/ipxe/src/core/strtoull.c b/roms/ipxe/src/core/strtoull.c index b1ceeb45b..00986eef0 100644 --- a/roms/ipxe/src/core/strtoull.c +++ b/roms/ipxe/src/core/strtoull.c @@ -29,8 +29,17 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ 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 ) { @@ -41,6 +50,9 @@ unsigned long long strtoull ( const char *p, char **endp, int base ) { p++; } + if ( negative ) + ret = -ret; + if ( endp ) *endp = ( char * ) p; diff --git a/roms/ipxe/src/core/time.c b/roms/ipxe/src/core/time.c new file mode 100644 index 000000000..f70e1981d --- /dev/null +++ b/roms/ipxe/src/core/time.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include + +/** @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/roms/ipxe/src/core/timer.c b/roms/ipxe/src/core/timer.c index 096d07ec0..18c2b2849 100644 --- a/roms/ipxe/src/core/timer.c +++ b/roms/ipxe/src/core/timer.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/uri.c b/roms/ipxe/src/core/uri.c index ff49e47a5..e95268826 100644 --- a/roms/ipxe/src/core/uri.c +++ b/roms/ipxe/src/core/uri.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/core/uuid.c b/roms/ipxe/src/core/uuid.c index d98553f0f..27a249da8 100644 --- a/roms/ipxe/src/core/uuid.c +++ b/roms/ipxe/src/core/uuid.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -35,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v uuid UUID * @ret string UUID in canonical form */ -char * uuid_ntoa ( union uuid *uuid ) { +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", diff --git a/roms/ipxe/src/core/version.c b/roms/ipxe/src/core/version.c new file mode 100644 index 000000000..1aa22d8ec --- /dev/null +++ b/roms/ipxe/src/core/version.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +/** @file + * + * Version number + * + */ + +#include +#include + +/** Version number feature */ +FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH ); + +/** Product major version */ +const int product_major_version = VERSION_MAJOR; + +/** Product minor version */ +const int product_minor_version = VERSION_MINOR; + +/** Product version string */ +const char *product_version = VERSION; diff --git a/roms/ipxe/src/core/vsprintf.c b/roms/ipxe/src/core/vsprintf.c index b46d9c419..5cc723108 100644 --- a/roms/ipxe/src/core/vsprintf.c +++ b/roms/ipxe/src/core/vsprintf.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -21,8 +22,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include +#include #include /** @file */ @@ -60,12 +61,21 @@ static uint8_t type_sizes[] = { */ #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 @@ -79,18 +89,18 @@ static uint8_t type_sizes[] = { static char * format_hex ( char *end, unsigned long long num, int width, int flags ) { char *ptr = end; - int case_mod; + int case_mod = ( flags & LCASE ); + int pad = ( ( flags & ZPAD ) | ' ' ); /* Generate the number */ - case_mod = flags & LCASE; do { *(--ptr) = "0123456789ABCDEF"[ num & 0xf ] | case_mod; num >>= 4; } while ( num ); - /* Zero-pad to width */ + /* Pad to width */ while ( ( end - ptr ) < width ) - *(--ptr) = '0'; + *(--ptr) = pad; /* Add "0x" or "0X" if alternate form specified */ if ( flags & ALT_FORM ) { @@ -107,6 +117,7 @@ static char * format_hex ( char *end, unsigned long long num, int width, * @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. @@ -115,9 +126,12 @@ static char * format_hex ( char *end, unsigned long long num, int 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 ) { +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 ) { @@ -130,12 +144,16 @@ static char * format_decimal ( char *end, signed long num, int width ) { } while ( num ); /* Add "-" if necessary */ - if ( negative ) + if ( negative && ( ! zpad ) ) *(--ptr) = '-'; - /* Space-pad to width */ + /* Pad to width */ while ( ( end - ptr ) < width ) - *(--ptr) = ' '; + *(--ptr) = pad; + + /* Add "-" if necessary */ + if ( negative && zpad ) + *ptr = '-'; return ptr; } @@ -169,6 +187,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { char *ptr; char tmp_buf[32]; /* 32 is enough for all numerical formats. * Insane width fields could overflow this buffer. */ + wchar_t *wptr; /* Initialise context */ ctx->len = 0; @@ -186,7 +205,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { if ( *fmt == '#' ) { flags |= ALT_FORM; } else if ( *fmt == '0' ) { - /* We always 0-pad hex and space-pad decimal */ + flags |= ZPAD; } else { /* End of flag characters */ break; @@ -218,11 +237,26 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { /* Process conversion specifier */ ptr = tmp_buf + sizeof ( tmp_buf ) - 1; *ptr = '\0'; + wptr = NULL; if ( *fmt == 'c' ) { - cputchar ( ctx, va_arg ( args, unsigned int ) ); + if ( length < &type_sizes[LONG_LEN] ) { + cputchar ( ctx, va_arg ( args, unsigned int ) ); + } else { + wchar_t wc; + size_t len; + + wc = va_arg ( args, wint_t ); + len = wcrtomb ( tmp_buf, wc, NULL ); + tmp_buf[len] = '\0'; + ptr = tmp_buf; + } } else if ( *fmt == 's' ) { - ptr = va_arg ( args, char * ); - if ( ! ptr ) + if ( length < &type_sizes[LONG_LEN] ) { + ptr = va_arg ( args, char * ); + } else { + wptr = va_arg ( args, wchar_t * ); + } + if ( ( ptr == NULL ) && ( wptr == NULL ) ) ptr = ""; } else if ( *fmt == 'p' ) { intptr_t ptrval; @@ -250,13 +284,22 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { } else { decimal = va_arg ( args, signed int ); } - ptr = format_decimal ( ptr, decimal, width ); + ptr = format_decimal ( ptr, decimal, width, flags ); } else { *(--ptr) = *fmt; } /* Write out conversion result */ - for ( ; *ptr ; ptr++ ) { - cputchar ( ctx, *ptr ); + if ( wptr == NULL ) { + for ( ; *ptr ; ptr++ ) { + cputchar ( ctx, *ptr ); + } + } else { + for ( ; *wptr ; wptr++ ) { + size_t len = wcrtomb ( tmp_buf, *wptr, NULL ); + for ( ptr = tmp_buf ; len-- ; ptr++ ) { + cputchar ( ctx, *ptr ); + } + } } } diff --git a/roms/ipxe/src/core/wchar.c b/roms/ipxe/src/core/wchar.c new file mode 100644 index 000000000..7fabca470 --- /dev/null +++ b/roms/ipxe/src/core/wchar.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** + * @file + * + * Wide-character strings + * + */ + +#include + +/** + * Calculate length of wide-character string + * + * @v string String + * @ret len Length (excluding terminating NUL) + */ +size_t wcslen ( const wchar_t *string ) { + size_t len = 0; + + while ( *(string++) ) + len++; + return len; +} diff --git a/roms/ipxe/src/core/xfer.c b/roms/ipxe/src/core/xfer.c index a755d438a..8d4bc9f53 100644 --- a/roms/ipxe/src/core/xfer.c +++ b/roms/ipxe/src/core/xfer.c @@ -13,12 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -54,6 +56,7 @@ static struct xfer_metadata dummy_metadata; * @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 ); @@ -66,8 +69,22 @@ int xfer_vredirect ( struct interface *intf, int type, va_list args ) { if ( op ) { rc = op ( object, type, args ); } else { - /* Default is to reopen the interface as instructed */ + /* 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 ) { @@ -282,17 +299,28 @@ int xfer_deliver_raw ( struct interface *intf, const void *data, size_t len ) { */ int xfer_vprintf ( struct interface *intf, const char *format, va_list args ) { - size_t len; va_list args_tmp; + char *buf; + int len; + int rc; + /* Create temporary string */ va_copy ( args_tmp, args ); - len = vsnprintf ( NULL, 0, format, args ); - { - char buf[len + 1]; - vsnprintf ( buf, sizeof ( buf ), format, args_tmp ); - va_end ( args_tmp ); - return xfer_deliver_raw ( intf, buf, len ); + 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; } /** diff --git a/roms/ipxe/src/core/xferbuf.c b/roms/ipxe/src/core/xferbuf.c new file mode 100644 index 000000000..a0457feee --- /dev/null +++ b/roms/ipxe/src/core/xferbuf.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include + +/** @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/roms/ipxe/src/crypto/aes_wrap.c b/roms/ipxe/src/crypto/aes_wrap.c index 46ef016f5..c09480e5a 100644 --- a/roms/ipxe/src/crypto/aes_wrap.c +++ b/roms/ipxe/src/crypto/aes_wrap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -48,7 +49,7 @@ int aes_wrap ( const void *kek, const void *src, void *dest, int nblk ) cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 ); /* Set up */ - memset ( A, 0xA6, sizeof ( A ) ); + memset ( A, 0xA6, 8 ); memmove ( dest + 8, src, nblk * 8 ); /* Wrap */ diff --git a/roms/ipxe/src/crypto/arc4.c b/roms/ipxe/src/crypto/arc4.c index ab3325c83..91a732019 100644 --- a/roms/ipxe/src/crypto/arc4.c +++ b/roms/ipxe/src/crypto/arc4.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/crypto/asn1.c b/roms/ipxe/src/crypto/asn1.c index a54d31d0c..6d880704f 100644 --- a/roms/ipxe/src/crypto/asn1.c +++ b/roms/ipxe/src/crypto/asn1.c @@ -13,14 +13,20 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include +#include +#include #include +#include +#include #include /** @file @@ -29,43 +35,88 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* 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 + * @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. - * - * If any error occurs (i.e. if the object is not of the expected - * type, or if we overflow beyond the end of the ASN.1 object), then - * the cursor will be invalidated and a negative value will be - * returned. */ -static int asn1_start ( struct asn1_cursor *cursor, - unsigned int type ) { +static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) { unsigned int len_len; unsigned int len; - int rc; /* Sanity check */ if ( cursor->len < 2 /* Tag byte and first length byte */ ) { if ( cursor->len ) DBGC ( cursor, "ASN1 %p too short\n", cursor ); - rc = -EINVAL; - goto notfound; + return -EINVAL_ASN1_EMPTY; } /* Check the tag byte */ - if ( *( ( uint8_t * ) cursor->data ) != type ) { + 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 ) ); - rc = -ENXIO; - goto notfound; + return -ENXIO; } cursor->data++; cursor->len--; @@ -82,8 +133,7 @@ static int asn1_start ( struct asn1_cursor *cursor, if ( cursor->len < len_len ) { DBGC ( cursor, "ASN1 %p bad length field length %d (max " "%zd)\n", cursor, len_len, cursor->len ); - rc = -EINVAL; - goto notfound; + return -EINVAL_ASN1_LEN_LEN; } /* Extract the length and sanity check */ @@ -96,23 +146,17 @@ static int asn1_start ( struct asn1_cursor *cursor, if ( cursor->len < len ) { DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n", cursor, len, cursor->len ); - rc = -EINVAL; - goto notfound; + return -EINVAL_ASN1_LEN; } return len; - - notfound: - cursor->data = NULL; - cursor->len = 0; - return rc; } /** * Enter ASN.1 object * * @v cursor ASN.1 object cursor - * @v type Expected type + * @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 @@ -123,8 +167,10 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { int len; len = asn1_start ( cursor, type ); - if ( len < 0 ) + if ( len < 0 ) { + asn1_invalidate_cursor ( cursor ); return len; + } cursor->len = len; DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n", @@ -134,17 +180,17 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { } /** - * Skip ASN.1 object + * Skip ASN.1 object if present * * @v cursor ASN.1 object cursor - * @v type Expected type + * @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. + * object. If any error occurs, the object cursor will not be + * modified. */ -int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) { +int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) { int len; len = asn1_start ( cursor, type ); @@ -158,9 +204,644 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) { if ( ! cursor->len ) { DBGC ( cursor, "ASN1 %p reached end of object\n", cursor ); - cursor->data = NULL; 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 */ + memset ( &pairs, 0, sizeof ( pairs ) ); + data = contents.data; + remaining = contents.len; + for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { + if ( remaining < 2 ) { + /* Some certificates violate the X.509 RFC by + * omitting the "seconds" value. + */ + if ( i == ( sizeof ( pairs.raw ) - 1 ) ) + break; + 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/roms/ipxe/src/crypto/axtls/aes.c b/roms/ipxe/src/crypto/axtls/aes.c index 87faaa1d2..bd99a7097 100644 --- a/roms/ipxe/src/crypto/axtls/aes.c +++ b/roms/ipxe/src/crypto/axtls/aes.c @@ -1,23 +1,33 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * 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. + * All rights reserved. * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * 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_LICENCE ( GPL2_OR_LATER ); - /** * 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 @@ -25,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include "os_port.h" #include "crypto.h" /* all commented out in skeleton mode */ @@ -64,10 +75,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); (f8)^=rot2(f4), \ (f8)^rot1(f9)) -/* some macros to do endian independent byte extraction */ -#define n2l(c,l) l=ntohl(*c); c++ -#define l2n(l,c) *c++=htonl(l) - /* * AES S-box */ @@ -154,11 +161,15 @@ static const unsigned char Rcon[30]= 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 = (x&0x80) ? (x<<1)^0x1b : x<<1; + return (x&0x80) ? (x<<1)^0x1b : x<<1; } /** @@ -247,7 +258,7 @@ void AES_convert_key(AES_CTX *ctx) k = ctx->ks; k += 4; - for (i=ctx->rounds*4; i>4; i--) + for (i= ctx->rounds*4; i > 4; i--) { w= *k; w = inv_mix_col(w,t1,t2,t3,t4); @@ -255,52 +266,43 @@ void AES_convert_key(AES_CTX *ctx) } } -#if 0 /** * 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) { - uint32_t tin0, tin1, tin2, tin3; - uint32_t tout0, tout1, tout2, tout3; - uint32_t tin[4]; - uint32_t *iv = (uint32_t *)ctx->iv; - uint32_t *msg_32 = (uint32_t *)msg; - uint32_t *out_32 = (uint32_t *)out; - - n2l(iv, tout0); - n2l(iv, tout1); - n2l(iv, tout2); - n2l(iv, tout3); - iv -= 4; + int i; + uint32_t tin[4], tout[4], iv[4]; - for (length -= 16; length >= 0; length -= 16) + 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) { - n2l(msg_32, tin0); - n2l(msg_32, tin1); - n2l(msg_32, tin2); - n2l(msg_32, tin3); - tin[0] = tin0^tout0; - tin[1] = tin1^tout1; - tin[2] = tin2^tout2; - tin[3] = tin3^tout3; + 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); - tout0 = tin[0]; - l2n(tout0, out_32); - tout1 = tin[1]; - l2n(tout1, out_32); - tout2 = tin[2]; - l2n(tout2, out_32); - tout3 = tin[3]; - l2n(tout3, out_32); + 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; } - l2n(tout0, iv); - l2n(tout1, iv); - l2n(tout2, iv); - l2n(tout3, iv); + for (i = 0; i < 4; i++) + iv[i] = htonl(tout[i]); + memcpy(ctx->iv, iv, AES_IV_SIZE); } /** @@ -308,61 +310,48 @@ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) */ void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) { - uint32_t tin0, tin1, tin2, tin3; - uint32_t xor0,xor1,xor2,xor3; - uint32_t tout0,tout1,tout2,tout3; - uint32_t data[4]; - uint32_t *iv = (uint32_t *)ctx->iv; - uint32_t *msg_32 = (uint32_t *)msg; - uint32_t *out_32 = (uint32_t *)out; - - n2l(iv ,xor0); - n2l(iv, xor1); - n2l(iv, xor2); - n2l(iv, xor3); - iv -= 4; - - for (length-=16; length >= 0; length -= 16) + 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) { - n2l(msg_32, tin0); - n2l(msg_32, tin1); - n2l(msg_32, tin2); - n2l(msg_32, tin3); + uint32_t msg_32[4]; + uint32_t out_32[4]; + memcpy(msg_32, msg, AES_BLOCKSIZE); + msg += AES_BLOCKSIZE; - data[0] = tin0; - data[1] = tin1; - data[2] = tin2; - data[3] = tin3; + for (i = 0; i < 4; i++) + { + tin[i] = ntohl(msg_32[i]); + data[i] = tin[i]; + } AES_decrypt(ctx, data); - tout0 = data[0]^xor0; - tout1 = data[1]^xor1; - tout2 = data[2]^xor2; - tout3 = data[3]^xor3; - - xor0 = tin0; - xor1 = tin1; - xor2 = tin2; - xor3 = tin3; + for (i = 0; i < 4; i++) + { + tout[i] = data[i]^xor[i]; + xor[i] = tin[i]; + out_32[i] = htonl(tout[i]); + } - l2n(tout0, out_32); - l2n(tout1, out_32); - l2n(tout2, out_32); - l2n(tout3, out_32); + memcpy(out, out_32, AES_BLOCKSIZE); + out += AES_BLOCKSIZE; } - l2n(xor0, iv); - l2n(xor1, iv); - l2n(xor2, iv); - l2n(xor3, iv); + for (i = 0; i < 4; i++) + iv[i] = htonl(xor[i]); + memcpy(ctx->iv, iv, AES_IV_SIZE); } -#endif /** * Encrypt a single block (16 bytes) of data */ -void AES_encrypt(const AES_CTX *ctx, uint32_t *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. @@ -375,9 +364,7 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) /* 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++) @@ -395,12 +382,10 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) { 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); @@ -409,32 +394,28 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) /* 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 */ -void AES_decrypt(const AES_CTX *ctx, uint32_t *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; - uint32_t *k = (uint32_t*)ctx->ks + ((rounds+1)*4); + 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++) + for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++) { /* Perform ByteSub and ShiftRow operations together */ for (row = 4; row > 0; row--) @@ -469,9 +450,7 @@ void AES_decrypt(const AES_CTX *ctx, uint32_t *data) } for (row = 4; row > 0; row--) - { data[row-1] = tmp[row-1] ^ *(--k); - } } } diff --git a/roms/ipxe/src/crypto/axtls/bigint.c b/roms/ipxe/src/crypto/axtls/bigint.c deleted file mode 100644 index 49cad971e..000000000 --- a/roms/ipxe/src/crypto/axtls/bigint.c +++ /dev/null @@ -1,1496 +0,0 @@ -/* - * Copyright(C) 2006 Cameron Rich - * - * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** - * @defgroup bigint_api Big Integer API - * @brief The bigint implementation as used by the axTLS project. - * - * The bigint library is for RSA encryption/decryption as well as signing. - * This code tries to minimise use of malloc/free by maintaining a small - * cache. A bigint context may maintain state by being made "permanent". - * It be be later released with a bi_depermanent() and bi_free() call. - * - * It supports the following reduction techniques: - * - Classical - * - Barrett - * - Montgomery - * - * It also implements the following: - * - Karatsuba multiplication - * - Squaring - * - Sliding window exponentiation - * - Chinese Remainder Theorem (implemented in rsa.c). - * - * All the algorithms used are pretty standard, and designed for different - * data bus sizes. Negative numbers are not dealt with at all, so a subtraction - * may need to be tested for negativity. - * - * This library steals some ideas from Jef Poskanzer - * - * and GMP . It gets most of its implementation - * detail from "The Handbook of Applied Cryptography" - * - * @{ - */ - -#include -#include -#include -#include -#include -#include "bigint.h" -#include "crypto.h" - -static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i); -static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom); -static bigint __malloc *alloc(BI_CTX *ctx, int size); -static bigint *trim(bigint *bi); -static void more_comps(bigint *bi, int n); -#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \ - defined(CONFIG_BIGINT_MONTGOMERY) -static bigint *comp_right_shift(bigint *biR, int num_shifts); -static bigint *comp_left_shift(bigint *biR, int num_shifts); -#endif - -#ifdef CONFIG_BIGINT_CHECK_ON -static void check(const bigint *bi); -#endif - -/** - * @brief Start a new bigint context. - * @return A bigint context. - */ -BI_CTX *bi_initialize(void) -{ - /* calloc() sets everything to zero */ - BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX)); - - /* the radix */ - ctx->bi_radix = alloc(ctx, 2); - ctx->bi_radix->comps[0] = 0; - ctx->bi_radix->comps[1] = 1; - bi_permanent(ctx->bi_radix); - return ctx; -} - -/** - * @brief Close the bigint context and free any resources. - * - * Free up any used memory - a check is done if all objects were not - * properly freed. - * @param ctx [in] The bigint session context. - */ -void bi_terminate(BI_CTX *ctx) -{ - bigint *p, *pn; - - bi_depermanent(ctx->bi_radix); - bi_free(ctx, ctx->bi_radix); - - if (ctx->active_count != 0) - { -#ifdef CONFIG_SSL_FULL_MODE - printf("bi_terminate: there were %d un-freed bigints\n", - ctx->active_count); -#endif - abort(); - } - - for (p = ctx->free_list; p != NULL; p = pn) - { - pn = p->next; - free(p->comps); - free(p); - } - - free(ctx); -} - -/** - * @brief Increment the number of references to this object. - * It does not do a full copy. - * @param bi [in] The bigint to copy. - * @return A reference to the same bigint. - */ -bigint *bi_copy(bigint *bi) -{ - check(bi); - if (bi->refs != PERMANENT) - bi->refs++; - return bi; -} - -/** - * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it. - * - * For this object to be freed, bi_depermanent() must be called. - * @param bi [in] The bigint to be made permanent. - */ -void bi_permanent(bigint *bi) -{ - check(bi); - if (bi->refs != 1) - { -#ifdef CONFIG_SSL_FULL_MODE - printf("bi_permanent: refs was not 1\n"); -#endif - abort(); - } - - bi->refs = PERMANENT; -} - -/** - * @brief Take a permanent object and make it eligible for freedom. - * @param bi [in] The bigint to be made back to temporary. - */ -void bi_depermanent(bigint *bi) -{ - check(bi); - if (bi->refs != PERMANENT) - { -#ifdef CONFIG_SSL_FULL_MODE - printf("bi_depermanent: bigint was not permanent\n"); -#endif - abort(); - } - - bi->refs = 1; -} - -/** - * @brief Free a bigint object so it can be used again. - * - * The memory itself it not actually freed, just tagged as being available - * @param ctx [in] The bigint session context. - * @param bi [in] The bigint to be freed. - */ -void bi_free(BI_CTX *ctx, bigint *bi) -{ - check(bi); - if (bi->refs == PERMANENT) - { - return; - } - - if (--bi->refs > 0) - { - return; - } - - bi->next = ctx->free_list; - ctx->free_list = bi; - ctx->free_count++; - - if (--ctx->active_count < 0) - { -#ifdef CONFIG_SSL_FULL_MODE - printf("bi_free: active_count went negative " - "- double-freed bigint?\n"); -#endif - abort(); - } -} - -/** - * @brief Convert an (unsigned) integer into a bigint. - * @param ctx [in] The bigint session context. - * @param i [in] The (unsigned) integer to be converted. - * - */ -bigint *int_to_bi(BI_CTX *ctx, comp i) -{ - bigint *biR = alloc(ctx, 1); - biR->comps[0] = i; - return biR; -} - -/** - * @brief Do a full copy of the bigint object. - * @param ctx [in] The bigint session context. - * @param bi [in] The bigint object to be copied. - */ -bigint *bi_clone(BI_CTX *ctx, const bigint *bi) -{ - bigint *biR = alloc(ctx, bi->size); - check(bi); - memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE); - return biR; -} - -/** - * @brief Perform an addition operation between two bigints. - * @param ctx [in] The bigint session context. - * @param bia [in] A bigint. - * @param bib [in] Another bigint. - * @return The result of the addition. - */ -bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) -{ - int n; - comp carry = 0; - comp *pa, *pb; - - check(bia); - check(bib); - - n = max(bia->size, bib->size); - more_comps(bia, n+1); - more_comps(bib, n); - pa = bia->comps; - pb = bib->comps; - - do - { - comp sl, rl, cy1; - sl = *pa + *pb++; - rl = sl + carry; - cy1 = sl < *pa; - carry = cy1 | (rl < sl); - *pa++ = rl; - } while (--n != 0); - - *pa = carry; /* do overflow */ - bi_free(ctx, bib); - return trim(bia); -} - -/** - * @brief Perform a subtraction operation between two bigints. - * @param ctx [in] The bigint session context. - * @param bia [in] A bigint. - * @param bib [in] Another bigint. - * @param is_negative [out] If defined, indicates that the result was negative. - * is_negative may be null. - * @return The result of the subtraction. The result is always positive. - */ -bigint *bi_subtract(BI_CTX *ctx, - bigint *bia, bigint *bib, int *is_negative) -{ - int n = bia->size; - comp *pa, *pb, carry = 0; - - check(bia); - check(bib); - - more_comps(bib, n); - pa = bia->comps; - pb = bib->comps; - - do - { - comp sl, rl, cy1; - sl = *pa - *pb++; - rl = sl - carry; - cy1 = sl > *pa; - carry = cy1 | (rl > sl); - *pa++ = rl; - } while (--n != 0); - - if (is_negative) /* indicate a negative result */ - { - *is_negative = carry; - } - - bi_free(ctx, trim(bib)); /* put bib back to the way it was */ - return trim(bia); -} - -/** - * Perform a multiply between a bigint an an (unsigned) integer - */ -static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b) -{ - int j = 0, n = bia->size; - bigint *biR = alloc(ctx, n + 1); - comp carry = 0; - comp *r = biR->comps; - comp *a = bia->comps; - - check(bia); - - /* clear things to start with */ - memset(r, 0, ((n+1)*COMP_BYTE_SIZE)); - - do - { - long_comp tmp = *r + (long_comp)a[j]*b + carry; - *r++ = (comp)tmp; /* downsize */ - carry = (comp)(tmp >> COMP_BIT_SIZE); - } while (++j < n); - - *r = carry; - bi_free(ctx, bia); - return trim(biR); -} - -/** - * @brief Does both division and modulo calculations. - * - * Used extensively when doing classical reduction. - * @param ctx [in] The bigint session context. - * @param u [in] A bigint which is the numerator. - * @param v [in] Either the denominator or the modulus depending on the mode. - * @param is_mod [n] Determines if this is a normal division (0) or a reduction - * (1). - * @return The result of the division/reduction. - */ -bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) -{ - int n = v->size, m = u->size-n; - int j = 0, orig_u_size = u->size; - uint8_t mod_offset = ctx->mod_offset; - comp d; - bigint *quotient, *tmp_u; - comp q_dash; - - check(u); - check(v); - - /* if doing reduction and we are < mod, then return mod */ - if (is_mod && bi_compare(v, u) > 0) - { - bi_free(ctx, v); - return u; - } - - quotient = alloc(ctx, m+1); - tmp_u = alloc(ctx, n+1); - v = trim(v); /* make sure we have no leading 0's */ - d = (comp)((long_comp)COMP_RADIX/(V1+1)); - - /* clear things to start with */ - memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE)); - - /* normalise */ - if (d > 1) - { - u = bi_int_multiply(ctx, u, d); - - if (is_mod) - { - v = ctx->bi_normalised_mod[mod_offset]; - } - else - { - v = bi_int_multiply(ctx, v, d); - } - } - - if (orig_u_size == u->size) /* new digit position u0 */ - { - more_comps(u, orig_u_size + 1); - } - - do - { - /* get a temporary short version of u */ - memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE); - - /* calculate q' */ - if (U(0) == V1) - { - q_dash = COMP_RADIX-1; - } - else - { - q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); - } - - if (v->size > 1 && V2) - { - /* we are implementing the following: - if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - - q_dash*V1)*COMP_RADIX) + U(2))) ... */ - comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - - (long_comp)q_dash*V1); - if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) - { - q_dash--; - } - } - - /* multiply and subtract */ - if (q_dash) - { - int is_negative; - tmp_u = bi_subtract(ctx, tmp_u, - bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative); - more_comps(tmp_u, n+1); - - Q(j) = q_dash; - - /* add back */ - if (is_negative) - { - Q(j)--; - tmp_u = bi_add(ctx, tmp_u, bi_copy(v)); - - /* lop off the carry */ - tmp_u->size--; - v->size--; - } - } - else - { - Q(j) = 0; - } - - /* copy back to u */ - memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE); - } while (++j <= m); - - bi_free(ctx, tmp_u); - bi_free(ctx, v); - - if (is_mod) /* get the remainder */ - { - bi_free(ctx, quotient); - return bi_int_divide(ctx, trim(u), d); - } - else /* get the quotient */ - { - bi_free(ctx, u); - return trim(quotient); - } -} - -/* - * Perform an integer divide on a bigint. - */ -static bigint *bi_int_divide(BI_CTX *ctx __unused, bigint *biR, comp denom) -{ - int i = biR->size - 1; - long_comp r = 0; - - check(biR); - - do - { - r = (r<comps[i]; - biR->comps[i] = (comp)(r / denom); - r %= denom; - } while (--i != 0); - - return trim(biR); -} - -#ifdef CONFIG_BIGINT_MONTGOMERY -/** - * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1, - * where B^-1(B-1) mod N=1. Actually, only the least significant part of - * N' is needed, hence the definition N0'=N' mod b. We reproduce below the - * simple algorithm from an article by Dusse and Kaliski to efficiently - * find N0' from N0 and b */ -static comp modular_inverse(bigint *bim) -{ - int i; - comp t = 1; - comp two_2_i_minus_1 = 2; /* 2^(i-1) */ - long_comp two_2_i = 4; /* 2^i */ - comp N = bim->comps[0]; - - for (i = 2; i <= COMP_BIT_SIZE; i++) - { - if ((long_comp)N*t%two_2_i >= two_2_i_minus_1) - { - t += two_2_i_minus_1; - } - - two_2_i_minus_1 <<= 1; - two_2_i <<= 1; - } - - return (comp)(COMP_RADIX-t); -} -#endif - -#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \ - defined(CONFIG_BIGINT_MONTGOMERY) -/** - * Take each component and shift down (in terms of components) - */ -static bigint *comp_right_shift(bigint *biR, int num_shifts) -{ - int i = biR->size-num_shifts; - comp *x = biR->comps; - comp *y = &biR->comps[num_shifts]; - - check(biR); - - if (i <= 0) /* have we completely right shifted? */ - { - biR->comps[0] = 0; /* return 0 */ - biR->size = 1; - return biR; - } - - do - { - *x++ = *y++; - } while (--i > 0); - - biR->size -= num_shifts; - return biR; -} - -/** - * Take each component and shift it up (in terms of components) - */ -static bigint *comp_left_shift(bigint *biR, int num_shifts) -{ - int i = biR->size-1; - comp *x, *y; - - check(biR); - - if (num_shifts <= 0) - { - return biR; - } - - more_comps(biR, biR->size + num_shifts); - - x = &biR->comps[i+num_shifts]; - y = &biR->comps[i]; - - do - { - *x-- = *y--; - } while (i--); - - memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */ - return biR; -} -#endif - -/** - * @brief Allow a binary sequence to be imported as a bigint. - * @param ctx [in] The bigint session context. - * @param data [in] The data to be converted. - * @param size [in] The number of bytes of data. - * @return A bigint representing this data. - */ -bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size) -{ - bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE); - int i, j = 0, offset = 0; - - memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE); - - for (i = size-1; i >= 0; i--) - { - biR->comps[offset] += data[i] << (j*8); - - if (++j == COMP_BYTE_SIZE) - { - j = 0; - offset ++; - } - } - - return trim(biR); -} - -#ifdef CONFIG_SSL_FULL_MODE -/** - * @brief The testharness uses this code to import text hex-streams and - * convert them into bigints. - * @param ctx [in] The bigint session context. - * @param data [in] A string consisting of hex characters. The characters must - * be in upper case. - * @return A bigint representing this data. - */ -bigint *bi_str_import(BI_CTX *ctx, const char *data) -{ - int size = strlen(data); - bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES); - int i, j = 0, offset = 0; - memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE); - - for (i = size-1; i >= 0; i--) - { - int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10); - biR->comps[offset] += num << (j*4); - - if (++j == COMP_NUM_NIBBLES) - { - j = 0; - offset ++; - } - } - - return biR; -} - -void bi_print(const char *label, bigint *x) -{ - int i, j; - - if (x == NULL) - { - printf("%s: (null)\n", label); - return; - } - - printf("%s: (size %d)\n", label, x->size); - for (i = x->size-1; i >= 0; i--) - { - for (j = COMP_NUM_NIBBLES-1; j >= 0; j--) - { - comp mask = 0x0f << (j*4); - comp num = (x->comps[i] & mask) >> (j*4); - putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout); - } - } - - printf("\n"); -} -#endif - -/** - * @brief Take a bigint and convert it into a byte sequence. - * - * This is useful after a decrypt operation. - * @param ctx [in] The bigint session context. - * @param x [in] The bigint to be converted. - * @param data [out] The converted data as a byte stream. - * @param size [in] The maximum size of the byte stream. Unused bytes will be - * zeroed. - */ -void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) -{ - int i, j, k = size-1; - - check(x); - memset(data, 0, size); /* ensure all leading 0's are cleared */ - - for (i = 0; i < x->size; i++) - { - for (j = 0; j < COMP_BYTE_SIZE; j++) - { - comp mask = 0xff << (j*8); - int num = (x->comps[i] & mask) >> (j*8); - data[k--] = num; - - if (k < 0) - { - break; - } - } - } - - bi_free(ctx, x); -} - -/** - * @brief Pre-calculate some of the expensive steps in reduction. - * - * This function should only be called once (normally when a session starts). - * When the session is over, bi_free_mod() should be called. bi_mod_power() - * relies on this function being called. - * @param ctx [in] The bigint session context. - * @param bim [in] The bigint modulus that will be used. - * @param mod_offset [in] There are three moduluii that can be stored - the - * standard modulus, and its two primes p and q. This offset refers to which - * modulus we are referring to. - * @see bi_free_mod(), bi_mod_power(). - */ -void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) -{ - int k = bim->size; - comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1)); -#ifdef CONFIG_BIGINT_MONTGOMERY - bigint *R, *R2; -#endif - - ctx->bi_mod[mod_offset] = bim; - bi_permanent(ctx->bi_mod[mod_offset]); - ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d); - bi_permanent(ctx->bi_normalised_mod[mod_offset]); - -#if defined(CONFIG_BIGINT_MONTGOMERY) - /* set montgomery variables */ - R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1); /* R */ - R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1); /* R^2 */ - ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */ - ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */ - - bi_permanent(ctx->bi_RR_mod_m[mod_offset]); - bi_permanent(ctx->bi_R_mod_m[mod_offset]); - - ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]); - -#elif defined (CONFIG_BIGINT_BARRETT) - ctx->bi_mu[mod_offset] = - bi_divide(ctx, comp_left_shift( - bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0); - bi_permanent(ctx->bi_mu[mod_offset]); -#endif -} - -/** - * @brief Used when cleaning various bigints at the end of a session. - * @param ctx [in] The bigint session context. - * @param mod_offset [in] The offset to use. - * @see bi_set_mod(). - */ -void bi_free_mod(BI_CTX *ctx, int mod_offset) -{ - bi_depermanent(ctx->bi_mod[mod_offset]); - bi_free(ctx, ctx->bi_mod[mod_offset]); -#if defined (CONFIG_BIGINT_MONTGOMERY) - bi_depermanent(ctx->bi_RR_mod_m[mod_offset]); - bi_depermanent(ctx->bi_R_mod_m[mod_offset]); - bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]); - bi_free(ctx, ctx->bi_R_mod_m[mod_offset]); -#elif defined(CONFIG_BIGINT_BARRETT) - bi_depermanent(ctx->bi_mu[mod_offset]); - bi_free(ctx, ctx->bi_mu[mod_offset]); -#endif - bi_depermanent(ctx->bi_normalised_mod[mod_offset]); - bi_free(ctx, ctx->bi_normalised_mod[mod_offset]); -} - -/** - * Perform a standard multiplication between two bigints. - */ -static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) -{ - int i, j, i_plus_j; - int n = bia->size; - int t = bib->size; - bigint *biR = alloc(ctx, n + t); - comp *sr = biR->comps; - comp *sa = bia->comps; - comp *sb = bib->comps; - - check(bia); - check(bib); - - /* clear things to start with */ - memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE)); - i = 0; - - do - { - comp carry = 0; - comp b = *sb++; - i_plus_j = i; - j = 0; - - do - { - long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry; - sr[i_plus_j++] = (comp)tmp; /* downsize */ - carry = (comp)(tmp >> COMP_BIT_SIZE); - } while (++j < n); - - sr[i_plus_j] = carry; - } while (++i < t); - - bi_free(ctx, bia); - bi_free(ctx, bib); - return trim(biR); -} - -#ifdef CONFIG_BIGINT_KARATSUBA -/* - * Karatsuba improves on regular multiplication due to only 3 multiplications - * being done instead of 4. The additional additions/subtractions are O(N) - * rather than O(N^2) and so for big numbers it saves on a few operations - */ -static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square) -{ - bigint *x0, *x1; - bigint *p0, *p1, *p2; - int m; - - if (is_square) - { - m = (bia->size + 1)/2; - } - else - { - m = (max(bia->size, bib->size) + 1)/2; - } - - x0 = bi_clone(ctx, bia); - x0->size = m; - x1 = bi_clone(ctx, bia); - comp_right_shift(x1, m); - bi_free(ctx, bia); - - /* work out the 3 partial products */ - if (is_square) - { - p0 = bi_square(ctx, bi_copy(x0)); - p2 = bi_square(ctx, bi_copy(x1)); - p1 = bi_square(ctx, bi_add(ctx, x0, x1)); - } - else /* normal multiply */ - { - bigint *y0, *y1; - y0 = bi_clone(ctx, bib); - y0->size = m; - y1 = bi_clone(ctx, bib); - comp_right_shift(y1, m); - bi_free(ctx, bib); - - p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0)); - p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1)); - p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1)); - } - - p1 = bi_subtract(ctx, - bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL); - - comp_left_shift(p1, m); - comp_left_shift(p2, 2*m); - return bi_add(ctx, p1, bi_add(ctx, p0, p2)); -} -#endif - -/** - * @brief Perform a multiplication operation between two bigints. - * @param ctx [in] The bigint session context. - * @param bia [in] A bigint. - * @param bib [in] Another bigint. - * @return The result of the multiplication. - */ -bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) -{ - check(bia); - check(bib); - -#ifdef CONFIG_BIGINT_KARATSUBA - if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH) - { - return regular_multiply(ctx, bia, bib); - } - - return karatsuba(ctx, bia, bib, 0); -#else - return regular_multiply(ctx, bia, bib); -#endif -} - -#ifdef CONFIG_BIGINT_SQUARE -/* - * Perform the actual square operion. It takes into account overflow. - */ -static bigint *regular_square(BI_CTX *ctx, bigint *bi) -{ - int t = bi->size; - int i = 0, j; - bigint *biR = alloc(ctx, t*2); - comp *w = biR->comps; - comp *x = bi->comps; - comp carry; - - memset(w, 0, biR->size*COMP_BYTE_SIZE); - - do - { - long_comp tmp = w[2*i] + (long_comp)x[i]*x[i]; - comp u = 0; - w[2*i] = (comp)tmp; - carry = (comp)(tmp >> COMP_BIT_SIZE); - - for (j = i+1; j < t; j++) - { - long_comp xx = (long_comp)x[i]*x[j]; - long_comp blob = (long_comp)w[i+j]+carry; - - if (u) /* previous overflow */ - { - blob += COMP_RADIX; - } - - u = 0; - if (xx & COMP_BIG_MSB) /* check for overflow */ - { - u = 1; - } - - tmp = 2*xx + blob; - w[i+j] = (comp)tmp; - carry = (comp)(tmp >> COMP_BIT_SIZE); - } - - w[i+t] += carry; - - if (u) - { - w[i+t+1] = 1; /* add carry */ - } - } while (++i < t); - - bi_free(ctx, bi); - return trim(biR); -} - -/** - * @brief Perform a square operation on a bigint. - * @param ctx [in] The bigint session context. - * @param bia [in] A bigint. - * @return The result of the multiplication. - */ -bigint *bi_square(BI_CTX *ctx, bigint *bia) -{ - check(bia); - -#ifdef CONFIG_BIGINT_KARATSUBA - if (bia->size < SQU_KARATSUBA_THRESH) - { - return regular_square(ctx, bia); - } - - return karatsuba(ctx, bia, NULL, 1); -#else - return regular_square(ctx, bia); -#endif -} -#endif - -/** - * @brief Compare two bigints. - * @param bia [in] A bigint. - * @param bib [in] Another bigint. - * @return -1 if smaller, 1 if larger and 0 if equal. - */ -int bi_compare(bigint *bia, bigint *bib) -{ - int r, i; - - check(bia); - check(bib); - - if (bia->size > bib->size) - r = 1; - else if (bia->size < bib->size) - r = -1; - else - { - comp *a = bia->comps; - comp *b = bib->comps; - - /* Same number of components. Compare starting from the high end - * and working down. */ - r = 0; - i = bia->size - 1; - - do - { - if (a[i] > b[i]) - { - r = 1; - break; - } - else if (a[i] < b[i]) - { - r = -1; - break; - } - } while (--i >= 0); - } - - return r; -} - -/* - * Allocate and zero more components. Does not consume bi. - */ -static void more_comps(bigint *bi, int n) -{ - if (n > bi->max_comps) - { - bi->max_comps = max(bi->max_comps * 2, n); - bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE); - } - - if (n > bi->size) - { - memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE); - } - - bi->size = n; -} - -/* - * Make a new empty bigint. It may just use an old one if one is available. - * Otherwise get one off the heap. - */ -static bigint *alloc(BI_CTX *ctx, int size) -{ - bigint *biR; - - /* Can we recycle an old bigint? */ - if (ctx->free_list != NULL) - { - biR = ctx->free_list; - ctx->free_list = biR->next; - ctx->free_count--; - - if (biR->refs != 0) - { -#ifdef CONFIG_SSL_FULL_MODE - printf("alloc: refs was not 0\n"); -#endif - abort(); /* create a stack trace from a core dump */ - } - - more_comps(biR, size); - } - else - { - /* No free bigints available - create a new one. */ - biR = (bigint *)malloc(sizeof(bigint)); - biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE); - biR->max_comps = size; /* give some space to spare */ - } - - biR->size = size; - biR->refs = 1; - biR->next = NULL; - ctx->active_count++; - return biR; -} - -/* - * Work out the highest '1' bit in an exponent. Used when doing sliding-window - * exponentiation. - */ -static int find_max_exp_index(bigint *biexp) -{ - int i = COMP_BIT_SIZE-1; - comp shift = COMP_RADIX/2; - comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */ - - check(biexp); - - do - { - if (test & shift) - { - return i+(biexp->size-1)*COMP_BIT_SIZE; - } - - shift >>= 1; - } while (--i != 0); - - return -1; /* error - must have been a leading 0 */ -} - -/* - * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window - * exponentiation. - */ -static int exp_bit_is_one(bigint *biexp, int offset) -{ - comp test = biexp->comps[offset / COMP_BIT_SIZE]; - int num_shifts = offset % COMP_BIT_SIZE; - comp shift = 1; - int i; - - check(biexp); - - for (i = 0; i < num_shifts; i++) - { - shift <<= 1; - } - - return test & shift; -} - -#ifdef CONFIG_BIGINT_CHECK_ON -/* - * Perform a sanity check on bi. - */ -static void check(const bigint *bi) -{ - if (bi->refs <= 0) - { - printf("check: zero or negative refs in bigint\n"); - abort(); - } - - if (bi->next != NULL) - { - printf("check: attempt to use a bigint from " - "the free list\n"); - abort(); - } -} -#endif - -/* - * Delete any leading 0's (and allow for 0). - */ -static bigint *trim(bigint *bi) -{ - check(bi); - - while (bi->comps[bi->size-1] == 0 && bi->size > 1) - { - bi->size--; - } - - return bi; -} - -#if defined(CONFIG_BIGINT_MONTGOMERY) -/** - * @brief Perform a single montgomery reduction. - * @param ctx [in] The bigint session context. - * @param bixy [in] A bigint. - * @return The result of the montgomery reduction. - */ -bigint *bi_mont(BI_CTX *ctx, bigint *bixy) -{ - int i = 0, n; - uint8_t mod_offset = ctx->mod_offset; - bigint *bim = ctx->bi_mod[mod_offset]; - comp mod_inv = ctx->N0_dash[mod_offset]; - - check(bixy); - - if (ctx->use_classical) /* just use classical instead */ - { - return bi_mod(ctx, bixy); - } - - n = bim->size; - - do - { - bixy = bi_add(ctx, bixy, comp_left_shift( - bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i)); - } while (++i < n); - - comp_right_shift(bixy, n); - - if (bi_compare(bixy, bim) >= 0) - { - bixy = bi_subtract(ctx, bixy, bim, NULL); - } - - return bixy; -} - -#elif defined(CONFIG_BIGINT_BARRETT) -/* - * Stomp on the most significant components to give the illusion of a "mod base - * radix" operation - */ -static bigint *comp_mod(bigint *bi, int mod) -{ - check(bi); - - if (bi->size > mod) - { - bi->size = mod; - } - - return bi; -} - -/* - * Barrett reduction has no need for some parts of the product, so ignore bits - * of the multiply. This routine gives Barrett its big performance - * improvements over Classical/Montgomery reduction methods. - */ -static bigint *partial_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, - int inner_partial, int outer_partial) -{ - int i = 0, j, n = bia->size, t = bib->size; - bigint *biR; - comp carry; - comp *sr, *sa, *sb; - - check(bia); - check(bib); - - biR = alloc(ctx, n + t); - sa = bia->comps; - sb = bib->comps; - sr = biR->comps; - - if (inner_partial) - { - memset(sr, 0, inner_partial*COMP_BYTE_SIZE); - } - else /* outer partial */ - { - if (n < outer_partial || t < outer_partial) /* should we bother? */ - { - bi_free(ctx, bia); - bi_free(ctx, bib); - biR->comps[0] = 0; /* return 0 */ - biR->size = 1; - return biR; - } - - memset(&sr[outer_partial], 0, (n+t-outer_partial)*COMP_BYTE_SIZE); - } - - do - { - comp *a = sa; - comp b = *sb++; - long_comp tmp; - int i_plus_j = i; - carry = 0; - j = n; - - if (outer_partial && i_plus_j < outer_partial) - { - i_plus_j = outer_partial; - a = &sa[outer_partial-i]; - j = n-(outer_partial-i); - } - - do - { - if (inner_partial && i_plus_j >= inner_partial) - { - break; - } - - tmp = sr[i_plus_j] + ((long_comp)*a++)*b + carry; - sr[i_plus_j++] = (comp)tmp; /* downsize */ - carry = (comp)(tmp >> COMP_BIT_SIZE); - } while (--j != 0); - - sr[i_plus_j] = carry; - } while (++i < t); - - bi_free(ctx, bia); - bi_free(ctx, bib); - return trim(biR); -} - -/** - * @brief Perform a single Barrett reduction. - * @param ctx [in] The bigint session context. - * @param bi [in] A bigint. - * @return The result of the Barrett reduction. - */ -bigint *bi_barrett(BI_CTX *ctx, bigint *bi) -{ - bigint *q1, *q2, *q3, *r1, *r2, *r; - uint8_t mod_offset = ctx->mod_offset; - bigint *bim = ctx->bi_mod[mod_offset]; - int k = bim->size; - - check(bi); - check(bim); - - /* use Classical method instead - Barrett cannot help here */ - if (bi->size > k*2) - { - return bi_mod(ctx, bi); - } - - q1 = comp_right_shift(bi_clone(ctx, bi), k-1); - - /* do outer partial multiply */ - q2 = partial_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); - q3 = comp_right_shift(q2, k+1); - r1 = comp_mod(bi, k+1); - - /* do inner partial multiply */ - r2 = comp_mod(partial_multiply(ctx, q3, bim, k+1, 0), k+1); - r = bi_subtract(ctx, r1, r2, NULL); - - /* if (r >= m) r = r - m; */ - if (bi_compare(r, bim) >= 0) - { - r = bi_subtract(ctx, r, bim, NULL); - } - - return r; -} -#endif /* CONFIG_BIGINT_BARRETT */ - -#ifdef CONFIG_BIGINT_SLIDING_WINDOW -/* - * Work out g1, g3, g5, g7... etc for the sliding-window algorithm - */ -static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) -{ - int k = 1, i; - bigint *g2; - - for (i = 0; i < window-1; i++) /* compute 2^(window-1) */ - { - k <<= 1; - } - - ctx->g = (bigint **)malloc(k*sizeof(bigint *)); - ctx->g[0] = bi_clone(ctx, g1); - bi_permanent(ctx->g[0]); - g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */ - - for (i = 1; i < k; i++) - { - ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2))); - bi_permanent(ctx->g[i]); - } - - bi_free(ctx, g2); - ctx->window = k; -} -#endif - -/** - * @brief Perform a modular exponentiation. - * - * This function requires bi_set_mod() to have been called previously. This is - * one of the optimisations used for performance. - * @param ctx [in] The bigint session context. - * @param bi [in] The bigint on which to perform the mod power operation. - * @param biexp [in] The bigint exponent. - * @see bi_set_mod(). - */ -bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) -{ - int i = find_max_exp_index(biexp), j, window_size = 1; - bigint *biR = int_to_bi(ctx, 1); - -#if defined(CONFIG_BIGINT_MONTGOMERY) - uint8_t mod_offset = ctx->mod_offset; - if (!ctx->use_classical) - { - /* preconvert */ - bi = bi_mont(ctx, - bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */ - bi_free(ctx, biR); - biR = ctx->bi_R_mod_m[mod_offset]; /* A */ - } -#endif - - check(bi); - check(biexp); - -#ifdef CONFIG_BIGINT_SLIDING_WINDOW - for (j = i; j > 32; j /= 5) /* work out an optimum size */ - window_size++; - - /* work out the slide constants */ - precompute_slide_window(ctx, window_size, bi); -#else /* just one constant */ - ctx->g = (bigint **)malloc(sizeof(bigint *)); - ctx->g[0] = bi_clone(ctx, bi); - ctx->window = 1; - bi_permanent(ctx->g[0]); -#endif - - /* if sliding-window is off, then only one bit will be done at a time and - * will reduce to standard left-to-right exponentiation */ - do - { - if (exp_bit_is_one(biexp, i)) - { - int l = i-window_size+1; - int part_exp = 0; - - if (l < 0) /* LSB of exponent will always be 1 */ - l = 0; - else - { - while (exp_bit_is_one(biexp, l) == 0) - l++; /* go back up */ - } - - /* build up the section of the exponent */ - for (j = i; j >= l; j--) - { - biR = bi_residue(ctx, bi_square(ctx, biR)); - if (exp_bit_is_one(biexp, j)) - part_exp++; - - if (j != l) - part_exp <<= 1; - } - - part_exp = (part_exp-1)/2; /* adjust for array */ - biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp])); - i = l-1; - } - else /* square it */ - { - biR = bi_residue(ctx, bi_square(ctx, biR)); - i--; - } - } while (i >= 0); - - /* cleanup */ - for (i = 0; i < ctx->window; i++) - { - bi_depermanent(ctx->g[i]); - bi_free(ctx, ctx->g[i]); - } - - free(ctx->g); - bi_free(ctx, bi); - bi_free(ctx, biexp); -#if defined CONFIG_BIGINT_MONTGOMERY - return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */ -#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */ - return biR; -#endif -} - -#ifdef CONFIG_SSL_CERT_VERIFICATION -/** - * @brief Perform a modular exponentiation using a temporary modulus. - * - * We need this function to check the signatures of certificates. The modulus - * of this function is temporary as it's just used for authentication. - * @param ctx [in] The bigint session context. - * @param bi [in] The bigint to perform the exp/mod. - * @param bim [in] The temporary modulus. - * @param biexp [in] The bigint exponent. - * @see bi_set_mod(). - */ -bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp) -{ - bigint *biR, *tmp_biR; - - /* Set up a temporary bigint context and transfer what we need between - * them. We need to do this since we want to keep the original modulus - * which is already in this context. This operation is only called when - * doing peer verification, and so is not expensive :-) */ - BI_CTX *tmp_ctx = bi_initialize(); - bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET); - tmp_biR = bi_mod_power(tmp_ctx, - bi_clone(tmp_ctx, bi), - bi_clone(tmp_ctx, biexp)); - biR = bi_clone(ctx, tmp_biR); - bi_free(tmp_ctx, tmp_biR); - bi_free_mod(tmp_ctx, BIGINT_M_OFFSET); - bi_terminate(tmp_ctx); - - bi_free(ctx, bi); - bi_free(ctx, bim); - bi_free(ctx, biexp); - return biR; -} -#endif -/** @} */ diff --git a/roms/ipxe/src/crypto/axtls/bigint.h b/roms/ipxe/src/crypto/axtls/bigint.h index f5f335311..1f38c53d6 100644 --- a/roms/ipxe/src/crypto/axtls/bigint.h +++ b/roms/ipxe/src/crypto/axtls/bigint.h @@ -1,44 +1,43 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * 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. + * All rights reserved. * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * 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_LICENCE ( GPL2_OR_LATER ); - #ifndef BIGINT_HEADER #define BIGINT_HEADER -/* 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 - -#include "os_port.h" -#include "bigint_impl.h" +#include "crypto.h" -#ifndef CONFIG_BIGINT_CHECK_ON -#define check(A) /**< disappears in normal production mode */ -#endif 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); @@ -90,4 +89,11 @@ bigint *bi_square(BI_CTX *ctx, bigint *bi); #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/roms/ipxe/src/crypto/axtls/bigint_impl.h b/roms/ipxe/src/crypto/axtls/bigint_impl.h index 762a7ccbb..09d8550ea 100644 --- a/roms/ipxe/src/crypto/axtls/bigint_impl.h +++ b/roms/ipxe/src/crypto/axtls/bigint_impl.h @@ -1,19 +1,31 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * 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.1 of the License, or - * (at your option) any later version. + * All rights reserved. * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * 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 @@ -30,20 +42,39 @@ #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_BIG_MSB 0x8000000000000000i64 +#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64 #else #define COMP_RADIX 4294967296ULL /**< Max component + 1 */ -#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */ +#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 @@ -97,9 +128,4 @@ typedef struct /**< A big integer "session" context. */ #define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ -#define V1 v->comps[v->size-1] /**< v1 for division */ -#define V2 v->comps[v->size-2] /**< v2 for division */ -#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ -#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ - #endif diff --git a/roms/ipxe/src/crypto/axtls/config.h b/roms/ipxe/src/crypto/axtls/config.h new file mode 100644 index 000000000..32fa3bf03 --- /dev/null +++ b/roms/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/roms/ipxe/src/crypto/axtls/crypto.h b/roms/ipxe/src/crypto/axtls/crypto.h index a9893cf35..2c4cda4de 100644 --- a/roms/ipxe/src/crypto/axtls/crypto.h +++ b/roms/ipxe/src/crypto/axtls/crypto.h @@ -1,23 +1,33 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * 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. + * All rights reserved. * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * 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_LICENCE ( GPL2_OR_LATER ); - /** * @file crypto.h */ @@ -29,20 +39,40 @@ FILE_LICENCE ( GPL2_OR_LATER ); 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[16]; + uint8_t iv[AES_IV_SIZE]; } AES_CTX; typedef enum @@ -57,8 +87,6 @@ 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); -void AES_encrypt(const AES_CTX *ctx, uint32_t *data); -void AES_decrypt(const AES_CTX *ctx, uint32_t *data); /************************************************************************** * RC4 declarations @@ -66,7 +94,7 @@ void AES_decrypt(const AES_CTX *ctx, uint32_t *data); typedef struct { - int x, y, m[256]; + uint8_t x, y, m[256]; } RC4_CTX; void RC4_setup(RC4_CTX *s, const uint8_t *key, int length); @@ -84,22 +112,38 @@ void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length); */ 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 */ + 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 */ + uint8_t Message_Block[64]; /* 512-bit message blocks */ } SHA1_CTX; -void SHA1Init(SHA1_CTX *); -void SHA1Update(SHA1_CTX *, const uint8_t * msg, int len); -void SHA1Final(SHA1_CTX *, uint8_t *digest); +void SHA1_Init(SHA1_CTX *); +void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len); +void SHA1_Final(uint8_t *digest, SHA1_CTX *); /************************************************************************** - * MD5 declarations + * MD2 declarations **************************************************************************/ -/* MD5 context. */ +#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 @@ -110,9 +154,9 @@ typedef struct uint8_t buffer[64]; /* input buffer */ } MD5_CTX; -void MD5Init(MD5_CTX *); -void MD5Update(MD5_CTX *, const uint8_t *msg, int len); -void MD5Final(MD5_CTX *, uint8_t *digest); +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 @@ -122,19 +166,6 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, int key_len, uint8_t *digest); -/************************************************************************** - * RNG declarations - **************************************************************************/ -void RNG_initialize(const uint8_t *seed_buf, int size); -void RNG_terminate(void); -void get_random(int num_rand_bytes, uint8_t *rand_data); -//void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); - -#include -static inline void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) { - memset ( rand_data, 0x01, num_rand_bytes ); -} - /************************************************************************** * RSA declarations **************************************************************************/ @@ -152,7 +183,6 @@ typedef struct bigint *qInv; /* q^-1 mod p */ #endif int num_octets; - bigint *sig_m; /* signature modulus */ BI_CTX *bi_ctx; } RSA_CTX; @@ -175,125 +205,22 @@ 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); -#ifdef CONFIG_SSL_CERT_VERIFICATION -bigint *RSA_raw_sign_verify(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); +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 /************************************************************************** - * ASN1 declarations - **************************************************************************/ -#define X509_OK 0 -#define X509_NOT_OK -1 -#define X509_VFY_ERROR_NO_TRUSTED_CERT -2 -#define X509_VFY_ERROR_BAD_SIGNATURE -3 -#define X509_VFY_ERROR_NOT_YET_VALID -4 -#define X509_VFY_ERROR_EXPIRED -5 -#define X509_VFY_ERROR_SELF_SIGNED -6 -#define X509_VFY_ERROR_INVALID_CHAIN -7 -#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8 -#define X509_INVALID_PRIV_KEY -9 - -/* - * The Distinguished Name - */ -#define X509_NUM_DN_TYPES 3 -#define X509_COMMON_NAME 0 -#define X509_ORGANIZATION 1 -#define X509_ORGANIZATIONAL_TYPE 2 - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OID 0x06 -#define ASN1_PRINTABLE_STR 0x13 -#define ASN1_TELETEX_STR 0x14 -#define ASN1_IA5_STR 0x16 -#define ASN1_UTC_TIME 0x17 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 -#define ASN1_IMPLICIT_TAG 0x80 -#define ASN1_EXPLICIT_TAG 0xa0 - -#define SALT_SIZE 8 - -struct _x509_ctx -{ - char *ca_cert_dn[X509_NUM_DN_TYPES]; - char *cert_dn[X509_NUM_DN_TYPES]; -#if defined(_WIN32_WCE) - long not_before; - long not_after; -#else - time_t not_before; - time_t not_after; -#endif - uint8_t *signature; - uint16_t sig_len; - uint8_t sig_type; - RSA_CTX *rsa_ctx; - bigint *digest; - struct _x509_ctx *next; -}; - -typedef struct _x509_ctx X509_CTX; - -#ifdef CONFIG_SSL_CERT_VERIFICATION -typedef struct -{ - X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS]; -} CA_CERT_CTX; -#endif - -int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx); -int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type); -int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type); -int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object); -int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx); -void x509_free(X509_CTX *x509_ctx); -#ifdef CONFIG_SSL_CERT_VERIFICATION -int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert); -const uint8_t *x509_get_signature(const uint8_t *asn1_signature, int *len); -#endif -#ifdef CONFIG_SSL_FULL_MODE -void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert); -void x509_display_error(int error); -#endif - -/************************************************************************** - * MISC declarations + * RNG declarations **************************************************************************/ - -extern const char * const unsupported_str; - -typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int); -typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key, - int key_len, uint8_t *digest); - -typedef struct -{ - uint8_t *pre_data; /* include the ssl record bytes */ - uint8_t *data; /* the regular ssl data */ - int max_len; - int index; -} BUF_MEM; - -BUF_MEM buf_new(void); -void buf_grow(BUF_MEM *bm, int len); -void buf_free(BUF_MEM *bm); -int get_file(const char *filename, uint8_t **buf); - -#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG) -void print_blob(const char *format, const uint8_t *data, int size, ...); -#else - #define print_blob(...) -#endif +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 } diff --git a/roms/ipxe/src/crypto/axtls/os_port.h b/roms/ipxe/src/crypto/axtls/os_port.h index babdbfad8..76313e204 100644 --- a/roms/ipxe/src/crypto/axtls/os_port.h +++ b/roms/ipxe/src/crypto/axtls/os_port.h @@ -1,61 +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. */ -#ifndef HEADER_OS_PORT_H -#define HEADER_OS_PORT_H - #include -#include -#include -#include -#include #include -#define STDCALL -#define EXP_FUNC -#define TTY_FLUSH() +/** 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 ) -/** crypto_misc.c has a bad #ifdef */ -static inline void close ( int fd __unused ) { - /* Do nothing */ +/** rsa.c uses alloca() */ +#define alloca( size ) __builtin_alloca ( size ) + +#include +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 ); } -typedef void FILE; - -static inline FILE * fopen ( const char *filename __unused, - const char *mode __unused ) { - return NULL; -} +/* Expose AES_encrypt() and AES_decrypt() in aes.o */ +#define aes 1 +#if OBJECT -static inline int fseek ( FILE *stream __unused, long offset __unused, - int whence __unused ) { - return -1; -} +struct aes_key_st; -static inline long ftell ( FILE *stream __unused ) { - return -1; -} +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 ); -static inline size_t fread ( void *ptr __unused, size_t size __unused, - size_t nmemb __unused, FILE *stream __unused ) { - return -1; +void axtls_aes_encrypt ( void *ctx, uint32_t *data ) { + AES_encrypt ( ctx, data ); } -static inline int fclose ( FILE *stream __unused ) { - return -1; +void axtls_aes_decrypt ( void *ctx, uint32_t *data ) { + AES_decrypt ( ctx, data ); } -#define CONFIG_SSL_CERT_VERIFICATION 1 -#define CONFIG_SSL_MAX_CERTS 1 -#define CONFIG_X509_MAX_CA_CERTS 1 -#define CONFIG_SSL_EXPIRY_TIME 24 -#define CONFIG_SSL_ENABLE_CLIENT 1 -#define CONFIG_BIGINT_CLASSICAL 1 +#endif +#undef aes #endif diff --git a/roms/ipxe/src/crypto/axtls/rsa.c b/roms/ipxe/src/crypto/axtls/rsa.c deleted file mode 100644 index 389eda577..000000000 --- a/roms/ipxe/src/crypto/axtls/rsa.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright(C) 2006 Cameron Rich - * - * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** - * Implements the RSA public encryption algorithm. Uses the bigint library to - * perform its calculations. - */ - -#include -#include -#include -#include -#include "crypto.h" - -#ifdef CONFIG_BIGINT_CRT -static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi); -#endif - -void RSA_priv_key_new(RSA_CTX **ctx, - const uint8_t *modulus, int mod_len, - const uint8_t *pub_exp, int pub_len, - const uint8_t *priv_exp, int priv_len -#if 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 - ) -{ - RSA_CTX *rsa_ctx; - BI_CTX *bi_ctx; - RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len); - rsa_ctx = *ctx; - bi_ctx = rsa_ctx->bi_ctx; - rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len); - bi_permanent(rsa_ctx->d); - -#ifdef CONFIG_BIGINT_CRT - rsa_ctx->p = bi_import(bi_ctx, p, p_len); - rsa_ctx->q = bi_import(bi_ctx, q, q_len); - rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len); - rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len); - rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len); - bi_permanent(rsa_ctx->dP); - bi_permanent(rsa_ctx->dQ); - bi_permanent(rsa_ctx->qInv); - bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET); - bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET); -#endif -} - -void RSA_pub_key_new(RSA_CTX **ctx, - const uint8_t *modulus, int mod_len, - const uint8_t *pub_exp, int pub_len) -{ - RSA_CTX *rsa_ctx; - BI_CTX *bi_ctx = bi_initialize(); - *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX)); - rsa_ctx = *ctx; - rsa_ctx->bi_ctx = bi_ctx; - rsa_ctx->num_octets = (mod_len & 0xFFF0); - rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len); - bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET); - rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len); - bi_permanent(rsa_ctx->e); -} - -/** - * Free up any RSA context resources. - */ -void RSA_free(RSA_CTX *rsa_ctx) -{ - BI_CTX *bi_ctx; - if (rsa_ctx == NULL) /* deal with ptrs that are null */ - return; - - bi_ctx = rsa_ctx->bi_ctx; - - bi_depermanent(rsa_ctx->e); - bi_free(bi_ctx, rsa_ctx->e); - bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET); - - if (rsa_ctx->d) - { - bi_depermanent(rsa_ctx->d); - bi_free(bi_ctx, rsa_ctx->d); -#ifdef CONFIG_BIGINT_CRT - bi_depermanent(rsa_ctx->dP); - bi_depermanent(rsa_ctx->dQ); - bi_depermanent(rsa_ctx->qInv); - bi_free(bi_ctx, rsa_ctx->dP); - bi_free(bi_ctx, rsa_ctx->dQ); - bi_free(bi_ctx, rsa_ctx->qInv); - bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET); - bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET); -#endif - } - - bi_terminate(bi_ctx); - free(rsa_ctx); -} - -/** - * @brief Use PKCS1.5 for decryption/verification. - * @param ctx [in] The context - * @param in_data [in] The data to encrypt (must be < modulus size-11) - * @param out_data [out] The encrypted data. - * @param is_decryption [in] Decryption or verify operation. - * @return The number of bytes that were originally encrypted. -1 on error. - * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125 - */ -int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, - uint8_t *out_data, int is_decryption) -{ - int byte_size = ctx->num_octets; - uint8_t *block; - int i, size; - bigint *decrypted_bi, *dat_bi; - - memset(out_data, 0, byte_size); /* initialise */ - - /* decrypt */ - dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size); -#ifdef CONFIG_SSL_CERT_VERIFICATION - decrypted_bi = is_decryption ? /* decrypt or verify? */ - RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi); -#else /* always a decryption */ - decrypted_bi = RSA_private(ctx, dat_bi); -#endif - - /* convert to a normal block */ - block = (uint8_t *)malloc(byte_size); - bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size); - - i = 10; /* start at the first possible non-padded byte */ - -#ifdef CONFIG_SSL_CERT_VERIFICATION - if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */ - { - while (block[i++] == 0xff && i < byte_size); - - if (block[i-2] != 0xff) - i = byte_size; /*ensure size is 0 */ - } - else /* PKCS1.5 encryption padding is random */ -#endif - { - while (block[i++] && i < byte_size); - } - size = byte_size - i; - - /* get only the bit we want */ - if (size > 0) - memcpy(out_data, &block[i], size); - - free(block); - return size ? size : -1; -} - -/** - * Performs m = c^d mod n - */ -bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg) -{ -#ifdef CONFIG_BIGINT_CRT - return bi_crt(c, bi_msg); -#else - BI_CTX *ctx = c->bi_ctx; - ctx->mod_offset = BIGINT_M_OFFSET; - return bi_mod_power(ctx, bi_msg, c->d); -#endif -} - -#ifdef CONFIG_BIGINT_CRT -/** - * Use the Chinese Remainder Theorem to quickly perform RSA decrypts. - * This should really be in bigint.c (and was at one stage), but needs - * access to the RSA_CTX context... - */ -static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi) -{ - BI_CTX *ctx = rsa->bi_ctx; - bigint *m1, *m2, *h; - - /* Montgomery has a condition the 0 < x, y < m and these products violate - * that condition. So disable Montgomery when using CRT */ -#if defined(CONFIG_BIGINT_MONTGOMERY) - ctx->use_classical = 1; -#endif - ctx->mod_offset = BIGINT_P_OFFSET; - m1 = bi_mod_power(ctx, bi_copy(bi), rsa->dP); - - ctx->mod_offset = BIGINT_Q_OFFSET; - m2 = bi_mod_power(ctx, bi, rsa->dQ); - - h = bi_subtract(ctx, bi_add(ctx, m1, rsa->p), bi_copy(m2), NULL); - h = bi_multiply(ctx, h, rsa->qInv); - ctx->mod_offset = BIGINT_P_OFFSET; - h = bi_residue(ctx, h); -#if defined(CONFIG_BIGINT_MONTGOMERY) - ctx->use_classical = 0; /* reset for any further operation */ -#endif - return bi_add(ctx, m2, bi_multiply(ctx, rsa->q, h)); -} -#endif - -#ifdef CONFIG_SSL_FULL_MODE -/** - * Used for diagnostics. - */ -void RSA_print(const RSA_CTX *rsa_ctx) -{ - if (rsa_ctx == NULL) - return; - - printf("----------------- RSA DEBUG ----------------\n"); - printf("Size:\t%d\n", rsa_ctx->num_octets); - bi_print("Modulus", rsa_ctx->m); - bi_print("Public Key", rsa_ctx->e); - bi_print("Private Key", rsa_ctx->d); -} -#endif - -#ifdef CONFIG_SSL_CERT_VERIFICATION -/** - * Performs c = m^e mod n - */ -bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg) -{ - c->bi_ctx->mod_offset = BIGINT_M_OFFSET; - return bi_mod_power(c->bi_ctx, bi_msg, c->e); -} - -/** - * Use PKCS1.5 for encryption/signing. - * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125 - */ -int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, - uint8_t *out_data, int is_signing) -{ - int byte_size = ctx->num_octets; - int num_pads_needed = byte_size-in_len-3; - bigint *dat_bi, *encrypt_bi; - - /* note: in_len+11 must be > byte_size */ - out_data[0] = 0; /* ensure encryption block is < modulus */ - - if (is_signing) - { - out_data[1] = 1; /* PKCS1.5 signing pads with "0xff"'s */ - memset(&out_data[2], 0xff, num_pads_needed); - } - else /* randomize the encryption padding with non-zero bytes */ - { - out_data[1] = 2; - get_random_NZ(num_pads_needed, &out_data[2]); - } - - out_data[2+num_pads_needed] = 0; - memcpy(&out_data[3+num_pads_needed], in_data, in_len); - - /* now encrypt it */ - dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size); - encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) : - RSA_public(ctx, dat_bi); - bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size); - return byte_size; -} - -#if 0 -/** - * Take a signature and decrypt it. - */ -bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, - bigint *modulus, bigint *pub_exp) -{ - uint8_t *block; - int i, size; - bigint *decrypted_bi, *dat_bi; - bigint *bir = NULL; - - block = (uint8_t *)malloc(sig_len); - - /* decrypt */ - dat_bi = bi_import(ctx, sig, sig_len); - ctx->mod_offset = BIGINT_M_OFFSET; - - /* convert to a normal block */ - decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp); - - bi_export(ctx, decrypted_bi, block, sig_len); - ctx->mod_offset = BIGINT_M_OFFSET; - - i = 10; /* start at the first possible non-padded byte */ - while (block[i++] && i < sig_len); - size = sig_len - i; - - /* get only the bit we want */ - if (size > 0) - { - int len; - const uint8_t *sig_ptr = x509_get_signature(&block[i], &len); - - if (sig_ptr) - { - bir = bi_import(ctx, sig_ptr, len); - } - } - - free(block); - return bir; -} -#endif - -#endif /* CONFIG_SSL_CERT_VERIFICATION */ diff --git a/roms/ipxe/src/crypto/axtls/sha1.c b/roms/ipxe/src/crypto/axtls/sha1.c deleted file mode 100644 index 9a42801f2..000000000 --- a/roms/ipxe/src/crypto/axtls/sha1.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright(C) 2006 Cameron Rich - * - * 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.1 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** - * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995. - * This code was originally taken from RFC3174 - */ - -#include -#include "crypto.h" - -/* - * Define the SHA1 circular left shift macro - */ -#define SHA1CircularShift(bits,word) \ - (((word) << (bits)) | ((word) >> (32-(bits)))) - -/* ----- static functions ----- */ -static void SHA1PadMessage(SHA1_CTX *ctx); -static void SHA1ProcessMessageBlock(SHA1_CTX *ctx); - -/** - * Initialize the SHA1 context - */ -void SHA1Init(SHA1_CTX *ctx) -{ - ctx->Length_Low = 0; - ctx->Length_High = 0; - ctx->Message_Block_Index = 0; - ctx->Intermediate_Hash[0] = 0x67452301; - ctx->Intermediate_Hash[1] = 0xEFCDAB89; - ctx->Intermediate_Hash[2] = 0x98BADCFE; - ctx->Intermediate_Hash[3] = 0x10325476; - ctx->Intermediate_Hash[4] = 0xC3D2E1F0; -} - -/** - * Accepts an array of octets as the next portion of the message. - */ -void SHA1Update(SHA1_CTX *ctx, const uint8_t *msg, int len) -{ - while (len--) - { - ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF); - - ctx->Length_Low += 8; - if (ctx->Length_Low == 0) - { - ctx->Length_High++; - } - - if (ctx->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(ctx); - } - - msg++; - } -} - -/** - * Return the 160-bit message digest into the user's array - */ -void SHA1Final(SHA1_CTX *ctx, uint8_t *digest) -{ - int i; - - SHA1PadMessage(ctx); - memset(ctx->Message_Block, 0, 64); - ctx->Length_Low = 0; /* and clear length */ - ctx->Length_High = 0; - - for (i = 0; i < SHA1_SIZE; i++) - { - digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ); - } -} - -/** - * Process the next 512 bits of the message stored in the array. - */ -static void SHA1ProcessMessageBlock(SHA1_CTX *ctx) -{ - const uint32_t K[] = { /* Constants defined in SHA-1 */ - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; /* Loop counter */ - uint32_t temp; /* Temporary word value */ - uint32_t W[80]; /* Word sequence */ - uint32_t A, B, C, D, E; /* Word buffers */ - - /* - * Initialize the first 16 words in the array W - */ - for (t = 0; t < 16; t++) - { - W[t] = ctx->Message_Block[t * 4] << 24; - W[t] |= ctx->Message_Block[t * 4 + 1] << 16; - W[t] |= ctx->Message_Block[t * 4 + 2] << 8; - W[t] |= ctx->Message_Block[t * 4 + 3]; - } - - for (t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = ctx->Intermediate_Hash[0]; - B = ctx->Intermediate_Hash[1]; - C = ctx->Intermediate_Hash[2]; - D = ctx->Intermediate_Hash[3]; - E = ctx->Intermediate_Hash[4]; - - for (t = 0; t < 20; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - - B = A; - A = temp; - } - - for (t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for (t = 40; t < 60; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for (t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - ctx->Intermediate_Hash[0] += A; - ctx->Intermediate_Hash[1] += B; - ctx->Intermediate_Hash[2] += C; - ctx->Intermediate_Hash[3] += D; - ctx->Intermediate_Hash[4] += E; - ctx->Message_Block_Index = 0; -} - -/* - * According to the standard, the message must be padded to an even - * 512 bits. The first padding bit must be a '1'. The last 64 - * bits represent the length of the original message. All bits in - * between should be 0. This function will pad the message - * according to those rules by filling the Message_Block array - * accordingly. It will also call the ProcessMessageBlock function - * provided appropriately. When it returns, it can be assumed that - * the message digest has been computed. - * - * @param ctx [in, out] The SHA1 context - */ -static void SHA1PadMessage(SHA1_CTX *ctx) -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second - * block. - */ - if (ctx->Message_Block_Index > 55) - { - ctx->Message_Block[ctx->Message_Block_Index++] = 0x80; - while(ctx->Message_Block_Index < 64) - { - ctx->Message_Block[ctx->Message_Block_Index++] = 0; - } - - SHA1ProcessMessageBlock(ctx); - - while (ctx->Message_Block_Index < 56) - { - ctx->Message_Block[ctx->Message_Block_Index++] = 0; - } - } - else - { - ctx->Message_Block[ctx->Message_Block_Index++] = 0x80; - while(ctx->Message_Block_Index < 56) - { - - ctx->Message_Block[ctx->Message_Block_Index++] = 0; - } - } - - /* - * Store the message length as the last 8 octets - */ - ctx->Message_Block[56] = ctx->Length_High >> 24; - ctx->Message_Block[57] = ctx->Length_High >> 16; - ctx->Message_Block[58] = ctx->Length_High >> 8; - ctx->Message_Block[59] = ctx->Length_High; - ctx->Message_Block[60] = ctx->Length_Low >> 24; - ctx->Message_Block[61] = ctx->Length_Low >> 16; - ctx->Message_Block[62] = ctx->Length_Low >> 8; - ctx->Message_Block[63] = ctx->Length_Low; - SHA1ProcessMessageBlock(ctx); -} diff --git a/roms/ipxe/src/crypto/axtls_aes.c b/roms/ipxe/src/crypto/axtls_aes.c index b73a57252..7f93c0ed7 100644 --- a/roms/ipxe/src/crypto/axtls_aes.c +++ b/roms/ipxe/src/crypto/axtls_aes.c @@ -13,13 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -119,7 +121,7 @@ static void aes_encrypt ( void *ctx, const void *src, void *dst, assert ( len == AES_BLOCKSIZE ); if ( aes_ctx->decrypting ) assert ( 0 ); - aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_encrypt ); + aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_encrypt ); } /** @@ -139,7 +141,7 @@ static void aes_decrypt ( void *ctx, const void *src, void *dst, AES_convert_key ( &aes_ctx->axtls_ctx ); aes_ctx->decrypting = 1; } - aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_decrypt ); + aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_decrypt ); } /** Basic AES algorithm */ diff --git a/roms/ipxe/src/crypto/axtls_sha1.c b/roms/ipxe/src/crypto/axtls_sha1.c deleted file mode 100644 index 3eb8912d3..000000000 --- a/roms/ipxe/src/crypto/axtls_sha1.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "crypto/axtls/crypto.h" -#include -#include - -static void sha1_init ( void *ctx ) { - SHA1Init ( ctx ); -} - -static void sha1_update ( void *ctx, const void *data, size_t len ) { - SHA1Update ( ctx, data, len ); -} - -static void sha1_final ( void *ctx, void *out ) { - SHA1Final ( ctx, out ); -} - -struct digest_algorithm sha1_algorithm = { - .name = "sha1", - .ctxsize = SHA1_CTX_SIZE, - .blocksize = 64, - .digestsize = SHA1_DIGEST_SIZE, - .init = sha1_init, - .update = sha1_update, - .final = sha1_final, -}; diff --git a/roms/ipxe/src/crypto/bigint.c b/roms/ipxe/src/crypto/bigint.c new file mode 100644 index 000000000..340128e2f --- /dev/null +++ b/roms/ipxe/src/crypto/bigint.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include + +/** @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/roms/ipxe/src/crypto/cbc.c b/roms/ipxe/src/crypto/cbc.c index c00ebb0a7..9bf0e8b49 100644 --- a/roms/ipxe/src/crypto/cbc.c +++ b/roms/ipxe/src/crypto/cbc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -87,13 +88,15 @@ void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len, 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; + uint8_t next_cbc_ctx[blocksize]; assert ( ( len % blocksize ) == 0 ); while ( len ) { + memcpy ( next_cbc_ctx, src, blocksize ); cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize ); cbc_xor ( cbc_ctx, dst, blocksize ); - memcpy ( cbc_ctx, src, blocksize ); + memcpy ( cbc_ctx, next_cbc_ctx, blocksize ); dst += blocksize; src += blocksize; len -= blocksize; diff --git a/roms/ipxe/src/crypto/chap.c b/roms/ipxe/src/crypto/chap.c index 492d22160..db64371c7 100644 --- a/roms/ipxe/src/crypto/chap.c +++ b/roms/ipxe/src/crypto/chap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/crypto/clientcert.c b/roms/ipxe/src/crypto/clientcert.c new file mode 100644 index 000000000..5ce1f6c1a --- /dev/null +++ b/roms/ipxe/src/crypto/clientcert.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include + +/** @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 privkey_setting __setting ( SETTING_CRYPTO ) = { + .name = "privkey", + .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, &privkey_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/roms/ipxe/src/crypto/cms.c b/roms/ipxe/src/crypto/cms.c new file mode 100644 index 000000000..c0c8d144f --- /dev/null +++ b/roms/ipxe/src/crypto/cms.c @@ -0,0 +1,705 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Cryptographic Message Syntax (PKCS #7) + * + * The format of CMS messages is defined in RFC 5652. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/roms/ipxe/src/crypto/crandom.c b/roms/ipxe/src/crypto/crandom.c deleted file mode 100644 index 1886f9b7e..000000000 --- a/roms/ipxe/src/crypto/crandom.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2009 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, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along 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 - * - * Cryptographically strong random number generator - * - * Currently the cryptographic part is not implemented, and this just - * uses random(). - */ - -#include -#include - -/** - * Get cryptographically strong random bytes - * - * @v buf Buffer in which to store random bytes - * @v len Number of random bytes to generate - * - * @b WARNING: This function is currently underimplemented, and does - * not give numbers any stronger than random()! - */ -void get_random_bytes ( void *buf, size_t len ) -{ - u8 *bufp = buf; - - /* - * Somewhat arbitrarily, choose the 0x00FF0000-masked byte - * returned by random() as having good entropy. PRNGs often - * don't provide good entropy in lower bits, and the top byte - * might show a pattern because of sign issues. - */ - - while ( len-- ) { - *bufp++ = ( random() >> 16 ) & 0xFF; - } -} diff --git a/roms/ipxe/src/crypto/crc32.c b/roms/ipxe/src/crypto/crc32.c index 71ec1d66c..cfef68c02 100644 --- a/roms/ipxe/src/crypto/crc32.c +++ b/roms/ipxe/src/crypto/crc32.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/crypto/crypto_null.c b/roms/ipxe/src/crypto/crypto_null.c index c9c32ae99..ba05f7269 100644 --- a/roms/ipxe/src/crypto/crypto_null.c +++ b/roms/ipxe/src/crypto/crypto_null.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -81,7 +82,56 @@ struct cipher_algorithm cipher_null = { .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/roms/ipxe/src/crypto/drbg.c b/roms/ipxe/src/crypto/drbg.c new file mode 100644 index 000000000..9e0175d25 --- /dev/null +++ b/roms/ipxe/src/crypto/drbg.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include +#include +#include + +/** + * 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/roms/ipxe/src/crypto/entropy.c b/roms/ipxe/src/crypto/entropy.c new file mode 100644 index 000000000..c7045840e --- /dev/null +++ b/roms/ipxe/src/crypto/entropy.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include +#include +#include +#include + +/* 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/roms/ipxe/src/crypto/hash_df.c b/roms/ipxe/src/crypto/hash_df.c new file mode 100644 index 000000000..adf1d87e4 --- /dev/null +++ b/roms/ipxe/src/crypto/hash_df.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include +#include +#include + +/** + * 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/roms/ipxe/src/crypto/hmac.c b/roms/ipxe/src/crypto/hmac.c index 6b61dc449..e9459198c 100644 --- a/roms/ipxe/src/crypto/hmac.c +++ b/roms/ipxe/src/crypto/hmac.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/crypto/hmac_drbg.c b/roms/ipxe/src/crypto/hmac_drbg.c new file mode 100644 index 000000000..1e5f732e2 --- /dev/null +++ b/roms/ipxe/src/crypto/hmac_drbg.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include +#include +#include +#include + +/** + * 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/roms/ipxe/src/crypto/md5.c b/roms/ipxe/src/crypto/md5.c index ef322ad2a..122c7d59e 100644 --- a/roms/ipxe/src/crypto/md5.c +++ b/roms/ipxe/src/crypto/md5.c @@ -1,234 +1,298 @@ -/* - * Cryptographic API. +/* + * Copyright (C) 2012 Michael Brown . * - * MD5 Message Digest Algorithm (RFC1321). + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. * - * Derived from cryptoapi implementation, originally based on the - * public domain implementation written by Colin Plumb in 1993. - * - * Reduced object size by around 50% compared to the original Linux - * version for use in Etherboot by Michael Brown. - * - * Copyright (c) Cryptoapi developers. - * Copyright (c) 2002 James Morris - * Copyright (c) 2006 Michael Brown - * - * This program is free software; you can redistribute it and/or modify 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 ); +/** @file + * + * MD5 algorithm + * + */ + #include #include #include +#include +#include #include +#include #include -struct md5_step { - u32 ( * f ) ( u32 b, u32 c, u32 d ); - u8 coefficient; - u8 constant; +/** 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 }; -static u32 f1(u32 b, u32 c, u32 d) -{ - return ( d ^ ( b & ( c ^ d ) ) ); +/** + * 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 ) ) ); } -static u32 f2(u32 b, u32 c, u32 d) -{ - return ( c ^ ( d & ( b ^ c ) ) ); +/** + * 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 ) ) ); } -static u32 f3(u32 b, u32 c, u32 d) -{ - return ( b ^ c ^ d ); +/** + * 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 ); } -static u32 f4(u32 b, u32 c, u32 d) -{ - return ( c ^ ( b | ~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) ) ); } -static struct md5_step md5_steps[4] = { - { - .f = f1, - .coefficient = 1, - .constant = 0, - }, - { - .f = f2, - .coefficient = 5, - .constant = 1, - }, - { - .f = f3, - .coefficient = 3, - .constant = 5, - }, - { - .f = f4, - .coefficient = 7, - .constant = 0, - } +/** 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; }; -static const u8 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 +/** 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 }, }; -static const u32 k[64] = { - 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, - 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, - 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, - 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, - 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, - 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, - 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, - 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, - 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, - 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, - 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, - 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, - 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, - 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, - 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, - 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL, -}; +/** + * Initialise MD5 algorithm + * + * @v ctx MD5 context + */ +static void md5_init ( void *ctx ) { + struct md5_context *context = ctx; -static void md5_transform(u32 *hash, const u32 *in) -{ - u32 a, b, c, d, f, g, temp; - int i; - struct md5_step *step; + 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; +} - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; +/** + * 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; - for ( i = 0 ; i < 64 ; i++ ) { - step = &md5_steps[i >> 4]; - f = step->f ( b, c, d ); - g = ( ( i * step->coefficient + step->constant ) & 0xf ); - temp = d; - d = c; - c = b; - a += ( f + k[i] + in[g] ); - a = ( ( a << r[i] ) | ( a >> ( 32-r[i] ) ) ); - b += a; - a = temp; - } + /* 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 ); - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; -} + 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 ) ); -/* XXX: this stuff can be optimized */ -static inline void le32_to_cpu_array(u32 *buf, unsigned int words) -{ - while (words--) { - le32_to_cpus(buf); - buf++; + /* 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]; } -} -static inline void cpu_to_le32_array(u32 *buf, unsigned int words) -{ - while (words--) { - cpu_to_le32s(buf); - buf++; + /* 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 ); } -} -static inline void md5_transform_helper(struct md5_ctx *ctx) -{ - le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); - md5_transform(ctx->hash, ctx->block); -} - -static void md5_init(void *context) -{ - struct md5_ctx *mctx = context; + /* 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] ); + } - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; + DBGC ( context, "MD5 digested:\n" ); + DBGC_HDA ( context, 0, &context->ddd.dd.digest, + sizeof ( context->ddd.dd.digest ) ); } -static void md5_update(void *context, const void *data, size_t len) -{ - struct md5_ctx *mctx = context; - const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); - - mctx->byte_count += len; +/** + * 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; - if (avail > len) { - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, len); - return; + /* 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 ); } +} - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, avail); +/** + * 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; - md5_transform_helper(mctx); - data += avail; - len -= avail; + /* Record length before pre-processing */ + len_bits = cpu_to_le64 ( ( ( uint64_t ) context->len ) * 8 ); - while (len >= sizeof(mctx->block)) { - memcpy(mctx->block, data, sizeof(mctx->block)); - md5_transform_helper(mctx); - data += sizeof(mctx->block); - len -= sizeof(mctx->block); - } + /* 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 ) ); - memcpy(mctx->block, data, len); -} - -static void md5_final(void *context, void *out) -{ - struct md5_ctx *mctx = context; - const unsigned int offset = mctx->byte_count & 0x3f; - char *p = (char *)mctx->block + offset; - int padding = 56 - (offset + 1); - - *p++ = 0x80; - if (padding < 0) { - memset(p, 0x00, padding + sizeof (u64)); - md5_transform_helper(mctx); - p = (char *)mctx->block; - padding = 56; - } + /* Append length (in bits) */ + md5_update ( ctx, &len_bits, sizeof ( len_bits ) ); + assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - memset(p, 0, padding); - mctx->block[14] = mctx->byte_count << 3; - mctx->block[15] = mctx->byte_count >> 29; - le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - - sizeof(u64)) / sizeof(u32)); - md5_transform(mctx->hash, mctx->block); - cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); - memcpy(out, mctx->hash, sizeof(mctx->hash)); - memset(mctx, 0, sizeof(*mctx)); + /* 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 = MD5_CTX_SIZE, - .blocksize = ( MD5_BLOCK_WORDS * 4 ), - .digestsize = MD5_DIGEST_SIZE, + .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/roms/ipxe/src/crypto/null_entropy.c b/roms/ipxe/src/crypto/null_entropy.c new file mode 100644 index 000000000..c56d5e76f --- /dev/null +++ b/roms/ipxe/src/crypto/null_entropy.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Nonexistent entropy source + * + * + * This source provides no entropy and must NOT be used in a + * security-sensitive environment. + */ + +#include + +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/roms/ipxe/src/crypto/ocsp.c b/roms/ipxe/src/crypto/ocsp.c new file mode 100644 index 000000000..ab75dea35 --- /dev/null +++ b/roms/ipxe/src/crypto/ocsp.c @@ -0,0 +1,824 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @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->uri_string ); + 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; +} + +/** + * Build OCSP URI string + * + * @v ocsp OCSP check + * @ret rc Return status code + */ +static int ocsp_uri_string ( struct ocsp_check *ocsp ) { + char *base_uri_string; + char *base64_request; + size_t base64_request_len; + size_t uri_string_len; + size_t prefix_len; + int rc; + + /* Sanity check */ + base_uri_string = ocsp->cert->extensions.auth_info.ocsp.uri; + if ( ! base_uri_string ) { + DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n", + ocsp, ocsp->cert->subject.name ); + rc = -ENOTTY; + goto err_no_uri; + } + + /* Base64-encode the request */ + base64_request_len = ( base64_encoded_len ( ocsp->request.builder.len ) + + 1 /* NUL */ ); + base64_request = malloc ( base64_request_len ); + if ( ! base64_request ) { + rc = -ENOMEM; + goto err_alloc_base64; + } + base64_encode ( ocsp->request.builder.data, ocsp->request.builder.len, + base64_request ); + + /* Allocate URI string */ + uri_string_len = ( strlen ( base_uri_string ) + 1 /* "/" */ + + uri_encode ( base64_request, NULL, 0, URI_FRAGMENT ) + + 1 /* NUL */ ); + ocsp->uri_string = malloc ( uri_string_len ); + if ( ! ocsp->uri_string ) { + rc = -ENOMEM; + goto err_alloc_uri; + } + + /* Construct URI string */ + prefix_len = snprintf ( ocsp->uri_string, uri_string_len, + "%s/", base_uri_string ); + uri_encode ( base64_request, ( ocsp->uri_string + prefix_len ), + ( uri_string_len - prefix_len ), URI_FRAGMENT ); + DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n", + ocsp, ocsp->cert->subject.name, ocsp->uri_string ); + + /* Free base64-encoded request */ + free ( base64_request ); + base64_request = NULL; + + return 0; + + err_alloc_uri: + free ( base64_request ); + err_alloc_base64: + err_no_uri: + return rc; +} + +/** + * 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; + + /* Build URI string */ + if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 ) + goto err_uri_string; + + return 0; + + err_uri_string: + err_request: + ocsp_put ( *ocsp ); + err_alloc: + *ocsp = NULL; + 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 + X509_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 - X509_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/roms/ipxe/src/crypto/random_nz.c b/roms/ipxe/src/crypto/random_nz.c new file mode 100644 index 000000000..f1d2e187d --- /dev/null +++ b/roms/ipxe/src/crypto/random_nz.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include + +/** + * 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/roms/ipxe/src/crypto/rbg.c b/roms/ipxe/src/crypto/rbg.c new file mode 100644 index 000000000..e2d06978c --- /dev/null +++ b/roms/ipxe/src/crypto/rbg.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @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 +#include +#include +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/crypto/rootcert.c b/roms/ipxe/src/crypto/rootcert.c new file mode 100644 index 000000000..30ca170f5 --- /dev/null +++ b/roms/ipxe/src/crypto/rootcert.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @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/roms/ipxe/src/crypto/rsa.c b/roms/ipxe/src/crypto/rsa.c new file mode 100644 index 000000000..1a5cf6cd5 --- /dev/null +++ b/roms/ipxe/src/crypto/rsa.c @@ -0,0 +1,642 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @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/roms/ipxe/src/crypto/sha1.c b/roms/ipxe/src/crypto/sha1.c new file mode 100644 index 000000000..e1bef669e --- /dev/null +++ b/roms/ipxe/src/crypto/sha1.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * SHA-1 algorithm + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/crypto/sha1extra.c b/roms/ipxe/src/crypto/sha1extra.c index 74445e9d1..cec0d35e5 100644 --- a/roms/ipxe/src/crypto/sha1extra.c +++ b/roms/ipxe/src/crypto/sha1extra.c @@ -13,11 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); +#include #include #include #include @@ -46,7 +48,7 @@ void prf_sha1 ( const void *key, size_t key_len, const char *label, 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_SIZE]; /* HMAC-SHA1 result */ + u8 out[SHA1_DIGEST_SIZE]; /* HMAC-SHA1 result */ u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */ const size_t label_len = strlen ( label ); @@ -67,14 +69,14 @@ void prf_sha1 ( const void *key, size_t key_len, const char *label, hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) ); hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out ); - if ( prf_len <= SHA1_SIZE ) { + if ( prf_len <= sizeof ( out ) ) { memcpy ( prf, out, prf_len ); break; } - memcpy ( prf, out, SHA1_SIZE ); - prf_len -= SHA1_SIZE; - prf += SHA1_SIZE; + memcpy ( prf, out, sizeof ( out ) ); + prf_len -= sizeof ( out ); + prf += sizeof ( out ); } } @@ -97,30 +99,31 @@ static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len, { u8 pass[pass_len]; /* modifiable passphrase */ u8 in[salt_len + 4]; /* input buffer to first round */ - u8 last[SHA1_SIZE]; /* output of round N, input of N+1 */ + 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, j; + 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, SHA1_SIZE ); + 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 < SHA1_SIZE; j++ ) { + for ( j = 0; j < sizeof ( last ); j++ ) { block[j] ^= last[j]; } next_in = last; - next_size = SHA1_SIZE; + next_size = sizeof ( last ); } } @@ -146,20 +149,20 @@ 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_SIZE - 1 ) / SHA1_SIZE; + u32 blocks = ( key_len + SHA1_DIGEST_SIZE - 1 ) / SHA1_DIGEST_SIZE; u32 blk; - u8 buf[SHA1_SIZE]; + 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 <= SHA1_SIZE ) { + if ( key_len <= sizeof ( buf ) ) { memcpy ( key, buf, key_len ); break; } - memcpy ( key, buf, SHA1_SIZE ); - key_len -= SHA1_SIZE; - key += SHA1_SIZE; + memcpy ( key, buf, sizeof ( buf ) ); + key_len -= sizeof ( buf ); + key += sizeof ( buf ); } } diff --git a/roms/ipxe/src/crypto/sha256.c b/roms/ipxe/src/crypto/sha256.c new file mode 100644 index 000000000..36e02b3c2 --- /dev/null +++ b/roms/ipxe/src/crypto/sha256.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * SHA-256 algorithm + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** 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/roms/ipxe/src/crypto/x509.c b/roms/ipxe/src/crypto/x509.c index 49bc2b867..df3c5c0de 100644 --- a/roms/ipxe/src/crypto/x509.c +++ b/roms/ipxe/src/crypto/x509.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -21,163 +22,1570 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include /** @file * * X.509 certificates * - * The structure of X.509v3 certificates is concisely documented in - * RFC5280 section 4.1. The structure of RSA public keys is - * documented in RFC2313. + * The structure of X.509v3 certificates is documented in RFC 5280 + * section 4.1. */ -/** Object Identifier for "rsaEncryption" (1.2.840.113549.1.1.1) */ -static const uint8_t oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01 }; +/* 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" ) +#define EACCES_OCSP_REQUIRED \ + __einfo_error ( EINFO_EACCES_OCSP_REQUIRED ) +#define EINFO_EACCES_OCSP_REQUIRED \ + __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" ) + +/** 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_discarder __cache_discarder ( CACHE_NORMAL ) = { + .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 ); /** - * Identify X.509 certificate public key + * Parse X.509 certificate version * - * @v certificate Certificate - * @v algorithm Public key algorithm to fill in - * @v pubkey Public key value to fill in + * @v cert X.509 certificate + * @v raw ASN.1 cursor * @ret rc Return status code */ -static int x509_public_key ( const struct asn1_cursor *certificate, - struct asn1_cursor *algorithm, - struct asn1_cursor *pubkey ) { +static int x509_parse_version ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { struct asn1_cursor cursor; + int version; int rc; - /* Locate subjectPublicKeyInfo */ - memcpy ( &cursor, certificate, sizeof ( cursor ) ); - rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */ - asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */ - asn1_skip ( &cursor, ASN1_EXPLICIT_TAG ), /* version */ - asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */ - asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */ - asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */ - asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */ - asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */ - asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/); - if ( rc != 0 ) { - DBG ( "Cannot locate subjectPublicKeyInfo in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); + /* 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; } - /* Locate algorithm */ - memcpy ( algorithm, &cursor, sizeof ( *algorithm ) ); - rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ ); - if ( rc != 0 ) { - DBG ( "Cannot locate algorithm in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); + /* 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 ); - /* Locate subjectPublicKey */ - memcpy ( pubkey, &cursor, sizeof ( *pubkey ) ); - rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */ - asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ ); - if ( rc != 0 ) { - DBG ( "Cannot locate subjectPublicKey in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->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; } /** - * Identify X.509 certificate RSA modulus and public exponent + * Parse X.509 certificate validity * - * @v certificate Certificate - * @v rsa RSA public key to fill in + * @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, + ¬_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, + ¬_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 * - * The caller is responsible for eventually calling - * x509_free_rsa_public_key() to free the storage allocated to hold - * the RSA modulus and exponent. + * @v cert X.509 certificate + * @v name Common name to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code */ -int x509_rsa_public_key ( const struct asn1_cursor *certificate, - struct x509_rsa_public_key *rsa_pubkey ) { - struct asn1_cursor algorithm; - struct asn1_cursor pubkey; - struct asn1_cursor modulus; - struct asn1_cursor exponent; +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; - /* First, extract the public key algorithm and key data */ - if ( ( rc = x509_public_key ( certificate, &algorithm, - &pubkey ) ) != 0 ) + /* 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 ); - /* Check that algorithm is RSA */ - rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ ); - if ( rc != 0 ) { - DBG ( "Cannot locate algorithm:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return rc; + 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 : "" ) ); + + /* 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 : "" ) ); + + /* 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 ); } - if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) || - ( memcmp ( algorithm.data, &oid_rsa_encryption, - sizeof ( oid_rsa_encryption ) ) != 0 ) ) { - DBG ( "algorithm is not rsaEncryption in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return -ENOTSUP; + + /* 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; - /* Check that public key is a byte string, i.e. that the - * "unused bits" byte contains zero. + 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 ( ( pubkey.len < 1 ) || - ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) { - DBG ( "subjectPublicKey is not a byte string in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return -ENOTSUP; - } - pubkey.data++; - pubkey.len--; - - /* Pick out the modulus and exponent */ - rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ ); - if ( rc != 0 ) { - DBG ( "Cannot locate RSAPublicKey in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return -ENOTSUP; - } - memcpy ( &modulus, &pubkey, sizeof ( modulus ) ); - rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ ); - if ( rc != 0 ) { - DBG ( "Cannot locate modulus in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return -ENOTSUP; - } - memcpy ( &exponent, &pubkey, sizeof ( exponent ) ); - rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */ - asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ ); - if ( rc != 0 ) { - DBG ( "Cannot locate publicExponent in:\n" ); - DBG_HDA ( 0, certificate->data, certificate->len ); - return -ENOTSUP; - } - - /* Allocate space and copy out modulus and exponent */ - rsa_pubkey->modulus = malloc ( modulus.len + exponent.len ); - if ( ! rsa_pubkey->modulus ) + 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; - rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len ); - memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len ); - rsa_pubkey->modulus_len = modulus.len; - memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len ); - rsa_pubkey->exponent_len = exponent.len; + 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 ); + *cert = NULL; + 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; - DBG2 ( "RSA modulus:\n" ); - DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len ); - DBG2 ( "RSA exponent:\n" ); - DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len ); + /* 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 ( validity->not_before.time > ( time + X509_ERROR_MARGIN_TIME ) ) { + DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n", + cert, cert->subject.name, time ); + return -EACCES_EXPIRED; + } + if ( validity->not_after.time < ( time - X509_ERROR_MARGIN_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; + } + + /* Fail if OCSP is required */ + if ( cert->extensions.auth_info.ocsp.uri && + ( ! cert->extensions.auth_info.ocsp.good ) ) { + DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n", + cert, cert->subject.name ); + return -EACCES_OCSP_REQUIRED; + } + + /* 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/roms/ipxe/src/drivers/bitbash/bitbash.c b/roms/ipxe/src/drivers/bitbash/bitbash.c index ac914075c..23ca30356 100644 --- a/roms/ipxe/src/drivers/bitbash/bitbash.c +++ b/roms/ipxe/src/drivers/bitbash/bitbash.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/bitbash/i2c_bit.c b/roms/ipxe/src/drivers/bitbash/i2c_bit.c index ccf82db8a..decc8d80e 100644 --- a/roms/ipxe/src/drivers/bitbash/i2c_bit.c +++ b/roms/ipxe/src/drivers/bitbash/i2c_bit.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -238,6 +239,7 @@ static int i2c_reset ( struct bit_basher *basher ) { * pull SDA low while SCL is high (which creates a start * condition). */ + open_bit ( basher ); setscl ( basher, 0 ); setsda ( basher, 1 ); for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) { @@ -250,6 +252,7 @@ static int i2c_reset ( struct bit_basher *basher ) { i2c_stop ( basher ); DBGC ( basher, "I2CBIT %p reset after %d attempts\n", basher, ( i + 1 ) ); + close_bit ( basher ); return 0; } setscl ( basher, 0 ); @@ -257,6 +260,7 @@ static int i2c_reset ( struct bit_basher *basher ) { DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n", basher, i ); + close_bit ( basher ); return -ETIMEDOUT; } @@ -284,6 +288,8 @@ static int i2c_bit_read ( struct i2c_interface *i2c, DBGC ( basher, "I2CBIT %p reading from device %x: ", basher, i2cdev->dev_addr ); + open_bit ( basher ); + for ( ; ; data++, offset++ ) { /* Select device for writing */ @@ -311,6 +317,7 @@ static int i2c_bit_read ( struct i2c_interface *i2c, DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); i2c_stop ( basher ); + close_bit ( basher ); return rc; } @@ -338,6 +345,8 @@ static int i2c_bit_write ( struct i2c_interface *i2c, DBGC ( basher, "I2CBIT %p writing to device %x: ", basher, i2cdev->dev_addr ); + open_bit ( basher ); + for ( ; ; data++, offset++ ) { /* Select device for writing */ @@ -358,9 +367,10 @@ static int i2c_bit_write ( struct i2c_interface *i2c, if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 ) break; } - + DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); i2c_stop ( basher ); + close_bit ( basher ); return rc; } diff --git a/roms/ipxe/src/drivers/bitbash/spi_bit.c b/roms/ipxe/src/drivers/bitbash/spi_bit.c index b64ffb828..1b39d72fa 100644 --- a/roms/ipxe/src/drivers/bitbash/spi_bit.c +++ b/roms/ipxe/src/drivers/bitbash/spi_bit.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -162,6 +163,9 @@ static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, uint32_t tmp_address; uint32_t tmp_address_detect; + /* Open bit-bashing interface */ + open_bit ( &spibit->basher ); + /* Deassert chip select to reset specified slave */ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); @@ -213,6 +217,9 @@ static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, /* Deassert chip select on specified slave */ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); + /* Close bit-bashing interface */ + close_bit ( &spibit->basher ); + return 0; } diff --git a/roms/ipxe/src/drivers/block/ata.c b/roms/ipxe/src/drivers/block/ata.c index 56740012b..c9b87c20c 100644 --- a/roms/ipxe/src/drivers/block/ata.c +++ b/roms/ipxe/src/drivers/block/ata.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/block/scsi.c b/roms/ipxe/src/drivers/block/scsi.c index d14165134..b45ae6304 100644 --- a/roms/ipxe/src/drivers/block/scsi.c +++ b/roms/ipxe/src/drivers/block/scsi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -218,8 +219,10 @@ struct scsi_device { /** SCSI device flags */ enum scsi_device_flags { - /** Unit is ready */ - SCSIDEV_UNIT_READY = 0x0001, + /** TEST UNIT READY has been issued */ + SCSIDEV_UNIT_TESTED = 0x0001, + /** TEST UNIT READY has completed successfully */ + SCSIDEV_UNIT_READY = 0x0002, }; /** A SCSI command */ @@ -892,23 +895,25 @@ static struct interface_descriptor scsidev_ready_desc = /** * SCSI TEST UNIT READY process * - * @v process Process + * @v scsidev SCSI device */ -static void scsidev_step ( struct process *process ) { - struct scsi_device *scsidev = - container_of ( process, struct scsi_device, process ); +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; - /* Stop process */ - process_del ( &scsidev->process ); - 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 ); @@ -918,6 +923,7 @@ static void scsidev_step ( struct process *process ) { /** 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 ), }; @@ -926,6 +932,10 @@ 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 * @@ -946,7 +956,8 @@ int scsi_open ( struct interface *block, struct interface *scsi, 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_step, &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", diff --git a/roms/ipxe/src/drivers/bus/isa.c b/roms/ipxe/src/drivers/bus/isa.c index 9b562c664..da0c43c60 100644 --- a/roms/ipxe/src/drivers/bus/isa.c +++ b/roms/ipxe/src/drivers/bus/isa.c @@ -46,9 +46,9 @@ static isa_probe_addr_t isa_extra_probe_addrs[] = { #endif #define ISA_IOADDR( driver, ioidx ) \ - ( ( (ioidx) < 0 ) ? \ - isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \ - (driver)->probe_addrs[(ioidx)] ) + ( ( (ioidx) >= 0 ) ? \ + (driver)->probe_addrs[(ioidx)] : \ + *( isa_extra_probe_addrs + (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ) ) static void isabus_remove ( struct root_device *rootdev ); diff --git a/roms/ipxe/src/drivers/bus/isapnp.c b/roms/ipxe/src/drivers/bus/isapnp.c index f7845d3fa..6417c74a6 100644 --- a/roms/ipxe/src/drivers/bus/isapnp.c +++ b/roms/ipxe/src/drivers/bus/isapnp.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) diff --git a/roms/ipxe/src/drivers/bus/pci.c b/roms/ipxe/src/drivers/bus/pci.c index 3ae17e5cf..7bd353d8b 100644 --- a/roms/ipxe/src/drivers/bus/pci.c +++ b/roms/ipxe/src/drivers/bus/pci.c @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/bus/pcibackup.c b/roms/ipxe/src/drivers/bus/pcibackup.c index 6719c53c7..6b592e893 100644 --- a/roms/ipxe/src/drivers/bus/pcibackup.c +++ b/roms/ipxe/src/drivers/bus/pcibackup.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/bus/pcivpd.c b/roms/ipxe/src/drivers/bus/pcivpd.c index 15cf90598..0b7a879fe 100644 --- a/roms/ipxe/src/drivers/bus/pcivpd.c +++ b/roms/ipxe/src/drivers/bus/pcivpd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/infiniband/arbel.c b/roms/ipxe/src/drivers/infiniband/arbel.c index c121bfd91..1a56ff9af 100644 --- a/roms/ipxe/src/drivers/infiniband/arbel.c +++ b/roms/ipxe/src/drivers/infiniband/arbel.c @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -31,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -772,6 +774,7 @@ static int arbel_alloc_qpn ( struct ib_device *ibdev, 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 ); @@ -822,6 +825,7 @@ 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, }; /** @@ -948,6 +952,18 @@ static int arbel_create_qp ( struct ib_device *ibdev, 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; @@ -1021,7 +1037,11 @@ static int arbel_create_qp ( struct ib_device *ibdev, ( send_wqe_base_adr >> 6 ) ); MLX_FILL_1 ( &qpctx, 35, qpc_eec_data.snd_db_record_index, arbel_qp->send.doorbell_idx ); - MLX_FILL_1 ( &qpctx, 38, qpc_eec_data.rsc, 1 ); + 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 ) ); @@ -1084,7 +1104,30 @@ static int arbel_modify_qp ( struct ib_device *ibdev, memset ( &qpctx, 0, sizeof ( qpctx ) ); MLX_FILL_2 ( &qpctx, 4, qpc_eec_data.mtu, ARBEL_MTU_2048, - qpc_eec_data.msg_max, 11 /* 2^11 = 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:" @@ -1097,6 +1140,15 @@ static int arbel_modify_qp ( struct ib_device *ibdev, /* 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, @@ -1198,14 +1250,14 @@ static const union ib_gid arbel_no_gid = { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); @@ -1217,16 +1269,16 @@ static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev, 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 ); + ud_address_vector.rlid, dest->lid, + ud_address_vector.g, dest->gid_present ); MLX_FILL_2 ( &wqe->ud.ud, 2, - ud_address_vector.max_stat_rate, arbel_rate ( av ), + ud_address_vector.max_stat_rate, arbel_rate ( dest ), 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 ); + MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl ); + gid = ( dest->gid_present ? &dest->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.ud, 8, destination_qp, dest->qpn ); + MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->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, @@ -1242,15 +1294,14 @@ static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); @@ -1260,16 +1311,16 @@ static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev, 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 ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* 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 ), + max_statrate, arbel_rate ( dest ), 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.ctrl, 1, rlid, dest->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 ); @@ -1288,16 +1339,46 @@ static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev, return ( offsetof ( typeof ( wqe->mlx ), data[2] ) >> 4 ); } +/** + * Construct RC send work queue entry + * + * @v ibdev Infiniband device + * @v qp Queue pair + * @v dest Destination address vector + * @v iobuf I/O buffer + * @v wqe Send work queue entry + * @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 *dest __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 ib_address_vector *dest, 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, }; /** @@ -1305,13 +1386,13 @@ static size_t * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); @@ -1341,7 +1422,7 @@ static int arbel_post_send ( struct ib_device *ibdev, 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 ); + nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, dest, 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 ) ); @@ -1444,9 +1525,10 @@ static int arbel_complete ( struct ib_device *ibdev, 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_address_vector recv_dest; + struct ib_address_vector recv_source; struct ib_global_route_header *grh; - struct ib_address_vector *av; + struct ib_address_vector *source; unsigned int opcode; unsigned long qpn; int is_send; @@ -1495,6 +1577,7 @@ static int arbel_complete ( struct ib_device *ibdev, 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 ); @@ -1526,6 +1609,8 @@ static int arbel_complete ( struct ib_device *ibdev, l_key, ARBEL_INVALID_LKEY ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); + memset ( &recv_dest, 0, sizeof ( recv_dest ) ); + recv_dest.qpn = qpn; switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -1534,20 +1619,27 @@ static int arbel_complete ( struct ib_device *ibdev, 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 ) ); + source = &recv_source; + memset ( source, 0, sizeof ( *source ) ); + source->qpn = MLX_GET ( &cqe->normal, rqpn ); + source->lid = MLX_GET ( &cqe->normal, rlid ); + source->sl = MLX_GET ( &cqe->normal, sl ); + recv_dest.gid_present = source->gid_present = + MLX_GET ( &cqe->normal, g ); + memcpy ( &recv_dest.gid, &grh->dgid, + sizeof ( recv_dest.gid ) ); + memcpy ( &source->gid, &grh->sgid, + sizeof ( source->gid ) ); + break; + case IB_QPT_RC: + source = &qp->av; break; default: assert ( 0 ); return -EINVAL; } /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, av, iobuf, rc ); + ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } return rc; @@ -1807,195 +1899,6 @@ static void arbel_poll_eq ( struct ib_device *ibdev ) { } } -/*************************************************************************** - * - * Infiniband link-layer operations - * - *************************************************************************** - */ - -/** - * Initialise Infiniband link - * - * @v ibdev Infiniband device - * @ret rc Return status code - */ -static int arbel_open ( struct ib_device *ibdev ) { - struct arbel *arbel = ib_get_drvdata ( ibdev ); - struct arbelprm_init_ib init_ib; - int rc; - - 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 ) ); - return rc; - } - - /* Update MAD parameters */ - ib_smc_update ( ibdev, arbel_mad ); - - return 0; -} - -/** - * Close Infiniband link - * - * @v ibdev Infiniband device - */ -static void arbel_close ( struct ib_device *ibdev ) { - struct arbel *arbel = ib_get_drvdata ( ibdev ); - int rc; - - 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 */ - } -} - -/** - * 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_open, - .close = arbel_close, - .mcast_attach = arbel_mcast_attach, - .mcast_detach = arbel_mcast_detach, - .set_port_info = arbel_inform_sma, - .set_pkey_table = arbel_inform_sma, -}; - /*************************************************************************** * * Firmware control @@ -2095,7 +1998,7 @@ 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_size; + size_t fw_len; physaddr_t fw_base; uint64_t eq_set_ci_base_addr; int rc; @@ -2123,17 +2026,22 @@ static int arbel_start_firmware ( struct arbel *arbel ) { arbel_cmd_enable_lam ( arbel, &lam ); /* Allocate firmware pages and map firmware area */ - fw_size = ( fw_pages * ARBEL_PAGE_SIZE ); - arbel->firmware_area = umalloc ( fw_size ); + fw_len = ( fw_pages * ARBEL_PAGE_SIZE ); if ( ! arbel->firmware_area ) { - rc = -ENOMEM; - goto err_alloc_fa; + 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_size ) ); + arbel, fw_base, ( fw_base + fw_len ) ); if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_fa, - 0, fw_base, fw_size ) ) != 0 ) { + 0, fw_base, fw_len ) ) != 0 ) { DBGC ( arbel, "Arbel %p could not map firmware: %s\n", arbel, strerror ( rc ) ); goto err_map_fa; @@ -2152,8 +2060,6 @@ static int arbel_start_firmware ( struct arbel *arbel ) { err_run_fw: arbel_cmd_unmap_fa ( arbel ); err_map_fa: - ufree ( arbel->firmware_area ); - arbel->firmware_area = UNULL; err_alloc_fa: err_query_fw: return rc; @@ -2171,10 +2077,9 @@ static void arbel_stop_firmware ( struct arbel *arbel ) { 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; } - ufree ( arbel->firmware_area ); - arbel->firmware_area = UNULL; } /*************************************************************************** @@ -2284,6 +2189,7 @@ static int arbel_alloc_icm ( struct arbel *arbel, 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; @@ -2297,7 +2203,8 @@ static int arbel_alloc_icm ( struct arbel *arbel, 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 - 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; @@ -2454,7 +2361,7 @@ static int arbel_alloc_icm ( struct arbel *arbel, /* Record amount of ICM to be allocated */ icm_offset = icm_align ( icm_offset, ARBEL_PAGE_SIZE ); - arbel->icm_len = icm_offset; + icm_len = icm_offset; /* User access region contexts * @@ -2479,24 +2386,29 @@ static int arbel_alloc_icm ( struct arbel *arbel, /* Get ICM auxiliary area size */ memset ( &icm_size, 0, sizeof ( icm_size ) ); - MLX_FILL_1 ( &icm_size, 1, value, arbel->icm_len ); + 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; } - arbel->icm_aux_len = - ( MLX_GET ( &icm_aux_size, value ) * ARBEL_PAGE_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, ( arbel->icm_len / 1024 ), - ( arbel->icm_aux_len / 1024 ) ); - arbel->icm = umalloc ( arbel->icm_len + arbel->icm_aux_len ); + arbel, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) ); if ( ! arbel->icm ) { - rc = -ENOMEM; - goto err_alloc_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 ); @@ -2562,8 +2474,6 @@ static int arbel_alloc_icm ( struct arbel *arbel, free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE ); arbel->db_rec= NULL; err_alloc_doorbell: - ufree ( arbel->icm ); - arbel->icm = UNULL; err_alloc_icm: err_set_icm_size: return rc; @@ -2586,17 +2496,41 @@ static void arbel_free_icm ( struct arbel *arbel ) { arbel_cmd_unmap_icm_aux ( arbel ); free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE ); arbel->db_rec = NULL; - ufree ( arbel->icm ); - arbel->icm = UNULL; } /*************************************************************************** * - * PCI interface + * 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 * @@ -2614,13 +2548,18 @@ static int arbel_setup_mpt ( struct arbel *arbel ) { /* Initialise memory protection table */ memset ( &mpt, 0, sizeof ( mpt ) ); - MLX_FILL_4 ( &mpt, 0, - r_w, 1, - pa, 1, + MLX_FILL_7 ( &mpt, 0, + a, 1, + rw, 1, + rr, 1, + lw, 1, lr, 1, - lw, 1 ); + pa, 1, + r_w, 1 ); MLX_FILL_1 ( &mpt, 2, mem_key, key ); - MLX_FILL_1 ( &mpt, 3, pd, ARBEL_GLOBAL_PD ); + 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, @@ -2671,30 +2610,395 @@ static int arbel_configure_special_qps ( struct arbel *arbel ) { } /** - * Probe PCI device + * Start Arbel device * - * @v pci PCI device - * @v id PCI ID + * @v arbel Arbel device + * @v running Firmware is already running * @ret rc Return status code */ -static int arbel_probe ( struct pci_device *pci ) { - struct arbel *arbel; - struct ib_device *ibdev; +static int arbel_start ( struct arbel *arbel, int running ) { struct arbelprm_init_hca init_hca; - int i; + unsigned int i; int rc; - /* Allocate Arbel device */ - arbel = zalloc ( sizeof ( *arbel ) ); - if ( ! arbel ) { - rc = -ENOMEM; - goto err_alloc_arbel; + /* Start firmware if not already running */ + if ( ! running ) { + if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 ) + goto err_start_firmware; } - pci_set_drvdata ( pci, arbel ); - /* Allocate Infiniband devices */ - for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { - ibdev = alloc_ibdev ( 0 ); + /* 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; @@ -2716,17 +3020,8 @@ static int arbel_probe ( struct pci_device *pci ) { ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ), ARBEL_PCI_UAR_SIZE ); - /* Allocate space for mailboxes */ - arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN ); - if ( ! arbel->mailbox_in ) { - rc = -ENOMEM; - goto err_mailbox_in; - } - arbel->mailbox_out = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN ); - if ( ! arbel->mailbox_out ) { - rc = -ENOMEM; - goto err_mailbox_out; - } + /* Reset device */ + arbel_reset ( arbel ); /* Start firmware */ if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 ) @@ -2736,29 +3031,9 @@ static int arbel_probe ( struct pci_device *pci ) { if ( ( rc = arbel_get_limits ( arbel ) ) != 0 ) goto err_get_limits; - /* 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; - - /* 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; + /* Start device */ + if ( ( rc = arbel_start ( arbel, 1 ) ) != 0 ) + goto err_start; /* Initialise parameters using SMC */ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) @@ -2774,33 +3049,27 @@ static int arbel_probe ( struct pci_device *pci ) { } } + /* 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] ); - 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 ( arbel ); + err_start: err_get_limits: arbel_stop_firmware ( arbel ); err_start_firmware: - free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); - err_mailbox_out: - free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); - err_mailbox_in: i = ARBEL_NUM_PORTS; err_alloc_ibdev: for ( i-- ; i >= 0 ; i-- ) ibdev_put ( arbel->ibdev[i] ); - free ( arbel ); - err_alloc_arbel: + arbel_free ( arbel ); + err_alloc: return rc; } @@ -2815,15 +3084,9 @@ static void arbel_remove ( struct pci_device *pci ) { for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) unregister_ibdev ( arbel->ibdev[i] ); - arbel_destroy_eq ( arbel ); - arbel_cmd_close_hca ( arbel ); - arbel_free_icm ( arbel ); - arbel_stop_firmware ( arbel ); - free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE ); - free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE ); for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) ibdev_put ( arbel->ibdev[i] ); - free ( arbel ); + arbel_free ( arbel ); } static struct pci_device_id arbel_nics[] = { diff --git a/roms/ipxe/src/drivers/infiniband/arbel.h b/roms/ipxe/src/drivers/infiniband/arbel.h index 534115729..c0303f1bc 100644 --- a/roms/ipxe/src/drivers/infiniband/arbel.h +++ b/roms/ipxe/src/drivers/infiniband/arbel.h @@ -31,6 +31,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 @@ -81,6 +86,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ARBEL_HCR_MAP_FA 0x0fff /* Service types */ +#define ARBEL_ST_RC 0x00 #define ARBEL_ST_UD 0x03 #define ARBEL_ST_MLX 0x07 @@ -111,6 +117,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 * @@ -223,6 +231,12 @@ struct arbelprm_mlx_send_wqe { 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 { @@ -324,6 +338,7 @@ 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 )); @@ -448,6 +463,8 @@ typedef uint32_t arbel_bitmask_t; /** An Arbel device */ struct arbel { + /** PCI device */ + struct pci_device *pci; /** PCI configuration registers */ void *config; /** PCI user Access Region */ @@ -460,13 +477,28 @@ struct arbel { /** Command output mailbox */ void *mailbox_out; - /** Firmware area in external memory */ + /** 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 */ + /** 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; diff --git a/roms/ipxe/src/drivers/infiniband/hermon.c b/roms/ipxe/src/drivers/infiniband/hermon.c index f44166f8b..a9c728706 100644 --- a/roms/ipxe/src/drivers/infiniband/hermon.c +++ b/roms/ipxe/src/drivers/infiniband/hermon.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -41,6 +42,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include "hermon.h" /** @@ -1363,7 +1366,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1371,7 +1374,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev, 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 ib_address_vector *dest __unused, struct io_buffer *iobuf __unused, union hermon_send_wqe *wqe ) { @@ -1385,7 +1388,7 @@ hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1393,7 +1396,7 @@ hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused, static unsigned int hermon_fill_ud_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1405,14 +1408,14 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, 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 ); + ud_address_vector.rlid, dest->lid, + ud_address_vector.g, dest->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 ); + ud_address_vector.max_stat_rate, hermon_rate ( dest ) ); + MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl ); + memcpy ( &wqe->ud.ud.u.dwords[4], &dest->gid, sizeof ( dest->gid ) ); + MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn ); + MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->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, @@ -1427,7 +1430,7 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1435,7 +1438,7 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, static unsigned int hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1445,7 +1448,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, 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 ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Fill work queue entry */ MLX_FILL_1 ( &wqe->mlx.ctrl, 1, ds, @@ -1453,10 +1456,10 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, MLX_FILL_5 ( &wqe->mlx.ctrl, 2, c, 0x03 /* generate completion */, icrc, 0 /* generate ICRC */, - max_statrate, hermon_rate ( av ), + max_statrate, hermon_rate ( dest ), 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.ctrl, 3, rlid, dest->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 ); @@ -1479,7 +1482,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1487,7 +1490,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, 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 ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1509,7 +1512,7 @@ hermon_fill_rc_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1517,7 +1520,7 @@ hermon_fill_rc_send_wqe ( struct ib_device *ibdev, 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 ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1542,7 +1545,7 @@ hermon_fill_eth_send_wqe ( struct ib_device *ibdev, static unsigned int ( * hermon_fill_send_wqe[] ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) = { [IB_QPT_SMI] = hermon_fill_mlx_send_wqe, @@ -1557,13 +1560,13 @@ static unsigned int * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp ); @@ -1594,7 +1597,7 @@ static int hermon_post_send ( struct ib_device *ibdev, 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 ); + opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe ); barrier(); MLX_FILL_2 ( &wqe->ctrl, 0, opcode, opcode, @@ -1676,9 +1679,10 @@ static int hermon_complete ( struct ib_device *ibdev, struct ib_work_queue *wq; struct ib_queue_pair *qp; struct io_buffer *iobuf; - struct ib_address_vector recv_av; + struct ib_address_vector recv_dest; + struct ib_address_vector recv_source; struct ib_global_route_header *grh; - struct ib_address_vector *av; + struct ib_address_vector *source; unsigned int opcode; unsigned long qpn; int is_send; @@ -1736,7 +1740,9 @@ static int hermon_complete ( struct ib_device *ibdev, len = MLX_GET ( &cqe->normal, byte_cnt ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); - memset ( &recv_av, 0, sizeof ( recv_av ) ); + memset ( &recv_dest, 0, sizeof ( recv_dest ) ); + recv_dest.qpn = qpn; + memset ( &recv_source, 0, sizeof ( recv_source ) ); switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -1745,28 +1751,32 @@ static int hermon_complete ( struct ib_device *ibdev, 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 ) ); + source = &recv_source; + source->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); + source->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); + source->sl = MLX_GET ( &cqe->normal, sl ); + recv_dest.gid_present = source->gid_present = + MLX_GET ( &cqe->normal, g ); + memcpy ( &recv_dest.gid, &grh->dgid, + sizeof ( recv_dest.gid ) ); + memcpy ( &source->gid, &grh->sgid, + sizeof ( source->gid ) ); break; case IB_QPT_RC: - av = &qp->av; + source = &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 ); + source = &recv_source; + source->vlan_present = MLX_GET ( &cqe->normal, vlan ); + source->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 ); + ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } return rc; @@ -2040,1284 +2050,1547 @@ static void hermon_poll_eq ( struct ib_device *ibdev ) { /*************************************************************************** * - * Infiniband link-layer operations + * Firmware control * *************************************************************************** */ /** - * Initialise Infiniband link + * Map virtual to physical address for firmware usage * - * @v ibdev Infiniband device + * @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_open ( struct ib_device *ibdev ) { - struct hermon *hermon = ib_get_drvdata ( ibdev ); - union hermonprm_set_port set_port; +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; - /* 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 ) ); - return rc; - } + /* Sanity checks */ + assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 ); + assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 ); + assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 ); - /* 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 ) ); - return rc; - } + /* 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 ); - /* Update MAD parameters */ - ib_smc_update ( ibdev, hermon_mad ); + /* 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; } /** - * Close Infiniband link + * Start firmware running * - * @v ibdev Infiniband device + * @v hermon Hermon device + * @ret rc Return status code */ -static void hermon_close ( struct ib_device *ibdev ) { - struct hermon *hermon = ib_get_drvdata ( ibdev ); +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; - 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 */ + /* 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; } /** - * Inform embedded subnet management agent of a received MAD + * Stop firmware running * - * @v ibdev Infiniband device - * @v mad MAD - * @ret rc Return status code + * @v hermon Hermon device */ -static int hermon_inform_sma ( struct ib_device *ibdev, - union ib_mad *mad ) { +static void hermon_stop_firmware ( struct hermon *hermon ) { 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; + 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; + } } /*************************************************************************** * - * Multicast group operations + * Infinihost Context Memory management * *************************************************************************** */ /** - * Attach to multicast group + * Get device limits * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v gid Multicast GID + * @v hermon Hermon device * @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; +static int hermon_get_cap ( struct hermon *hermon ) { + struct hermonprm_query_dev_cap dev_cap; 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", + 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; } - 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; + 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 ); - /* 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; + /* 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; } /** - * Detach from multicast group + * Align ICM table * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v gid Multicast GID + * @v icm_offset Current ICM offset + * @v len ICM table length + * @ret icm_offset ICM offset */ -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 ); +static uint64_t icm_align ( uint64_t icm_offset, size_t len ) { - /* 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; - } + /* Round up to a multiple of the table size */ + assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) ); + return ( ( icm_offset + len - 1 ) & ~( ( ( uint64_t ) len ) - 1 ) ); } -/** 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_open, - .close = hermon_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 + * Map ICM (allocating if necessary) * * @v hermon Hermon device - * @v port Hermon port + * @v init_hca INIT_HCA structure to fill in * @ret rc Return status code */ -static int hermon_register_ibdev ( struct hermon *hermon, - struct hermon_port *port ) { - struct ib_device *ibdev = port->ibdev; +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; - /* 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; - } + /* + * Start by carving up the ICM virtual address space + * + */ - return 0; -} + /* 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; -/** - * 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; + /* 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; - /* Update MAD parameters */ - ib_smc_update ( ibdev, hermon_mad ); -} + hermon->icm_map[HERMON_ICM_OTHER].offset = icm_offset; -/** - * 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; + /* 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; - unregister_ibdev ( ibdev ); -} + /* 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; -/** 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, -}; + /* 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; -/*************************************************************************** - * - * Ethernet operation - * - *************************************************************************** - */ + /* 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; -/** Number of Hermon Ethernet send work queue entries */ -#define HERMON_ETH_NUM_SEND_WQES 2 + /* 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; -/** Number of Hermon Ethernet receive work queue entries */ -#define HERMON_ETH_NUM_RECV_WQES 4 + /* 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; -/** Number of Hermon Ethernet completion entries */ -#define HERMON_ETH_NUM_CQES 8 + /* 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; -/** - * 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; + /* 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; - /* 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; + /* 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; } /** - * Handle Hermon Ethernet device send completion + * Unmap ICM * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @v rc Completion status code + * @v hermon Hermon device */ -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 ); +static void hermon_unmap_icm ( struct hermon *hermon ) { + struct hermonprm_scalar_parameter unmap_icm; + int i; - netdev_tx_complete_err ( netdev, iobuf, rc ); + 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 + * + *************************************************************************** + */ + /** - * Handle Hermon Ethernet device receive completion + * Reset device * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v av Address vector, or NULL - * @v iobuf I/O buffer - * @v rc Completion status code + * @v hermon Hermon device */ -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; +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 ); - /* 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; - } - } + /* 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 ); - /* Hand off to network layer */ - if ( rc == 0 ) { - netdev_rx ( netdev, iobuf ); - } else { - netdev_rx_err ( netdev, iobuf, rc ); - } + /* Reset command interface toggle */ + hermon->toggle = 0; } -/** 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 + * Set up memory protection table * - * @v netdev Network device + * @v hermon Hermon device + * @ret rc Return status code */ -static void hermon_eth_poll ( struct net_device *netdev ) { - struct hermon_port *port = netdev->priv; - struct ib_device *ibdev = port->ibdev; +static int hermon_setup_mpt ( struct hermon *hermon ) { + struct hermonprm_mpt mpt; + uint32_t key; + int rc; - ib_poll_eq ( ibdev ); + /* 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; } /** - * Open Hermon Ethernet device + * Configure special queue pairs * - * @v netdev Network device + * @v hermon Hermon 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; +static int hermon_configure_special_qps ( struct hermon *hermon ) { int rc; - /* 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; - } + /* 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 ) ); - /* 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; + /* 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; } - 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; - } + return 0; +} - /* Fill receive rings */ - ib_refill_recv ( ibdev, port->eth_qp ); +/** + * 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; - /* 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; + /* Start firmware if not already running */ + if ( ! running ) { + if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 ) + goto err_start_firmware; } - /* 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; - } + /* 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 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; + /* 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_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: + 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; } /** - * Close Hermon Ethernet device + * Stop Hermon device * - * @v netdev Network device + * @v hermon Hermon 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 ); +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 ); } -/** 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 + * Open Hermon 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; +static int hermon_open ( struct hermon *hermon ) { 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; + /* Start device if applicable */ + if ( hermon->open_count == 0 ) { + if ( ( rc = hermon_start ( hermon, 0 ) ) != 0 ) + 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; - } + /* Increment open counter */ + hermon->open_count++; return 0; } /** - * Handle Hermon Ethernet device port state change + * Close Hermon device * * @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 ); - } -} +static void hermon_close ( struct hermon *hermon ) { -/** - * 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; + /* Decrement open counter */ + assert ( hermon->open_count != 0 ); + hermon->open_count--; - unregister_netdev ( netdev ); + /* Stop device if applicable */ + if ( hermon->open_count == 0 ) + hermon_stop ( hermon ); } -/** 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 + * Infiniband link-layer operations * *************************************************************************** */ -/** Timeout for port sensing */ -#define HERMON_SENSE_PORT_TIMEOUT ( TICKS_PER_SEC / 2 ) - /** - * Name port type + * Initialise Infiniband link * - * @v port_type Port type - * @v port_type_name Port type name + * @v ibdev Infiniband device + * @ret rc Return status code */ -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"; - } -} +static int hermon_ib_open ( struct ib_device *ibdev ) { + struct hermon *hermon = ib_get_drvdata ( ibdev ); + union hermonprm_set_port set_port; + int rc; -/** - * 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; + /* Open hardware */ + if ( ( rc = hermon_open ( hermon ) ) != 0 ) + goto err_open; - /* 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; + /* 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; } - /* 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; + /* 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; } - 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; + /* Update MAD parameters */ + ib_smc_update ( ibdev, hermon_mad ); + + return 0; + + err_init_port: + err_set_port: + hermon_close ( hermon ); + err_open: + return rc; } /** - * Set port type + * Close Infiniband link * - * @v hermon Hermon device - * @v port Hermon port - * @ret rc Return status code + * @v ibdev Infiniband device */ -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; +static void hermon_ib_close ( struct ib_device *ibdev ) { + struct hermon *hermon = ib_get_drvdata ( ibdev ); 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", + /* 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 ) ); - return rc; + /* Nothing we can do about this */ } - 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 ) { + /* Close hardware */ + hermon_close ( hermon ); +} - /* 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 ) ); +/** + * 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; - /* 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; - } + /* Send the MAD to the embedded SMA */ + if ( ( rc = hermon_mad ( ibdev, mad ) ) != 0 ) + return rc; - } else if ( eth_supported ) { - port->type = &hermon_port_type_eth; - } else { - port->type = &hermon_port_type_ib; - } + /* Update parameters held in software */ + ib_smc_update ( ibdev, hermon_mad ); - assert ( port->type != NULL ); return 0; } /*************************************************************************** * - * Firmware control + * Multicast group operations * *************************************************************************** */ /** - * Map virtual to physical address for firmware usage + * Attach to multicast group * - * @v hermon Hermon device - * @v map Mapping function - * @v va Virtual address - * @v pa Physical address - * @v len Length of region + * @v ibdev Infiniband device + * @v qp Queue pair + * @v gid Multicast GID * @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; +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; - /* 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 ) { + /* 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 ); - /* 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 ); + /* 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; + } - /* 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; + /* 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; } - assert ( low == start ); - assert ( high == end ); - DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA ); return 0; } /** - * Start firmware running + * Detach from multicast group * - * @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_size; - physaddr_t fw_base; + * @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; - /* Get firmware parameters */ - if ( ( rc = hermon_cmd_query_fw ( hermon, &fw ) ) != 0 ) { - DBGC ( hermon, "Hermon %p could not query firmware: %s\n", + /* 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 ) ); - goto err_query_fw; + return; } - 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 ) ); + index = MLX_GET ( &hash, hash ); - /* Allocate firmware pages and map firmware area */ - fw_size = ( fw_pages * HERMON_PAGE_SIZE ); - hermon->firmware_area = umalloc ( fw_size ); - if ( ! hermon->firmware_area ) { - rc = -ENOMEM; - goto err_alloc_fa; - } - 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_size ) ); - if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa, - 0, fw_base, fw_size ) ) != 0 ) { - DBGC ( hermon, "Hermon %p could not map firmware: %s\n", - hermon, strerror ( rc ) ); - goto err_map_fa; + /* 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; } +} - /* 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; +/** 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; } - DBGC ( hermon, "Hermon %p firmware started\n", hermon ); return 0; +} - err_run_fw: - err_map_fa: - hermon_cmd_unmap_fa ( hermon ); - ufree ( hermon->firmware_area ); - hermon->firmware_area = UNULL; - err_alloc_fa: - err_query_fw: - return rc; +/** + * 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 ); } /** - * Stop firmware running + * Unregister Hermon Infiniband device * * @v hermon Hermon device + * @v port Hermon port */ -static void hermon_stop_firmware ( struct hermon *hermon ) { - int rc; +static void hermon_unregister_ibdev ( struct hermon *hermon __unused, + struct hermon_port *port ) { + struct ib_device *ibdev = port->ibdev; - 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 */ - return; - } - ufree ( hermon->firmware_area ); - hermon->firmware_area = UNULL; + 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, +}; + /*************************************************************************** * - * Infinihost Context Memory management + * 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 + /** - * Get device limits + * Transmit packet via Hermon Ethernet device * - * @v hermon Hermon device + * @v netdev Network device + * @v iobuf I/O buffer * @ret rc Return status code */ -static int hermon_get_cap ( struct hermon *hermon ) { - struct hermonprm_query_dev_cap dev_cap; +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; - 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 ) ); + /* 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; } - 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; } +/** Hermon Ethernet queue pair operations */ +static struct ib_queue_pair_operations hermon_eth_qp_op = { + .alloc_iob = alloc_iob, +}; + /** - * Align ICM table + * Handle Hermon Ethernet device send completion * - * @v icm_offset Current ICM offset - * @v len ICM table length - * @ret icm_offset ICM offset + * @v ibdev Infiniband device + * @v qp Queue pair + * @v iobuf I/O buffer + * @v rc Completion status code */ -static uint64_t icm_align ( uint64_t icm_offset, size_t len ) { +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 ); - /* Round up to a multiple of the table size */ - assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) ); - return ( ( icm_offset + len - 1 ) & ~( ( ( uint64_t ) len ) - 1 ) ); + netdev_tx_complete_err ( netdev, iobuf, rc ); } /** - * Allocate ICM + * Handle Hermon Ethernet device receive completion * - * @v hermon Hermon device - * @v init_hca INIT_HCA structure to fill in - * @ret rc Return status code + * @v ibdev Infiniband device + * @v qp Queue pair + * @v dest Destination address vector, or NULL + * @v source Source address vector, or NULL + * @v iobuf I/O buffer + * @v rc Completion status code */ -static int hermon_alloc_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; +static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused, + struct ib_queue_pair *qp, + struct ib_address_vector *dest __unused, + struct ib_address_vector *source, + struct io_buffer *iobuf, int rc ) { + struct net_device *netdev = ib_qp_get_ownerdata ( qp ); + struct net_device *vlan; - /* - * Start by carving up the ICM virtual address space - * - */ + /* Find VLAN device, if applicable */ + if ( source->vlan_present ) { + if ( ( vlan = vlan_find ( netdev, source->vlan ) ) != NULL ) { + netdev = vlan; + } else if ( rc == 0 ) { + rc = -ENODEV; + } + } - /* 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; + /* Hand off to network layer */ + if ( rc == 0 ) { + netdev_rx ( netdev, iobuf ); + } else { + netdev_rx_err ( netdev, iobuf, rc ); + } +} - /* 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 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, +}; - hermon->icm_map[HERMON_ICM_OTHER].offset = icm_offset; +/** + * 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; - /* 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; + ib_poll_eq ( ibdev ); +} - /* 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; +/** + * 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; - /* 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; + /* Open hardware */ + if ( ( rc = hermon_open ( hermon ) ) != 0 ) + goto err_open; - /* 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; + /* 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; + } - /* 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; + /* 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, + &hermon_eth_qp_op ); + 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 ); - /* 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; + /* 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; + } - /* 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; + /* Fill receive rings */ + ib_refill_recv ( ibdev, port->eth_qp ); - /* 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; + /* 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; + } - /* 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; + /* 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; + } - hermon->icm_map[HERMON_ICM_OTHER].len = - ( icm_offset - hermon->icm_map[HERMON_ICM_OTHER].offset ); + return 0; - /* - * Allocate and map physical memory for (portions of) ICM - * - * Map is: - * ICM AUX area (aligned to its own size) - * cMPT areas - * Other areas - */ + 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; +} - /* 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; +/** + * 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 */ } - /* 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; + /* 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 ) ); + goto err_query_port; } - icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * HERMON_PAGE_SIZE ); + 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 ); - /* 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 ) ); - hermon->icm = umalloc ( icm_aux_len + icm_len ); - if ( ! hermon->icm ) { - rc = -ENOMEM; - goto err_alloc; + /* 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 ) ); + goto err_register_netdev; } - 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; + /* Register non-volatile options */ + if ( ( rc = register_nvo ( &port->nvo, + netdev_settings ( netdev ) ) ) != 0 ) { + DBGC ( hermon, "Hermon %p port %d could not register non-" + "volatile options: %s\n", + hermon, ibdev->port, strerror ( rc ) ); + goto err_register_nvo; } - 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; + + unregister_nvo ( &port->nvo ); + err_register_nvo: + unregister_netdev ( netdev ); + err_register_netdev: + err_query_port: + return rc; +} + +/** + * 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_nvo ( &port->nvo ); + 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; } - return 0; + /* 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 ); - err_map_icm: - assert ( i == 0 ); /* We don't handle partial failure at present */ - err_map_icm_aux: - hermon_cmd_unmap_icm_aux ( hermon ); - ufree ( hermon->icm ); - hermon->icm = UNULL; - err_alloc: - err_set_icm_size: - return rc; + DBGC ( hermon, "Hermon %p port %d sensed an %s network\n", + hermon, ibdev->port, hermon_name_port_type ( port_type ) ); + return port_type; } /** - * Free ICM + * Set port type * * @v hermon Hermon device + * @v port Hermon port + * @ret rc Return status code */ -static void hermon_free_icm ( struct hermon *hermon ) { - struct hermonprm_scalar_parameter unmap_icm; - int i; +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; - 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 ); + /* 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; } - hermon_cmd_unmap_icm_aux ( hermon ); - ufree ( hermon->icm ); - hermon->icm = UNULL; + 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; } /*************************************************************************** @@ -3382,56 +3655,32 @@ static int hermon_bofm_update ( struct bofm_device *bofm, unsigned int mport, union { uint8_t bytes[8]; uint32_t dwords[2]; - uint64_t qword; } buf; - uint8_t *mac_copy = &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ]; int rc; /* Prepare MAC address */ memset ( &buf, 0, sizeof ( buf ) ); - memcpy ( mac_copy, mac, ETH_ALEN ); + memcpy ( &buf.bytes[ sizeof ( buf.bytes ) - ETH_ALEN ], mac, + ETH_ALEN ); - /* Current BOFM versions are unable to create entries with - * mport>1, which means that only the port 1 MAC address can - * be explicitly specified. Work around this by using the - * provided MAC address as a base address for all subsequent - * ports. For example, if BOFM assigns the address - * - * 00:1A:64:76:00:09 for port 1 - * - * then we will assign the addresses - * - * 00:1A:64:76:00:09 for port 1 - * 00:1A:64:76:00:0a for port 2 - * - * Note that hermon->cap.num_ports is not yet defined at this - * point. - */ - for ( ; mport <= HERMON_MAX_PORTS ; mport++ ) { - - /* 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, + /* 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_copy ) ); - - /* Increment MAC address */ - buf.qword = cpu_to_be64 ( be64_to_cpu ( buf.qword ) + 1 ); + 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; } @@ -3448,94 +3697,6 @@ static struct bofm_operations hermon_bofm_operations = { *************************************************************************** */ -/** - * 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; -} - -/** - * Reset device - * - * @v hermon Hermon device - * @v pci PCI device - */ -static void hermon_reset ( struct hermon *hermon, - struct pci_device *pci ) { - struct pci_config_backup backup; - static const uint8_t backup_exclude[] = - PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c ); - - 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 ); -} - /** * Allocate Hermon device * @@ -3579,6 +3740,8 @@ static struct hermon * hermon_alloc ( void ) { */ 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 ); @@ -3588,9 +3751,9 @@ static void hermon_free ( struct hermon *hermon ) { * Initialise Hermon PCI parameters * * @v hermon Hermon device - * @v pci PCI device */ -static void hermon_pci_init ( struct hermon *hermon, struct pci_device *pci ) { +static void hermon_pci_init ( struct hermon *hermon ) { + struct pci_device *pci = hermon->pci; /* Fix up PCI device */ adjust_pci_device ( pci ); @@ -3614,7 +3777,6 @@ static int hermon_probe ( struct pci_device *pci ) { struct ib_device *ibdev; struct net_device *netdev; struct hermon_port *port; - struct hermonprm_init_hca init_hca; unsigned int i; int rc; @@ -3625,12 +3787,13 @@ static int hermon_probe ( struct pci_device *pci ) { goto err_alloc; } pci_set_drvdata ( pci, hermon ); + hermon->pci = pci; /* Initialise PCI parameters */ - hermon_pci_init ( hermon, pci ); + hermon_pci_init ( hermon ); /* Reset device */ - hermon_reset ( hermon, pci ); + hermon_reset ( hermon ); /* Start firmware */ if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 ) @@ -3667,34 +3830,9 @@ static int hermon_probe ( struct pci_device *pci ) { netdev->priv = &hermon->port[i]; } - /* Allocate ICM */ - memset ( &init_hca, 0, sizeof ( init_hca ) ); - if ( ( rc = hermon_alloc_icm ( hermon, &init_hca ) ) != 0 ) - goto err_alloc_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; + /* Start device */ + if ( ( rc = hermon_start ( hermon, 1 ) ) != 0 ) + goto err_start; /* Determine port types */ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) { @@ -3703,6 +3841,15 @@ static int hermon_probe ( struct pci_device *pci ) { goto err_set_port_type; } + /* Initialise non-volatile storage */ + nvs_vpd_init ( &hermon->nvsvpd, pci ); + for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) { + port = &hermon->port[i]; + nvs_vpd_nvo_init ( &hermon->nvsvpd, + HERMON_VPD_FIELD ( port->ibdev->port ), + &port->nvo, NULL ); + } + /* Register devices */ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) { port = &hermon->port[i]; @@ -3710,6 +3857,10 @@ static int hermon_probe ( struct pci_device *pci ) { goto err_register; } + /* Leave device quiescent until opened */ + if ( hermon->open_count == 0 ) + hermon_stop ( hermon ); + return 0; i = hermon->cap.num_ports; @@ -3719,14 +3870,8 @@ static int hermon_probe ( struct pci_device *pci ) { port->type->unregister_dev ( hermon, port ); } err_set_port_type: - err_conf_special_qps: - hermon_destroy_eq ( hermon ); - err_create_eq: - err_setup_mpt: - hermon_cmd_close_hca ( hermon ); - err_init_hca: - hermon_free_icm ( hermon ); - err_alloc_icm: + hermon_stop ( hermon ); + err_start: i = hermon->cap.num_ports; err_alloc_netdev: for ( i-- ; ( signed int ) i >= 0 ; i-- ) { @@ -3759,10 +3904,6 @@ static void hermon_remove ( struct pci_device *pci ) { port = &hermon->port[i]; port->type->unregister_dev ( hermon, port ); } - hermon_destroy_eq ( hermon ); - hermon_cmd_close_hca ( hermon ); - hermon_free_icm ( hermon ); - hermon_stop_firmware ( hermon ); for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) { netdev_nullify ( hermon->port[i].netdev ); netdev_put ( hermon->port[i].netdev ); @@ -3790,9 +3931,10 @@ static int hermon_bofm_probe ( struct pci_device *pci ) { goto err_alloc; } pci_set_drvdata ( pci, hermon ); + hermon->pci = pci; /* Initialise PCI parameters */ - hermon_pci_init ( hermon, pci ); + hermon_pci_init ( hermon ); /* Initialise BOFM device */ bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations ); diff --git a/roms/ipxe/src/drivers/infiniband/hermon.h b/roms/ipxe/src/drivers/infiniband/hermon.h index 1c8623035..e0b028f26 100644 --- a/roms/ipxe/src/drivers/infiniband/hermon.h +++ b/roms/ipxe/src/drivers/infiniband/hermon.h @@ -13,6 +13,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include "mlx_bitops.h" #include "MT25408_PRM.h" @@ -135,6 +137,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define HERMON_MOD_STAT_CFG_SET 0x01 #define HERMON_MOD_STAT_CFG_QUERY 0x03 +#define HERMON_VPD_FIELD( port ) \ + PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'V', ( '5' + (port) - 1 ) ) + /* * Datatypes that seem to be missing from the autogenerated documentation * @@ -825,10 +830,14 @@ struct hermon_port { struct ib_queue_pair *eth_qp; /** Port type */ struct hermon_port_type *type; + /** Non-volatile option storage */ + struct nvo_block nvo; }; /** A Hermon device */ struct hermon { + /** PCI device */ + struct pci_device *pci; /** PCI configuration registers */ void *config; /** PCI user Access Region */ @@ -841,11 +850,30 @@ struct hermon { /** Command output mailbox */ void *mailbox_out; - /** Firmware area in external memory */ + /** 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 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; /** Event queue */ @@ -870,6 +898,9 @@ struct hermon { /** QPN base */ unsigned long qpn_base; + /** Non-volatile storage in PCI VPD */ + struct nvs_vpd_device nvsvpd; + /** Ports */ struct hermon_port port[HERMON_MAX_PORTS]; diff --git a/roms/ipxe/src/drivers/infiniband/linda.c b/roms/ipxe/src/drivers/infiniband/linda.c index 6a6a2ec9a..4afda1208 100644 --- a/roms/ipxe/src/drivers/infiniband/linda.c +++ b/roms/ipxe/src/drivers/infiniband/linda.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -935,13 +936,13 @@ static void linda_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf ) { struct linda *linda = ib_get_drvdata ( ibdev ); struct ib_work_queue *wq = &qp->send; @@ -968,7 +969,7 @@ static int linda_post_send ( struct ib_device *ibdev, /* 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 ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Calculate packet length */ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) + @@ -1169,7 +1170,8 @@ static void linda_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; - struct ib_address_vector av; + struct ib_address_vector dest; + struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; unsigned int egrindex; @@ -1237,7 +1239,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &av ) ) != 0 ) { + &payload_len, &dest, &source ) ) != 0 ) { DBGC ( linda, "Linda %p could not parse headers: %s\n", linda, strerror ( rc ) ); err = 1; @@ -1294,10 +1296,12 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc); + ib_complete_recv ( ibdev, intended_qp, &dest, &source, + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED ); + ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, + -ECANCELED ); } /* Clear eager buffer */ diff --git a/roms/ipxe/src/drivers/infiniband/linda.h b/roms/ipxe/src/drivers/infiniband/linda.h index 1450a6ada..72ce70868 100644 --- a/roms/ipxe/src/drivers/infiniband/linda.h +++ b/roms/ipxe/src/drivers/infiniband/linda.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/infiniband/mlx_bitops.h b/roms/ipxe/src/drivers/infiniband/mlx_bitops.h index 490d5e3c5..b6ca9f633 100644 --- a/roms/ipxe/src/drivers/infiniband/mlx_bitops.h +++ b/roms/ipxe/src/drivers/infiniband/mlx_bitops.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/infiniband/qib7322.c b/roms/ipxe/src/drivers/infiniband/qib7322.c index b66f8eff9..9979b346e 100644 --- a/roms/ipxe/src/drivers/infiniband/qib7322.c +++ b/roms/ipxe/src/drivers/infiniband/qib7322.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -1172,13 +1173,13 @@ static void qib7322_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf ) { struct qib7322 *qib7322 = ib_get_drvdata ( ibdev ); struct ib_work_queue *wq = &qp->send; @@ -1210,7 +1211,7 @@ static int qib7322_post_send ( struct ib_device *ibdev, /* 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 ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Calculate packet length */ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) + @@ -1412,7 +1413,8 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; - struct ib_address_vector av; + struct ib_address_vector dest; + struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; unsigned int egrindex; @@ -1473,7 +1475,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &av ) ) != 0 ) { + &payload_len, &dest, &source ) ) != 0 ) { DBGC ( qib7322, "QIB7322 %p could not parse headers: %s\n", qib7322, strerror ( rc ) ); err = 1; @@ -1530,10 +1532,12 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc); + ib_complete_recv ( ibdev, intended_qp, &dest, &source, + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED ); + ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, + -ECANCELED ); } /* Clear eager buffer */ @@ -2062,6 +2066,9 @@ static int qib7322_ahb_read ( struct qib7322 *qib7322, unsigned int location, struct QIB_7322_ahb_transaction_reg xact; int rc; + /* Avoid returning uninitialised data on error */ + *data = 0; + /* Initiate transaction */ memset ( &xact, 0, sizeof ( xact ) ); BIT_FILL_2 ( &xact, diff --git a/roms/ipxe/src/drivers/infiniband/qib7322.h b/roms/ipxe/src/drivers/infiniband/qib7322.h index 0dac09ef2..63abe221b 100644 --- a/roms/ipxe/src/drivers/infiniband/qib7322.h +++ b/roms/ipxe/src/drivers/infiniband/qib7322.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/infiniband/qib_genbits.pl b/roms/ipxe/src/drivers/infiniband/qib_genbits.pl index 1d5eeded0..586f7b6b8 100755 --- a/roms/ipxe/src/drivers/infiniband/qib_genbits.pl +++ b/roms/ipxe/src/drivers/infiniband/qib_genbits.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/roms/ipxe/src/drivers/net/3c509-eisa.c b/roms/ipxe/src/drivers/net/3c509-eisa.c index 195a844a4..81c60ee91 100644 --- a/roms/ipxe/src/drivers/net/3c509-eisa.c +++ b/roms/ipxe/src/drivers/net/3c509-eisa.c @@ -6,7 +6,6 @@ #include #include -#include #include "3c509.h" /* diff --git a/roms/ipxe/src/drivers/net/3c509.h b/roms/ipxe/src/drivers/net/3c509.h index f030d4ba4..25e4a88d8 100644 --- a/roms/ipxe/src/drivers/net/3c509.h +++ b/roms/ipxe/src/drivers/net/3c509.h @@ -77,7 +77,7 @@ FILE_LICENCE ( BSD3 ); /************************************************************************** * * These define the EEPROM data structure. They are used in the probe - * function to verify the existance of the adapter after having sent + * 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. diff --git a/roms/ipxe/src/drivers/net/3c515.c b/roms/ipxe/src/drivers/net/3c515.c index 2b8606906..0aa68b1aa 100644 --- a/roms/ipxe/src/drivers/net/3c515.c +++ b/roms/ipxe/src/drivers/net/3c515.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 1997-2002 Donald Becker 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux. @@ -655,7 +656,7 @@ 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 */ + /* Direct copy from Becker 3c515.c with unnecessary parts removed */ vp->product_name = "3c515"; vp->options = options; if (options >= 0) { diff --git a/roms/ipxe/src/drivers/net/3c595.c b/roms/ipxe/src/drivers/net/3c595.c index 3178178ac..1aa8ed641 100644 --- a/roms/ipxe/src/drivers/net/3c595.c +++ b/roms/ipxe/src/drivers/net/3c595.c @@ -127,7 +127,7 @@ static void t595_reset(struct nic *nic) S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); /* - * Attempt to get rid of any stray interrupts that occured during + * Attempt to get rid of any stray interrupts that occurred during * configuration. On the i386 this isn't possible because one may * already be queued. However, a single stray interrupt is * unimportant. diff --git a/roms/ipxe/src/drivers/net/amd8111e.c b/roms/ipxe/src/drivers/net/amd8111e.c index 476d53068..693d77d1d 100644 --- a/roms/ipxe/src/drivers/net/amd8111e.c +++ b/roms/ipxe/src/drivers/net/amd8111e.c @@ -24,7 +24,8 @@ * * You 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * USA */ diff --git a/roms/ipxe/src/drivers/net/amd8111e.h b/roms/ipxe/src/drivers/net/amd8111e.h index a402a63ec..2000df158 100644 --- a/roms/ipxe/src/drivers/net/amd8111e.h +++ b/roms/ipxe/src/drivers/net/amd8111e.h @@ -14,7 +14,8 @@ * * You 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * USA Module Name: @@ -573,7 +574,7 @@ typedef enum { #define CSTATE 1 #define SSTATE 2 -/* amd8111e decriptor flag definitions */ +/* amd8111e descriptor flag definitions */ typedef enum { OWN_BIT = (1 << 15), diff --git a/roms/ipxe/src/drivers/net/ath/ath.h b/roms/ipxe/src/drivers/net/ath/ath.h new file mode 100644 index 000000000..5a19a19cd --- /dev/null +++ b/roms/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 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 +#include + +/* 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c new file mode 100644 index 000000000..92c4ffdf4 --- /dev/null +++ b/roms/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 + * Copyright (c) 2007 Luis R. Rodriguez + * + * Modified for iPXE, July 2009, by Joshua Oreman + * 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 +#include +#include +#include +#include +#include + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.h b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.h new file mode 100644 index 000000000..30e2024c6 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.h @@ -0,0 +1,1279 @@ +/* + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2007 Nick Kossifidis + * + * Modified for iPXE, July 2009, by Joshua Oreman + * 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 +#include +#include +#include +#include +#include + +/* 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c new file mode 100644 index 000000000..302536dbd --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_attach.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Modified for iPXE, July 2009, by Joshua Oreman + * 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 +#include +#include +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c new file mode 100644 index 000000000..9c00d15d7 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_caps.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c new file mode 100644 index 000000000..30fe1c777 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_desc.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Pavel Roskin + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c new file mode 100644 index 000000000..fa1e0d013 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_dma.c @@ -0,0 +1,631 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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 + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c new file mode 100644 index 000000000..983d206b7 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_eeprom.c @@ -0,0 +1,1760 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2008-2009 Felix Fietkau + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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 +#include + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c new file mode 100644 index 000000000..2301ec70b --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_gpio.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c new file mode 100644 index 000000000..8f3bd2034 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_initvals.c @@ -0,0 +1,1560 @@ +/* + * Initial register settings functions + * + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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 + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c new file mode 100644 index 000000000..c8165da79 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_pcu.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Matthew W. S. Bell + * Copyright (c) 2007-2008 Luis Rodriguez + * Copyright (c) 2007-2008 Pavel Roskin + * Copyright (c) 2007-2008 Jiri Slaby + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c new file mode 100644 index 000000000..7891d39ea --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c @@ -0,0 +1,2581 @@ +/* + * PHY functions + * + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * Copyright (c) 2008-2009 Felix Fietkau + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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 +#include + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c new file mode 100644 index 000000000..e38dba9e2 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_qcu.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c new file mode 100644 index 000000000..2f36a4e9a --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c @@ -0,0 +1,1174 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Luis Rodriguez + * Copyright (c) 2007-2008 Pavel Roskin + * Copyright (c) 2007-2008 Jiri Slaby + * + * Lightly modified for iPXE, July 2009, by Joshua Oreman . + * + * 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 /* To determine if a card is pci-e */ +#include + +#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/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c new file mode 100644 index 000000000..752ef70b9 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_rfkill.c @@ -0,0 +1,107 @@ +/* + * RFKILL support for ath5k + * + * Copyright (c) 2009 Tobias Doerffel + * Lightly modified for iPXE, Sep 2008 by Joshua Oreman + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/base.h b/roms/ipxe/src/drivers/net/ath/ath5k/base.h new file mode 100644 index 000000000..976a3f306 --- /dev/null +++ b/roms/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 + * 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 + +#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/roms/ipxe/src/drivers/net/ath/ath5k/desc.h b/roms/ipxe/src/drivers/net/ath/ath5k/desc.h new file mode 100644 index 000000000..6e11b0d43 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/desc.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/eeprom.h b/roms/ipxe/src/drivers/net/ath/ath5k/eeprom.h new file mode 100644 index 000000000..da4543393 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/eeprom.h @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/reg.h b/roms/ipxe/src/drivers/net/ath/ath5k/reg.h new file mode 100644 index 000000000..7070d1543 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/reg.h @@ -0,0 +1,2589 @@ +/* + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2007-2008 Michael Taylor + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h b/roms/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h new file mode 100644 index 000000000..e50baff66 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/rfbuffer.h @@ -0,0 +1,1181 @@ +/* + * RF Buffer handling functions + * + * Copyright (c) 2009 Nick Kossifidis + * + * 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/roms/ipxe/src/drivers/net/ath/ath5k/rfgain.h b/roms/ipxe/src/drivers/net/ath/ath5k/rfgain.h new file mode 100644 index 000000000..1354d8c39 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath5k/rfgain.h @@ -0,0 +1,516 @@ +/* + * RF Gain optimization + * + * Copyright (c) 2004-2009 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * + * 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/roms/ipxe/src/drivers/net/ath/ath9k/ani.h b/roms/ipxe/src/drivers/net/ath/ath9k/ani.h new file mode 100644 index 000000000..9a333b5f7 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar5008_initvals.h new file mode 100644 index 000000000..479aed547 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9001_initvals.h new file mode 100644 index 000000000..7dca47443 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h new file mode 100644 index 000000000..dd121513b --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_phy.h new file mode 100644 index 000000000..453af6dc5 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h new file mode 100644 index 000000000..e8ac70da5 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_eeprom.h new file mode 100644 index 000000000..393f2de52 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_mac.h new file mode 100644 index 000000000..6442bb779 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_phy.h new file mode 100644 index 000000000..443090d27 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h new file mode 100644 index 000000000..815a8af1b --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h new file mode 100644 index 000000000..611ea6ce8 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k.c new file mode 100644 index 000000000..183aa65f6 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k.h b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k.h new file mode 100644 index 000000000..d2dce9b7b --- /dev/null +++ b/roms/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 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<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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ani.c new file mode 100644 index 000000000..ff7df497f --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar5008_phy.c new file mode 100644 index 000000000..60e87e9e2 --- /dev/null +++ b/roms/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 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 +#include + +#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 + * + * + * 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, ¢ers); + 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, ¢ers); + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c new file mode 100644 index 000000000..f8978a558 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_hw.c new file mode 100644 index 000000000..cc4edece4 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_mac.c new file mode 100644 index 000000000..057756b2e --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_phy.c new file mode 100644 index 000000000..72203ba48 --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + 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, ¢ers); + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_calib.c new file mode 100644 index 000000000..c37168bd2 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_eeprom.c new file mode 100644 index 000000000..95e54b9b2 --- /dev/null +++ b/roms/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 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 +#include + +#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, ¢ers); + + /* 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_hw.c new file mode 100644 index 000000000..f3020fd7e --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_mac.c new file mode 100644 index 000000000..1fa4039cc --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9003_phy.c new file mode 100644 index 000000000..6103040ab --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + 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, ¢ers); + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_calib.c new file mode 100644 index 000000000..6f3e07e6d --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_common.c new file mode 100644 index 000000000..ce33afbd4 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c new file mode 100644 index 000000000..f552acaa3 --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + 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, ¢ers); + 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, ¢ers); + + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_4k.c new file mode 100644 index 000000000..a42ad3d97 --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_9287.c new file mode 100644 index 000000000..ee16a6f18 --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + + 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, ¢ers); + + /* 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom_def.c new file mode 100644 index 000000000..9b144d70b --- /dev/null +++ b/roms/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 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 + +#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, ¢ers); + + 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, ¢ers); + + 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, ¢ers); + + 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_hw.c new file mode 100644 index 000000000..554e9be3c --- /dev/null +++ b/roms/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 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 +#include + +#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= 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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c new file mode 100644 index 000000000..93fbe7733 --- /dev/null +++ b/roms/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 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 +#include +#include + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_mac.c new file mode 100644 index 000000000..c2f6d630a --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c new file mode 100644 index 000000000..0a17b9bcb --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c new file mode 100644 index 000000000..ba363c676 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_xmit.c new file mode 100644 index 000000000..7f4f28ab8 --- /dev/null +++ b/roms/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 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 + +#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<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<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/roms/ipxe/src/drivers/net/ath/ath9k/calib.h b/roms/ipxe/src/drivers/net/ath/ath9k/calib.h new file mode 100644 index 000000000..5bf50f4a6 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/common.h b/roms/ipxe/src/drivers/net/ath/ath9k/common.h new file mode 100644 index 000000000..009f8036d --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/eeprom.h b/roms/ipxe/src/drivers/net/ath/ath9k/eeprom.h new file mode 100644 index 000000000..b451ebd70 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/ath9k/hw-ops.h b/roms/ipxe/src/drivers/net/ath/ath9k/hw-ops.h new file mode 100644 index 000000000..65cff3b08 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/hw.h b/roms/ipxe/src/drivers/net/ath/ath9k/hw.h new file mode 100644 index 000000000..c10df3883 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/mac.h b/roms/ipxe/src/drivers/net/ath/ath9k/mac.h new file mode 100644 index 000000000..5899230e0 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath9k/phy.h b/roms/ipxe/src/drivers/net/ath/ath9k/phy.h new file mode 100644 index 000000000..8b380305b --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath9k/reg.h b/roms/ipxe/src/drivers/net/ath/ath9k/reg.h new file mode 100644 index 000000000..c18ee9921 --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/ath/ath_hw.c b/roms/ipxe/src/drivers/net/ath/ath_hw.c new file mode 100644 index 000000000..8e3128868 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath_key.c b/roms/ipxe/src/drivers/net/ath/ath_key.c new file mode 100644 index 000000000..d269a45ac --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath_key.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2010 Bruno Randolf + * + * Modified for iPXE by Scott K Logan 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/roms/ipxe/src/drivers/net/ath/ath_main.c b/roms/ipxe/src/drivers/net/ath/ath_main.c new file mode 100644 index 000000000..85d159a36 --- /dev/null +++ b/roms/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 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 + +#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/roms/ipxe/src/drivers/net/ath/ath_regd.c b/roms/ipxe/src/drivers/net/ath/ath_regd.c new file mode 100644 index 000000000..190b1f9f5 --- /dev/null +++ b/roms/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 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, +// ®_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, ®_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, ®_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 ®DomainPairs[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/roms/ipxe/src/drivers/net/ath/reg.h b/roms/ipxe/src/drivers/net/ath/reg.h new file mode 100644 index 000000000..484a8f1cb --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/regd.h b/roms/ipxe/src/drivers/net/ath/regd.h new file mode 100644 index 000000000..6954c5f36 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath/regd_common.h b/roms/ipxe/src/drivers/net/ath/regd_common.h new file mode 100644 index 000000000..ee1ac3f40 --- /dev/null +++ b/roms/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 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/roms/ipxe/src/drivers/net/ath5k/ath5k.c b/roms/ipxe/src/drivers/net/ath5k/ath5k.c deleted file mode 100644 index 92c4ffdf4..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* - * 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 - * Copyright (c) 2007 Luis R. Rodriguez - * - * Modified for iPXE, July 2009, by Joshua Oreman - * 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 -#include -#include -#include -#include -#include - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k.h b/roms/ipxe/src/drivers/net/ath5k/ath5k.h deleted file mode 100644 index 30e2024c6..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k.h +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2007 Nick Kossifidis - * - * Modified for iPXE, July 2009, by Joshua Oreman - * 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 -#include -#include -#include -#include -#include - -/* 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/roms/ipxe/src/drivers/net/ath5k/ath5k_attach.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_attach.c deleted file mode 100644 index 302536dbd..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_attach.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Modified for iPXE, July 2009, by Joshua Oreman - * 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 -#include -#include -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_caps.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_caps.c deleted file mode 100644 index 9c00d15d7..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_caps.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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/roms/ipxe/src/drivers/net/ath5k/ath5k_desc.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_desc.c deleted file mode 100644 index 30fe1c777..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_desc.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Pavel Roskin - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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/roms/ipxe/src/drivers/net/ath5k/ath5k_dma.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_dma.c deleted file mode 100644 index fa1e0d013..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_dma.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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 - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_eeprom.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_eeprom.c deleted file mode 100644 index 983d206b7..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_eeprom.c +++ /dev/null @@ -1,1760 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2008-2009 Felix Fietkau - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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 -#include - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_gpio.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_gpio.c deleted file mode 100644 index 2301ec70b..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_gpio.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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/roms/ipxe/src/drivers/net/ath5k/ath5k_initvals.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_initvals.c deleted file mode 100644 index 8f3bd2034..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_initvals.c +++ /dev/null @@ -1,1560 +0,0 @@ -/* - * Initial register settings functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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 - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_pcu.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_pcu.c deleted file mode 100644 index c8165da79..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_pcu.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Matthew W. S. Bell - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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/roms/ipxe/src/drivers/net/ath5k/ath5k_phy.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_phy.c deleted file mode 100644 index 7891d39ea..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_phy.c +++ /dev/null @@ -1,2581 +0,0 @@ -/* - * PHY functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * Copyright (c) 2008-2009 Felix Fietkau - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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 -#include - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_qcu.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_qcu.c deleted file mode 100644 index e38dba9e2..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_qcu.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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/roms/ipxe/src/drivers/net/ath5k/ath5k_reset.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_reset.c deleted file mode 100644 index 2f36a4e9a..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_reset.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Lightly modified for iPXE, July 2009, by Joshua Oreman . - * - * 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 /* To determine if a card is pci-e */ -#include - -#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/roms/ipxe/src/drivers/net/ath5k/ath5k_rfkill.c b/roms/ipxe/src/drivers/net/ath5k/ath5k_rfkill.c deleted file mode 100644 index 752ef70b9..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/ath5k_rfkill.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * RFKILL support for ath5k - * - * Copyright (c) 2009 Tobias Doerffel - * Lightly modified for iPXE, Sep 2008 by Joshua Oreman - * - * 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/roms/ipxe/src/drivers/net/ath5k/base.h b/roms/ipxe/src/drivers/net/ath5k/base.h deleted file mode 100644 index 976a3f306..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/base.h +++ /dev/null @@ -1,145 +0,0 @@ -/*- - * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Modified for iPXE, July 2009, by Joshua Oreman - * 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 - -#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/roms/ipxe/src/drivers/net/ath5k/desc.h b/roms/ipxe/src/drivers/net/ath5k/desc.h deleted file mode 100644 index 6e11b0d43..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/desc.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * 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/roms/ipxe/src/drivers/net/ath5k/eeprom.h b/roms/ipxe/src/drivers/net/ath5k/eeprom.h deleted file mode 100644 index da4543393..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/eeprom.h +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * 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/roms/ipxe/src/drivers/net/ath5k/reg.h b/roms/ipxe/src/drivers/net/ath5k/reg.h deleted file mode 100644 index 7070d1543..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/reg.h +++ /dev/null @@ -1,2589 +0,0 @@ -/* - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2007-2008 Michael Taylor - * - * 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/roms/ipxe/src/drivers/net/ath5k/rfbuffer.h b/roms/ipxe/src/drivers/net/ath5k/rfbuffer.h deleted file mode 100644 index e50baff66..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/rfbuffer.h +++ /dev/null @@ -1,1181 +0,0 @@ -/* - * RF Buffer handling functions - * - * Copyright (c) 2009 Nick Kossifidis - * - * 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/roms/ipxe/src/drivers/net/ath5k/rfgain.h b/roms/ipxe/src/drivers/net/ath5k/rfgain.h deleted file mode 100644 index 1354d8c39..000000000 --- a/roms/ipxe/src/drivers/net/ath5k/rfgain.h +++ /dev/null @@ -1,516 +0,0 @@ -/* - * RF Gain optimization - * - * Copyright (c) 2004-2009 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * - * 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/roms/ipxe/src/drivers/net/atl1e.c b/roms/ipxe/src/drivers/net/atl1e.c index e4dd5c973..1ff0f0d10 100644 --- a/roms/ipxe/src/drivers/net/atl1e.c +++ b/roms/ipxe/src/drivers/net/atl1e.c @@ -17,8 +17,8 @@ * more details. * * You 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. + * 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 ); diff --git a/roms/ipxe/src/drivers/net/atl1e.h b/roms/ipxe/src/drivers/net/atl1e.h index e759ea49b..2c972ea10 100644 --- a/roms/ipxe/src/drivers/net/atl1e.h +++ b/roms/ipxe/src/drivers/net/atl1e.h @@ -18,8 +18,8 @@ * more details. * * You 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. + * 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 ); diff --git a/roms/ipxe/src/drivers/net/b44.c b/roms/ipxe/src/drivers/net/b44.c index 66fa8ea3c..d9aeb1b4b 100644 --- a/roms/ipxe/src/drivers/net/b44.c +++ b/roms/ipxe/src/drivers/net/b44.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * This driver is a port of the b44 linux driver version 1.01 * @@ -78,24 +79,21 @@ static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout) /** - * Return non-zero if the installed RAM is within - * the limit given and zero if it is outside. - * Hopefully will be removed soon. + * Check if card can access address + * + * @v address Virtual address + * @v address_ok Card can access address */ -int phys_ram_within_limit(u64 limit) -{ - struct memory_map memmap; - struct memory_region *highest = NULL; - get_memmap(&memmap); +static inline __attribute__ (( always_inline )) int +b44_address_ok ( void *address ) { - if (memmap.count == 0) - return 0; - highest = &memmap.regions[memmap.count - 1]; + /* Card can address anything with a 30-bit address */ + if ( ( virt_to_bus ( address ) & ~B44_30BIT_DMA_MASK ) == 0 ) + return 1; - return (highest->end < limit); + return 0; } - /** * Ring cells waiting to be processed are between 'tx_cur' and 'pending' * indexes in the ring. @@ -404,6 +402,7 @@ static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx) */ static void b44_rx_refill(struct b44_private *bp, u32 pending) { + struct io_buffer *iobuf; u32 i; // skip pending @@ -411,11 +410,17 @@ static void b44_rx_refill(struct b44_private *bp, u32 pending) if (bp->rx_iobuf[i] != NULL) continue; - bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ); - if (!bp->rx_iobuf[i]) { + iobuf = alloc_iob(RX_PKT_BUF_SZ); + if (!iobuf) { DBG("Refill rx ring failed!!\n"); break; } + if (!b44_address_ok(iobuf->data)) { + DBG("Refill rx ring bad address!!\n"); + free_iob(iobuf); + break; + } + bp->rx_iobuf[i] = iobuf; b44_populate_rx_descriptor(bp, i); } @@ -444,6 +449,10 @@ static int b44_init_rx_ring(struct b44_private *bp) bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT); if (!bp->rx) return -ENOMEM; + if (!b44_address_ok(bp->rx)) { + free_dma(bp->rx, B44_RX_RING_LEN_BYTES); + return -ENOTSUP; + } memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf)); @@ -472,6 +481,10 @@ static int b44_init_tx_ring(struct b44_private *bp) bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT); if (!bp->tx) return -ENOMEM; + if (!b44_address_ok(bp->tx)) { + free_dma(bp->tx, B44_TX_RING_LEN_BYTES); + return -ENOTSUP; + } memset(bp->tx, 0, B44_TX_RING_LEN_BYTES); memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf)); @@ -644,17 +657,6 @@ static int b44_probe(struct pci_device *pci) 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) @@ -793,6 +795,10 @@ static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf) return -ENOBUFS; } + /* Check for addressability */ + if (!b44_address_ok(iobuf->data)) + return -ENOTSUP; + /* Will call netdev_tx_complete() on the iobuf later */ bp->tx_iobuf[cur] = iobuf; diff --git a/roms/ipxe/src/drivers/net/b44.h b/roms/ipxe/src/drivers/net/b44.h index 2d1f206e0..089580926 100644 --- a/roms/ipxe/src/drivers/net/b44.h +++ b/roms/ipxe/src/drivers/net/b44.h @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * This driver is a port of the b44 linux driver version 1.01 * diff --git a/roms/ipxe/src/drivers/net/cs89x0.c b/roms/ipxe/src/drivers/net/cs89x0.c index ee34d0c59..17b7157a1 100644 --- a/roms/ipxe/src/drivers/net/cs89x0.c +++ b/roms/ipxe/src/drivers/net/cs89x0.c @@ -58,7 +58,7 @@ FILE_LICENCE ( GPL2_ONLY ); Fri Nov 22 23:00:00 1996 Markus Gutschke * 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 + changes that will be necessary in order to adapt Russel Nelson's code to the requirements of a BOOT-Prom * 6 @@ -92,7 +92,6 @@ FILE_LICENCE ( GPL2_ONLY ); #include "etherboot.h" #include "nic.h" #include -#include #include "cs89x0.h" static unsigned short eth_nic_base; diff --git a/roms/ipxe/src/drivers/net/cs89x0.h b/roms/ipxe/src/drivers/net/cs89x0.h index a36b907c6..432fe94eb 100644 --- a/roms/ipxe/src/drivers/net/cs89x0.h +++ b/roms/ipxe/src/drivers/net/cs89x0.h @@ -31,7 +31,8 @@ FILE_LICENCE ( GPL2_ONLY ); You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ /* offset 2h -> Model/Product Number */ diff --git a/roms/ipxe/src/drivers/net/davicom.c b/roms/ipxe/src/drivers/net/davicom.c index 141177426..a4870a729 100644 --- a/roms/ipxe/src/drivers/net/davicom.c +++ b/roms/ipxe/src/drivers/net/davicom.c @@ -213,11 +213,11 @@ static int phy_read(int location) phy_write_1bit(io_dcr9, PHY_DATA_1); phy_write_1bit(io_dcr9, PHY_DATA_0); - /* Send Phy addres */ + /* Send Phy address */ 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 */ + /* Send register address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); @@ -257,11 +257,11 @@ static void phy_write(int location, u16 phy_data) phy_write_1bit(io_dcr9, PHY_DATA_0); phy_write_1bit(io_dcr9, PHY_DATA_1); - /* Send Phy addres */ + /* Send Phy address */ 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 */ + /* Send register address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); diff --git a/roms/ipxe/src/drivers/net/depca.c b/roms/ipxe/src/drivers/net/depca.c index 735a52dfb..016f28bb2 100644 --- a/roms/ipxe/src/drivers/net/depca.c +++ b/roms/ipxe/src/drivers/net/depca.c @@ -240,7 +240,6 @@ FILE_LICENCE ( GPL_ANY ); #include "etherboot.h" #include "nic.h" #include -#include #include /* diff --git a/roms/ipxe/src/drivers/net/dmfe.c b/roms/ipxe/src/drivers/net/dmfe.c index dd6c1dec2..aae40fce7 100644 --- a/roms/ipxe/src/drivers/net/dmfe.c +++ b/roms/ipxe/src/drivers/net/dmfe.c @@ -17,7 +17,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * @@ -260,15 +261,15 @@ static void dmfe_reset(struct nic *nic) db->cr0_data = 0; db->dm910x_chk_mode = 1; /* Enter the check mode */ } - /* Initilize DM910X board */ + /* Initialize DM910X board */ dmfe_init_dm910x(nic); return; } -/* Initilize DM910X board +/* Initialize DM910X board * Reset DM910X board - * Initilize TX/Rx descriptor chain structure + * Initialize TX/Rx descriptor chain structure * Send the set-up frame * Enable Tx/Rx machine */ @@ -306,7 +307,7 @@ static void dmfe_init_dm910x(struct nic *nic) if (!(db->media_mode & DMFE_AUTO)) db->op_mode = db->media_mode; /* Force Mode */ - /* Initiliaze Transmit/Receive decriptor and CR3/4 */ + /* Initiliaze Transmit/Receive descriptor and CR3/4 */ dmfe_descriptor_init(nic, ioaddr); /* tx descriptor start pointer */ @@ -571,7 +572,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr) /* * Send a setup frame for DM9132 - * This setup frame initilize DM910X addres filter mode + * This setup frame initialize DM910X address filter mode */ static void dm9132_id_table(struct nic *nic __unused) @@ -622,7 +623,7 @@ static void dm9132_id_table(struct nic *nic __unused) /* * Send a setup frame for DM9102/DM9102A - * This setup frame initilize DM910X addres filter mode + * This setup frame initialize DM910X address filter mode */ static void send_filter_frame(struct nic *nic) @@ -902,13 +903,13 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, phy_write_1bit(ioaddr, PHY_DATA_0); phy_write_1bit(ioaddr, PHY_DATA_1); - /* Send Phy addres */ + /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : @@ -958,13 +959,13 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, phy_write_1bit(ioaddr, PHY_DATA_1); phy_write_1bit(ioaddr, PHY_DATA_0); - /* Send Phy addres */ + /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : diff --git a/roms/ipxe/src/drivers/net/e1000/e1000.c b/roms/ipxe/src/drivers/net/e1000/e1000.c deleted file mode 100644 index a32a4d7c4..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000.c +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -REQUIRE_OBJECT(e1000_main); -REQUIRE_OBJECT(e1000_82540); -REQUIRE_OBJECT(e1000_82541); -REQUIRE_OBJECT(e1000_82542); -REQUIRE_OBJECT(e1000_82543); diff --git a/roms/ipxe/src/drivers/net/e1000/e1000.h b/roms/ipxe/src/drivers/net/e1000/e1000.h deleted file mode 100644 index 31dbb859a..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000.h +++ /dev/null @@ -1,326 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - 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 _E1000_H_ -#define _E1000_H_ - -#include "e1000_api.h" - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 - -struct e1000_adapter; - -/* TX/RX descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 256 -#define E1000_MIN_TXD 80 -#define E1000_MAX_82544_TXD 4096 - -#define E1000_DEFAULT_TXD_PWR 12 -#define E1000_MAX_TXD_PWR 12 -#define E1000_MIN_TXD_PWR 7 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 256 - -#define E1000_MIN_RXD 80 -#define E1000_MAX_82544_RXD 4096 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - - -/* this is the size past which hardware will drop packets when setting LPE=0 */ -#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 - -/* Supported Rx Buffer Sizes */ -#define E1000_RXBUFFER_128 128 -#define E1000_RXBUFFER_256 256 -#define E1000_RXBUFFER_512 512 -#define E1000_RXBUFFER_1024 1024 -#define E1000_RXBUFFER_2048 2048 -#define E1000_RXBUFFER_4096 4096 -#define E1000_RXBUFFER_8192 8192 -#define E1000_RXBUFFER_16384 16384 - -/* SmartSpeed delimiters */ -#define E1000_SMARTSPEED_DOWNSHIFT 3 -#define E1000_SMARTSPEED_MAX 15 - -/* Packet Buffer allocations */ -#define E1000_PBA_BYTES_SHIFT 0xA -#define E1000_TX_HEAD_ADDR_SHIFT 7 -#define E1000_PBA_TX_MASK 0xFFFF0000 - -/* Early Receive defines */ -#define E1000_ERT_2048 0x100 - -#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -#define E1000_TX_QUEUE_WAKE 16 -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0004 -#define E1000_EEPROM_APME 0x0400 - -/* wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer */ -struct e1000_buffer { - struct sk_buff *skb; - dma_addr_t dma; - unsigned long time_stamp; - u16 length; - u16 next_to_watch; -}; - -struct e1000_rx_buffer { - struct sk_buff *skb; - dma_addr_t dma; - struct page *page; -}; - - - -struct e1000_tx_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; - - spinlock_t tx_lock; - u16 tdh; - u16 tdt; - - /* TXDdescriptor index increment to be used when advancing - * to the next descriptor. This is normally one, but on some - * architectures, but on some architectures there are cache - * coherency issues that require only the first descriptor in - * cache line can be used. - */ - unsigned int step; - - bool last_tx_tso; -}; - -struct e1000_rx_ring { - struct e1000_adapter *adapter; /* back link */ - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_rx_buffer *buffer_info; - struct sk_buff *rx_skb_top; - - /* cpu for rx queue */ - int cpu; - - u16 rdh; - u16 rdt; -}; - - -#define E1000_TX_DESC_INC(R,index) \ - {index += (R)->step; if (index == (R)->count) index = 0; } - -#define E1000_TX_DESC_DEC(R,index) \ - { if (index == 0) index = (R)->count - (R)->step; \ - else index -= (R)->step; } - -#define E1000_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ - (R)->next_to_clean - (R)->next_to_use - 1) - -#define E1000_RX_DESC_EXT(R, i) \ - (&(((union e1000_rx_desc_extended *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -/* board specific private data structure */ - -struct e1000_adapter { - u32 bd_number; - u32 rx_buffer_len; - u32 wol; - u32 smartspeed; - u32 en_mng_pt; - u16 link_speed; - u16 link_duplex; - spinlock_t stats_lock; - unsigned int total_tx_bytes; - unsigned int total_tx_packets; - unsigned int total_rx_bytes; - unsigned int total_rx_packets; - /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; - - bool fc_autoneg; - - /* TX */ - struct e1000_tx_ring *tx_ring; - unsigned int restart_queue; - unsigned long tx_queue_len; - u32 txd_cmd; - u32 tx_int_delay; - u32 tx_abs_int_delay; - u32 gotc; - u64 gotc_old; - u64 tpt_old; - u64 colc_old; - u32 tx_timeout_count; - u32 tx_fifo_head; - u32 tx_head_addr; - u32 tx_fifo_size; - u8 tx_timeout_factor; - bool pcix_82544; - bool detect_tx_hung; - - /* RX */ - bool (*clean_rx) (struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); - void (*alloc_rx_buf) (struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); - struct e1000_rx_ring *rx_ring; - - u64 hw_csum_err; - u64 hw_csum_good; - u32 alloc_rx_buff_failed; - u32 rx_int_delay; - u32 rx_abs_int_delay; - bool rx_csum; - u32 gorc; - u64 gorc_old; - u32 max_frame_size; - u32 min_frame_size; - - - /* 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; - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - - int msg_enable; - /* to not mess up cache alignment, always add to the bottom */ - unsigned long state; - u32 eeprom_wol; - - u32 *config_space; - - /* hardware capability, feature, and workaround flags */ - unsigned int flags; - - /* upper limit parameter for tx desc size */ - u32 tx_desc_pwr; - -#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]; - - struct e1000_tx_desc *tx_base; - struct e1000_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; -}; - -#define E1000_FLAG_HAS_SMBUS (1 << 0) -#define E1000_FLAG_HAS_INTR_MODERATION (1 << 4) -#define E1000_FLAG_BAD_TX_CARRIER_STATS_FD (1 << 6) -#define E1000_FLAG_QUAD_PORT_A (1 << 8) -#define E1000_FLAG_SMART_POWER_DOWN (1 << 9) - -extern char e1000_driver_name[]; -extern const char e1000_driver_version[]; - -extern void e1000_power_up_phy(struct e1000_hw *hw); - -extern void e1000_set_ethtool_ops(struct net_device *netdev); -extern void e1000_check_options(struct e1000_adapter *adapter); - -extern int e1000_up(struct e1000_adapter *adapter); -extern void e1000_down(struct e1000_adapter *adapter); -extern void e1000_reinit_locked(struct e1000_adapter *adapter); -extern void e1000_reset(struct e1000_adapter *adapter); -extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx); -extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_update_stats(struct e1000_adapter *adapter); - -#endif /* _E1000_H_ */ diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82540.c b/roms/ipxe/src/drivers/net/e1000/e1000_82540.c deleted file mode 100644 index 41f3f979f..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82540.c +++ /dev/null @@ -1,754 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82540EM Gigabit Ethernet Controller - * 82540EP Gigabit Ethernet Controller - * 82545EM Gigabit Ethernet Controller (Copper) - * 82545EM Gigabit Ethernet Controller (Fiber) - * 82545GM Gigabit Ethernet Controller - * 82546EB Gigabit Ethernet Controller (Copper) - * 82546EB Gigabit Ethernet Controller (Fiber) - * 82546GB Gigabit Ethernet Controller - */ - -#include "e1000_api.h" - -static s32 e1000_init_phy_params_82540(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw); -static s32 e1000_init_mac_params_82540(struct e1000_hw *hw); -static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw); -static s32 e1000_init_hw_82540(struct e1000_hw *hw); -static s32 e1000_reset_hw_82540(struct e1000_hw *hw); -static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw); -static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw); -static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw); -static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw); -static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw); -static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw); - -/** - * e1000_init_phy_params_82540 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82540(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 10000; - phy->type = e1000_phy_m88; - - /* Function Pointers */ - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.commit = e1000_phy_sw_reset_generic; -#if 0 - phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; -#endif -#if 0 - phy->ops.get_cable_length = e1000_get_cable_length_m88; -#endif - phy->ops.get_cfg_done = e1000_get_cfg_done_generic; - phy->ops.read_reg = e1000_read_phy_reg_m88; - phy->ops.reset = e1000_phy_hw_reset_generic; - phy->ops.write_reg = e1000_write_phy_reg_m88; - phy->ops.get_info = e1000_get_phy_info_m88; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82540; - - ret_val = e1000_get_phy_id(hw); - if (ret_val) - goto out; - - /* Verify phy id */ - switch (hw->mac.type) { - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - if (phy->id == M88E1011_I_PHY_ID) - break; - /* Fall Through */ - default: - ret_val = -E1000_ERR_PHY; - goto out; - break; - } - -out: - return ret_val; -} - -/** - * e1000_init_nvm_params_82540 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - - DEBUGFUNC("e1000_init_nvm_params_82540"); - - nvm->type = e1000_nvm_eeprom_microwire; - nvm->delay_usec = 50; - nvm->opcode_bits = 3; - switch (nvm->override) { - case e1000_nvm_override_microwire_large: - nvm->address_bits = 8; - nvm->word_size = 256; - break; - case e1000_nvm_override_microwire_small: - nvm->address_bits = 6; - nvm->word_size = 64; - break; - default: - nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6; - nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64; - break; - } - - /* Function Pointers */ - nvm->ops.acquire = e1000_acquire_nvm_generic; - nvm->ops.read = e1000_read_nvm_microwire; - nvm->ops.release = e1000_release_nvm_generic; - nvm->ops.update = e1000_update_nvm_checksum_generic; - nvm->ops.valid_led_default = e1000_valid_led_default_generic; - nvm->ops.validate = e1000_validate_nvm_checksum_generic; - nvm->ops.write = e1000_write_nvm_microwire; - - return E1000_SUCCESS; -} - -/** - * e1000_init_mac_params_82540 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82540(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_init_mac_params_82540"); - - /* Set media type */ - switch (hw->device_id) { - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82545GM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - hw->phy.media_type = e1000_media_type_fiber; - break; - case E1000_DEV_ID_82545GM_SERDES: - case E1000_DEV_ID_82546GB_SERDES: - hw->phy.media_type = e1000_media_type_internal_serdes; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; - /* function id */ - mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; - /* reset */ - mac->ops.reset_hw = e1000_reset_hw_82540; - /* hw initialization */ - mac->ops.init_hw = e1000_init_hw_82540; - /* link setup */ - mac->ops.setup_link = e1000_setup_link_generic; - /* physical interface setup */ - mac->ops.setup_physical_interface = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000_setup_copper_link_82540 - : e1000_setup_fiber_serdes_link_82540; - /* check for link */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - mac->ops.check_for_link = e1000_check_for_copper_link_generic; - break; - case e1000_media_type_fiber: - mac->ops.check_for_link = e1000_check_for_fiber_link_generic; - break; - case e1000_media_type_internal_serdes: - mac->ops.check_for_link = e1000_check_for_serdes_link_generic; - break; - default: - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - /* link info */ - mac->ops.get_link_up_info = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000_get_speed_and_duplex_copper_generic - : e1000_get_speed_and_duplex_fiber_serdes_generic; - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000_clear_vfta_generic; - /* setting MTA */ - mac->ops.mta_set = e1000_mta_set_generic; - /* read mac address */ - mac->ops.read_mac_addr = e1000_read_mac_addr_82540; - /* ID LED init */ - mac->ops.id_led_init = e1000_id_led_init_generic; - /* setup LED */ - mac->ops.setup_led = e1000_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_generic; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_generic; - mac->ops.led_off = e1000_led_off_generic; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540; - -out: - return ret_val; -} - -/** - * e1000_init_function_pointers_82540 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000_init_function_pointers_82540(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_init_function_pointers_82540"); - - hw->mac.ops.init_params = e1000_init_mac_params_82540; - hw->nvm.ops.init_params = e1000_init_nvm_params_82540; - hw->phy.ops.init_params = e1000_init_phy_params_82540; -} - -/** - * e1000_reset_hw_82540 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82540(struct e1000_hw *hw) -{ - u32 ctrl, manc; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_reset_hw_82540"); - - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); - - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - /* - * Delay to allow any outstanding PCI transactions to complete - * before resetting the device. - */ - msec_delay(10); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n"); - switch (hw->mac.type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST); - break; - default: - /* - * These controllers can't ack the 64-bit write when - * issuing the reset, so we use IO-mapping as a - * workaround to issue the reset. - */ - E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - break; - } - - /* Wait for EEPROM reload */ - msec_delay(5); - - /* Disable HW ARPs on ASF enabled adapters */ - manc = E1000_READ_REG(hw, E1000_MANC); - manc &= ~E1000_MANC_ARP_EN; - E1000_WRITE_REG(hw, E1000_MANC, manc); - - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - E1000_READ_REG(hw, E1000_ICR); - - return ret_val; -} - -/** - * e1000_init_hw_82540 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82540(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txdctl, ctrl_ext; - s32 ret_val = E1000_SUCCESS; - u16 i; - - DEBUGFUNC("e1000_init_hw_82540"); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) { - DEBUGOUT("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ - } - - /* Disabling VLAN filtering */ - DEBUGOUT("Initializing the IEEE VLAN\n"); - if (mac->type < e1000_82545_rev_3) - E1000_WRITE_REG(hw, E1000_VET, 0); - - mac->ops.clear_vfta(hw); - - /* Setup the receive address. */ - e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - /* - * Avoid back to back register writes by adding the register - * read (flush). This is to protect against some strange - * bridge configurations that may issue Memory Write Block - * (MWB) to our register space. The *_rev_3 hardware at - * least doesn't respond correctly to every other dword in an - * MWB to our register space. - */ - E1000_WRITE_FLUSH(hw); - } - - if (mac->type < e1000_82545_rev_3) - e1000_pcix_mmrbc_workaround_generic(hw); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); - txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82540(hw); - - if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) || - (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) { - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - /* - * Relaxed ordering must be disabled to avoid a parity - * error crash in a PCI slot. - */ - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - } - - return ret_val; -} - -/** - * e1000_setup_copper_link_82540 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - u16 data; - - DEBUGFUNC("e1000_setup_copper_link_82540"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - ret_val = e1000_set_phy_mode_82540(hw); - if (ret_val) - goto out; - - if (hw->mac.type == e1000_82545_rev_3 || - hw->mac.type == e1000_82546_rev_3) { - ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data); - if (ret_val) - goto out; - data |= 0x00000008; - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data); - if (ret_val) - goto out; - } - - ret_val = e1000_copper_link_setup_m88(hw); - if (ret_val) - goto out; - - ret_val = e1000_setup_copper_link_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Set the output amplitude to the value in the EEPROM and adjust the VCO - * speed to improve Bit Error Rate (BER) performance. Configures collision - * distance and flow control for fiber and serdes links. Upon successful - * setup, poll for link. - **/ -static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_fiber_serdes_link_82540"); - - switch (mac->type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - if (hw->phy.media_type == e1000_media_type_internal_serdes) { - /* - * If we're on serdes media, adjust the output - * amplitude to value set in the EEPROM. - */ - ret_val = e1000_adjust_serdes_amplitude_82540(hw); - if (ret_val) - goto out; - } - /* Adjust VCO speed to improve BER performance */ - ret_val = e1000_set_vco_speed_82540(hw); - if (ret_val) - goto out; - default: - break; - } - - ret_val = e1000_setup_fiber_serdes_link_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM - * @hw: pointer to the HW structure - * - * Adjust the SERDES output amplitude based on the EEPROM settings. - **/ -static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 nvm_data; - - DEBUGFUNC("e1000_adjust_serdes_amplitude_82540"); - - ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data); - if (ret_val) - goto out; - - if (nvm_data != NVM_RESERVED_WORD) { - /* Adjust serdes output amplitude only. */ - nvm_data &= NVM_SERDES_AMPLITUDE_MASK; - ret_val = hw->phy.ops.write_reg(hw, - M88E1000_PHY_EXT_CTRL, - nvm_data); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_set_vco_speed_82540 - Set VCO speed for better performance - * @hw: pointer to the HW structure - * - * Set the VCO speed to improve Bit Error Rate (BER) performance. - **/ -static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 default_page = 0; - u16 phy_data; - - DEBUGFUNC("e1000_set_vco_speed_82540"); - - /* Set PHY register 30, page 5, bit 8 to 0 */ - - ret_val = hw->phy.ops.read_reg(hw, - M88E1000_PHY_PAGE_SELECT, - &default_page); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - goto out; - - /* Set PHY register 30, page 4, bit 11 to 1 */ - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PHY_VCO_REG_BIT11; - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, - default_page); - -out: - return ret_val; -} - -/** - * e1000_set_phy_mode_82540 - Set PHY to class A mode - * @hw: pointer to the HW structure - * - * Sets the PHY to class A mode and assumes the following operations will - * follow to enable the new class mode: - * 1. Do a PHY soft reset. - * 2. Restart auto-negotiation or force link. - **/ -static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 nvm_data; - - DEBUGFUNC("e1000_set_phy_mode_82540"); - - if (hw->mac.type != e1000_82545_rev_3) - goto out; - - ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data); - if (ret_val) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) { - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, - 0x000B); - if (ret_val) { - ret_val = -E1000_ERR_PHY; - goto out; - } - ret_val = hw->phy.ops.write_reg(hw, - M88E1000_PHY_GEN_CONTROL, - 0x8104); - if (ret_val) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - phy->reset_disable = false; - } - -out: - return ret_val; -} - -/** - * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) - e1000_power_down_phy_copper(hw); - - return; -} - -/** - * e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_clear_hw_cntrs_82540"); - - e1000_clear_hw_cntrs_base_generic(hw); - -#if 0 - E1000_READ_REG(hw, E1000_PRC64); - E1000_READ_REG(hw, E1000_PRC127); - E1000_READ_REG(hw, E1000_PRC255); - E1000_READ_REG(hw, E1000_PRC511); - E1000_READ_REG(hw, E1000_PRC1023); - E1000_READ_REG(hw, E1000_PRC1522); - E1000_READ_REG(hw, E1000_PTC64); - E1000_READ_REG(hw, E1000_PTC127); - E1000_READ_REG(hw, E1000_PTC255); - E1000_READ_REG(hw, E1000_PTC511); - E1000_READ_REG(hw, E1000_PTC1023); - E1000_READ_REG(hw, E1000_PTC1522); - - E1000_READ_REG(hw, E1000_ALGNERRC); - E1000_READ_REG(hw, E1000_RXERRC); - E1000_READ_REG(hw, E1000_TNCRS); - E1000_READ_REG(hw, E1000_CEXTERR); - E1000_READ_REG(hw, E1000_TSCTC); - E1000_READ_REG(hw, E1000_TSCTFC); - - E1000_READ_REG(hw, E1000_MGTPRC); - E1000_READ_REG(hw, E1000_MGTPDC); - E1000_READ_REG(hw, E1000_MGTPTC); -#endif -} - -/** - * e1000_read_mac_addr_82540 - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - * - * This version is being used over generic because of customer issues - * with VmWare and Virtual Box when using generic. It seems in - * the emulated 82545, RAR[0] does NOT have a valid address after a - * reset, this older method works and using this breaks nothing for - * these legacy adapters. - **/ -s32 e1000_read_mac_addr_82540(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 offset, nvm_data, i; - - DEBUGFUNC("e1000_read_mac_addr"); - - for (i = 0; i < ETH_ADDR_LEN; i += 2) { - offset = i >> 1; - ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); - hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); - } - - /* Flip last bit of mac address if we're on second port */ - if (hw->bus.func == E1000_FUNC_1) - hw->mac.perm_addr[5] ^= 1; - - for (i = 0; i < ETH_ADDR_LEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - -out: - return ret_val; -} - -static struct pci_device_id e1000_82540_nics[] = { - PCI_ROM(0x8086, 0x100E, "E1000_DEV_ID_82540EM", "E1000_DEV_ID_82540EM", e1000_82540), - PCI_ROM(0x8086, 0x1015, "E1000_DEV_ID_82540EM_LOM", "E1000_DEV_ID_82540EM_LOM", e1000_82540), - PCI_ROM(0x8086, 0x1016, "E1000_DEV_ID_82540EP_LOM", "E1000_DEV_ID_82540EP_LOM", e1000_82540), - PCI_ROM(0x8086, 0x1017, "E1000_DEV_ID_82540EP", "E1000_DEV_ID_82540EP", e1000_82540), - PCI_ROM(0x8086, 0x101E, "E1000_DEV_ID_82540EP_LP", "E1000_DEV_ID_82540EP_LP", e1000_82540), - PCI_ROM(0x8086, 0x100F, "E1000_DEV_ID_82545EM_COPPER", "E1000_DEV_ID_82545EM_COPPER", e1000_82545), - PCI_ROM(0x8086, 0x1011, "E1000_DEV_ID_82545EM_FIBER", "E1000_DEV_ID_82545EM_FIBER", e1000_82545), - PCI_ROM(0x8086, 0x1026, "E1000_DEV_ID_82545GM_COPPER", "E1000_DEV_ID_82545GM_COPPER", e1000_82545_rev_3), - PCI_ROM(0x8086, 0x1027, "E1000_DEV_ID_82545GM_FIBER", "E1000_DEV_ID_82545GM_FIBER", e1000_82545_rev_3), - PCI_ROM(0x8086, 0x1028, "E1000_DEV_ID_82545GM_SERDES", "E1000_DEV_ID_82545GM_SERDES", e1000_82545_rev_3), - PCI_ROM(0x8086, 0x1010, "E1000_DEV_ID_82546EB_COPPER", "E1000_DEV_ID_82546EB_COPPER", e1000_82546), - PCI_ROM(0x8086, 0x1012, "E1000_DEV_ID_82546EB_FIBER", "E1000_DEV_ID_82546EB_FIBER", e1000_82546), - PCI_ROM(0x8086, 0x101D, "E1000_DEV_ID_82546EB_QUAD_COPPER", "E1000_DEV_ID_82546EB_QUAD_COPPER", e1000_82546), - PCI_ROM(0x8086, 0x1079, "E1000_DEV_ID_82546GB_COPPER", "E1000_DEV_ID_82546GB_COPPER", e1000_82546_rev_3), - PCI_ROM(0x8086, 0x107A, "E1000_DEV_ID_82546GB_FIBER", "E1000_DEV_ID_82546GB_FIBER", e1000_82546_rev_3), - PCI_ROM(0x8086, 0x107B, "E1000_DEV_ID_82546GB_SERDES", "E1000_DEV_ID_82546GB_SERDES", e1000_82546_rev_3), - PCI_ROM(0x8086, 0x108A, "E1000_DEV_ID_82546GB_PCIE", "E1000_DEV_ID_82546GB_PCIE", e1000_82546_rev_3), - PCI_ROM(0x8086, 0x1099, "E1000_DEV_ID_82546GB_QUAD_COPPER", "E1000_DEV_ID_82546GB_QUAD_COPPER", e1000_82546_rev_3), - PCI_ROM(0x8086, 0x10B5, "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", e1000_82546_rev_3), -}; - -struct pci_driver e1000_82540_driver __pci_driver = { - .ids = e1000_82540_nics, - .id_count = (sizeof (e1000_82540_nics) / sizeof (e1000_82540_nics[0])), - .probe = e1000_probe, - .remove = e1000_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82541.c b/roms/ipxe/src/drivers/net/e1000/e1000_82541.c deleted file mode 100644 index 2d1aecc70..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82541.c +++ /dev/null @@ -1,1314 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82541EI Gigabit Ethernet Controller - * 82541ER Gigabit Ethernet Controller - * 82541GI Gigabit Ethernet Controller - * 82541PI Gigabit Ethernet Controller - * 82547EI Gigabit Ethernet Controller - * 82547GI Gigabit Ethernet Controller - */ - -#include "e1000_api.h" - -static s32 e1000_init_phy_params_82541(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw); -static s32 e1000_init_mac_params_82541(struct e1000_hw *hw); -static s32 e1000_reset_hw_82541(struct e1000_hw *hw); -static s32 e1000_init_hw_82541(struct e1000_hw *hw); -static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw); -static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw); -static s32 e1000_check_for_link_82541(struct e1000_hw *hw); -#if 0 -static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw); -#endif -static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, - bool active); -static s32 e1000_setup_led_82541(struct e1000_hw *hw); -static s32 e1000_cleanup_led_82541(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw); -#if 0 -static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, - bool link_up); -#endif -static s32 e1000_phy_init_script_82541(struct e1000_hw *hw); -static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw); - -#if 0 -static const u16 e1000_igp_cable_length_table[] = - { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; -#define IGP01E1000_AGC_LENGTH_TABLE_SIZE \ - (sizeof(e1000_igp_cable_length_table) / \ - sizeof(e1000_igp_cable_length_table[0])) -#endif -/** - * e1000_init_phy_params_82541 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82541(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_init_phy_params_82541"); - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 10000; - phy->type = e1000_phy_igp; - - /* Function Pointers */ - phy->ops.check_polarity = e1000_check_polarity_igp; -#if 0 - phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; -#endif -#if 0 - phy->ops.get_cable_length = e1000_get_cable_length_igp_82541; -#endif - phy->ops.get_cfg_done = e1000_get_cfg_done_generic; - phy->ops.get_info = e1000_get_phy_info_igp; - phy->ops.read_reg = e1000_read_phy_reg_igp; - phy->ops.reset = e1000_phy_hw_reset_82541; - phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541; - phy->ops.write_reg = e1000_write_phy_reg_igp; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82541; - - ret_val = e1000_get_phy_id(hw); - if (ret_val) - goto out; - - /* Verify phy id */ - if (phy->id != IGP01E1000_I_PHY_ID) { - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_init_nvm_params_82541 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val = E1000_SUCCESS; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - u16 size; - - DEBUGFUNC("e1000_init_nvm_params_82541"); - - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->type = e1000_nvm_eeprom_spi; - eecd |= E1000_EECD_ADDR_BITS; - break; - case e1000_nvm_override_spi_small: - nvm->type = e1000_nvm_eeprom_spi; - eecd &= ~E1000_EECD_ADDR_BITS; - break; - case e1000_nvm_override_microwire_large: - nvm->type = e1000_nvm_eeprom_microwire; - eecd |= E1000_EECD_SIZE; - break; - case e1000_nvm_override_microwire_small: - nvm->type = e1000_nvm_eeprom_microwire; - eecd &= ~E1000_EECD_SIZE; - break; - default: - nvm->type = eecd & E1000_EECD_TYPE - ? e1000_nvm_eeprom_spi - : e1000_nvm_eeprom_microwire; - break; - } - - if (nvm->type == e1000_nvm_eeprom_spi) { - nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) - ? 16 : 8; - nvm->delay_usec = 1; - nvm->opcode_bits = 8; - nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) - ? 32 : 8; - - /* Function Pointers */ - nvm->ops.acquire = e1000_acquire_nvm_generic; - nvm->ops.read = e1000_read_nvm_spi; - nvm->ops.release = e1000_release_nvm_generic; - nvm->ops.update = e1000_update_nvm_checksum_generic; - nvm->ops.valid_led_default = e1000_valid_led_default_generic; - nvm->ops.validate = e1000_validate_nvm_checksum_generic; - nvm->ops.write = e1000_write_nvm_spi; - - /* - * nvm->word_size must be discovered after the pointers - * are set so we can verify the size from the nvm image - * itself. Temporarily set it to a dummy value so the - * read will work. - */ - nvm->word_size = 64; - ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size); - if (ret_val) - goto out; - size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT; - /* - * if size != 0, it can be added to a constant and become - * the left-shift value to set the word_size. Otherwise, - * word_size stays at 64. - */ - if (size) { - size += NVM_WORD_SIZE_BASE_SHIFT_82541; - nvm->word_size = 1 << size; - } - } else { - nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) - ? 8 : 6; - nvm->delay_usec = 50; - nvm->opcode_bits = 3; - nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) - ? 256 : 64; - - /* Function Pointers */ - nvm->ops.acquire = e1000_acquire_nvm_generic; - nvm->ops.read = e1000_read_nvm_microwire; - nvm->ops.release = e1000_release_nvm_generic; - nvm->ops.update = e1000_update_nvm_checksum_generic; - nvm->ops.valid_led_default = e1000_valid_led_default_generic; - nvm->ops.validate = e1000_validate_nvm_checksum_generic; - nvm->ops.write = e1000_write_nvm_microwire; - } - -out: - return ret_val; -} - -/** - * e1000_init_mac_params_82541 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82541(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("e1000_init_mac_params_82541"); - - /* Set media type */ - hw->phy.media_type = e1000_media_type_copper; - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* Set if part includes ASF firmware */ - mac->asf_firmware_present = true; - - /* Function Pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; - /* function id */ - mac->ops.set_lan_id = e1000_set_lan_id_single_port; - /* reset */ - mac->ops.reset_hw = e1000_reset_hw_82541; - /* hw initialization */ - mac->ops.init_hw = e1000_init_hw_82541; - /* link setup */ - mac->ops.setup_link = e1000_setup_link_generic; - /* physical interface link setup */ - mac->ops.setup_physical_interface = e1000_setup_copper_link_82541; - /* check for link */ - mac->ops.check_for_link = e1000_check_for_link_82541; - /* link info */ - mac->ops.get_link_up_info = e1000_get_link_up_info_82541; - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000_clear_vfta_generic; - /* setting MTA */ - mac->ops.mta_set = e1000_mta_set_generic; - /* ID LED init */ - mac->ops.id_led_init = e1000_id_led_init_generic; - /* setup LED */ - mac->ops.setup_led = e1000_setup_led_82541; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_82541; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_generic; - mac->ops.led_off = e1000_led_off_generic; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541; - - return E1000_SUCCESS; -} - -/** - * e1000_init_function_pointers_82541 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000_init_function_pointers_82541(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_init_function_pointers_82541"); - - hw->mac.ops.init_params = e1000_init_mac_params_82541; - hw->nvm.ops.init_params = e1000_init_nvm_params_82541; - hw->phy.ops.init_params = e1000_init_phy_params_82541; -} - -/** - * e1000_reset_hw_82541 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82541(struct e1000_hw *hw) -{ - u32 ledctl, ctrl, manc; - - DEBUGFUNC("e1000_reset_hw_82541"); - - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); - - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - /* - * Delay to allow any outstanding PCI transactions to complete - * before resetting the device. - */ - msec_delay(10); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Must reset the Phy before resetting the MAC */ - if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); - msec_delay(5); - } - - DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n"); - switch (hw->mac.type) { - case e1000_82541: - case e1000_82541_rev_2: - /* - * These controllers can't ack the 64-bit write when - * issuing the reset, so we use IO-mapping as a - * workaround to issue the reset. - */ - E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - break; - default: - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - break; - } - - /* Wait for NVM reload */ - msec_delay(20); - - /* Disable HW ARPs on ASF enabled adapters */ - manc = E1000_READ_REG(hw, E1000_MANC); - manc &= ~E1000_MANC_ARP_EN; - E1000_WRITE_REG(hw, E1000_MANC, manc); - - if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { - e1000_phy_init_script_82541(hw); - - /* Configure activity LED after Phy reset */ - ledctl = E1000_READ_REG(hw, E1000_LEDCTL); - ledctl &= IGP_ACTIVITY_LED_MASK; - ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); - } - - /* Once again, mask the interrupts */ - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); - - /* Clear any pending interrupt events. */ - E1000_READ_REG(hw, E1000_ICR); - - return E1000_SUCCESS; -} - -/** - * e1000_init_hw_82541 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82541(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - u32 i, txdctl; - s32 ret_val; - - DEBUGFUNC("e1000_init_hw_82541"); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) { - DEBUGOUT("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ - } - - /* Storing the Speed Power Down value for later use */ - ret_val = hw->phy.ops.read_reg(hw, - IGP01E1000_GMII_FIFO, - &dev_spec->spd_default); - if (ret_val) - goto out; - - /* Disabling VLAN filtering */ - DEBUGOUT("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. */ - e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - /* - * Avoid back to back register writes by adding the register - * read (flush). This is to protect against some strange - * bridge configurations that may issue Memory Write Block - * (MWB) to our register space. - */ - E1000_WRITE_FLUSH(hw); - } - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); - txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82541(hw); - -out: - return ret_val; -} - -/** - * e1000_get_link_up_info_82541 - Report speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to speed buffer - * @duplex: pointer to duplex buffer - * - * Retrieve the current speed and duplex configuration. - **/ -static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("e1000_get_link_up_info_82541"); - - ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); - if (ret_val) - goto out; - - if (!phy->speed_downgraded) - goto out; - - /* - * IGP01 PHY may advertise full duplex operation after speed - * downgrade even if it is operating at half duplex. - * Here we set the duplex settings to match the duplex in the - * link partner's capabilities. - */ - ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data); - if (ret_val) - goto out; - - if (!(data & NWAY_ER_LP_NWAY_CAPS)) { - *duplex = HALF_DUPLEX; - } else { - ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data); - if (ret_val) - goto out; - - if (*speed == SPEED_100) { - if (!(data & NWAY_LPAR_100TX_FD_CAPS)) - *duplex = HALF_DUPLEX; - } else if (*speed == SPEED_10) { - if (!(data & NWAY_LPAR_10T_FD_CAPS)) - *duplex = HALF_DUPLEX; - } - } - -out: - return ret_val; -} - -/** - * e1000_phy_hw_reset_82541 - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw) -{ - s32 ret_val; - u32 ledctl; - - DEBUGFUNC("e1000_phy_hw_reset_82541"); - - ret_val = e1000_phy_hw_reset_generic(hw); - if (ret_val) - goto out; - - e1000_phy_init_script_82541(hw); - - if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { - /* Configure activity LED after PHY reset */ - ledctl = E1000_READ_REG(hw, E1000_LEDCTL); - ledctl &= IGP_ACTIVITY_LED_MASK; - ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); - } - -out: - return ret_val; -} - -/** - * e1000_setup_copper_link_82541 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - s32 ret_val; - u32 ctrl, ledctl; - - DEBUGFUNC("e1000_setup_copper_link_82541"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - hw->phy.reset_disable = false; - - /* Earlier revs of the IGP phy require us to force MDI. */ - if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) { - dev_spec->dsp_config = e1000_dsp_config_disabled; - phy->mdix = 1; - } else { - dev_spec->dsp_config = e1000_dsp_config_enabled; - } - - ret_val = e1000_copper_link_setup_igp(hw); - if (ret_val) - goto out; - - if (hw->mac.autoneg) { - if (dev_spec->ffe_config == e1000_ffe_config_active) - dev_spec->ffe_config = e1000_ffe_config_enabled; - } - - /* Configure activity LED after Phy reset */ - ledctl = E1000_READ_REG(hw, E1000_LEDCTL); - ledctl &= IGP_ACTIVITY_LED_MASK; - ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); - - ret_val = e1000_setup_copper_link_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_check_for_link_82541 - Check/Store link connection - * @hw: pointer to the HW structure - * - * This checks the link condition of the adapter and stores the - * results in the hw->mac structure. - **/ -static s32 e1000_check_for_link_82541(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - DEBUGFUNC("e1000_check_for_link_82541"); - - /* - * We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - ret_val = -E1000_ERR_CONFIG; -#if 0 - ret_val = e1000_config_dsp_after_link_change_82541(hw, false); -#endif - goto out; /* No link detected */ - } - - mac->get_link_status = false; - - /* - * Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000_check_downshift_generic(hw); - - /* - * If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -#if 0 - ret_val = e1000_config_dsp_after_link_change_82541(hw, true); -#endif - - /* - * Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - e1000_config_collision_dist_generic(hw); - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - } - -out: - return ret_val; -} - -#if 0 -/** - * e1000_config_dsp_after_link_change_82541 - Config DSP after link - * @hw: pointer to the HW structure - * @link_up: boolean flag for link up status - * - * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS - * at any other case. - * - * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a - * gigabit link is achieved to improve link quality. - **/ -static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, - bool link_up) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - s32 ret_val; - u32 idle_errs = 0; - u16 phy_data, phy_saved_data, speed, duplex, i; - u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; - u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = - {IGP01E1000_PHY_AGC_PARAM_A, - IGP01E1000_PHY_AGC_PARAM_B, - IGP01E1000_PHY_AGC_PARAM_C, - IGP01E1000_PHY_AGC_PARAM_D}; - - DEBUGFUNC("e1000_config_dsp_after_link_change_82541"); - - if (link_up) { - ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - DEBUGOUT("Error getting link speed and duplex\n"); - goto out; - } - - if (speed != SPEED_1000) { - ret_val = E1000_SUCCESS; - goto out; - } - -#if 0 - ret_val = phy->ops.get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; - - if ((dev_spec->dsp_config == e1000_dsp_config_enabled) && - phy->min_cable_length >= 50) { - - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = phy->ops.read_reg(hw, - dsp_reg_array[i], - &phy_data); - if (ret_val) - goto out; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - - ret_val = phy->ops.write_reg(hw, - dsp_reg_array[i], - phy_data); - if (ret_val) - goto out; - } - dev_spec->dsp_config = e1000_dsp_config_activated; - } - - if ((dev_spec->ffe_config != e1000_ffe_config_enabled) || - (phy->min_cable_length >= 50)) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* clear previous idle error counts */ - ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - goto out; - - for (i = 0; i < ffe_idle_err_timeout; i++) { - usec_delay(1000); - ret_val = phy->ops.read_reg(hw, - PHY_1000T_STATUS, - &phy_data); - if (ret_val) - goto out; - - idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); - if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { - dev_spec->ffe_config = e1000_ffe_config_active; - - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_CM_CP); - if (ret_val) - goto out; - break; - } - - if (idle_errs) - ffe_idle_err_timeout = - FFE_IDLE_ERR_COUNT_TIMEOUT_100; - } - } else { - if (dev_spec->dsp_config == e1000_dsp_config_activated) { - /* - * Save off the current value of register 0x2F5B - * to be restored at the end of the routines. - */ - ret_val = phy->ops.read_reg(hw, - 0x2F5B, - &phy_saved_data); - if (ret_val) - goto out; - - /* Disable the PHY transmitter */ - ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); - if (ret_val) - goto out; - - msec_delay_irq(20); - - ret_val = phy->ops.write_reg(hw, - 0x0000, - IGP01E1000_IEEE_FORCE_GIG); - if (ret_val) - goto out; - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = phy->ops.read_reg(hw, - dsp_reg_array[i], - &phy_data); - if (ret_val) - goto out; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; - - ret_val = phy->ops.write_reg(hw, - dsp_reg_array[i], - phy_data); - if (ret_val) - goto out; - } - - ret_val = phy->ops.write_reg(hw, - 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - goto out; - - msec_delay_irq(20); - - /* Now enable the transmitter */ - ret_val = phy->ops.write_reg(hw, - 0x2F5B, - phy_saved_data); - if (ret_val) - goto out; - - dev_spec->dsp_config = e1000_dsp_config_enabled; - } - - if (dev_spec->ffe_config != e1000_ffe_config_active) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * Save off the current value of register 0x2F5B - * to be restored at the end of the routines. - */ - ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data); - if (ret_val) - goto out; - - /* Disable the PHY transmitter */ - ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); - if (ret_val) - goto out; - - msec_delay_irq(20); - - ret_val = phy->ops.write_reg(hw, - 0x0000, - IGP01E1000_IEEE_FORCE_GIG); - if (ret_val) - goto out; - - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_DEFAULT); - if (ret_val) - goto out; - - ret_val = phy->ops.write_reg(hw, - 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - goto out; - - msec_delay_irq(20); - - /* Now enable the transmitter */ - ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data); - - if (ret_val) - goto out; - - dev_spec->ffe_config = e1000_ffe_config_enabled; - } - -out: - return ret_val; -} -#endif - -#if 0 -/** - * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 i, data; - u16 cur_agc_value, agc_value = 0; - u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; - u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = - {IGP01E1000_PHY_AGC_A, - IGP01E1000_PHY_AGC_B, - IGP01E1000_PHY_AGC_C, - IGP01E1000_PHY_AGC_D}; - - DEBUGFUNC("e1000_get_cable_length_igp_82541"); - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data); - if (ret_val) - goto out; - - cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT; - - /* Bounds checking */ - if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || - (cur_agc_value == 0)) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - agc_value += cur_agc_value; - - if (min_agc_value > cur_agc_value) - min_agc_value = cur_agc_value; - } - - /* Remove the minimal AGC result for length < 50m */ - if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) { - agc_value -= min_agc_value; - /* Average the three remaining channels for the length. */ - agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); - } else { - /* Average the channels for the length. */ - agc_value /= IGP01E1000_PHY_CHANNEL_NUM; - } - - phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] > - IGP01E1000_AGC_RANGE) - ? (e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) - : 0; - phy->max_cable_length = e1000_igp_cable_length_table[agc_value] + - IGP01E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} -#endif - -/** - * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("e1000_set_d3_lplu_state_82541"); - - switch (hw->mac.type) { - case e1000_82541_rev_2: - case e1000_82547_rev_2: - break; - default: - ret_val = e1000_set_d3_lplu_state_generic(hw, active); - goto out; - break; - } - - ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data); - if (ret_val) - goto out; - - if (!active) { - data &= ~IGP01E1000_GMII_FLEX_SPD; - ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); - if (ret_val) - goto out; - - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP01E1000_GMII_FLEX_SPD; - ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - } - -out: - return ret_val; -} - -/** - * e1000_setup_led_82541 - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -static s32 e1000_setup_led_82541(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - s32 ret_val; - - DEBUGFUNC("e1000_setup_led_82541"); - - ret_val = hw->phy.ops.read_reg(hw, - IGP01E1000_GMII_FIFO, - &dev_spec->spd_default); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, - IGP01E1000_GMII_FIFO, - (u16)(dev_spec->spd_default & - ~IGP01E1000_GMII_SPD)); - if (ret_val) - goto out; - - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_cleanup_led_82541 - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -static s32 e1000_cleanup_led_82541(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - s32 ret_val; - - DEBUGFUNC("e1000_cleanup_led_82541"); - - ret_val = hw->phy.ops.write_reg(hw, - IGP01E1000_GMII_FIFO, - dev_spec->spd_default); - if (ret_val) - goto out; - - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_phy_init_script_82541 - Initialize GbE PHY - * @hw: pointer to the HW structure - * - * Initializes the IGP PHY. - **/ -static s32 e1000_phy_init_script_82541(struct e1000_hw *hw) -{ - struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; - u32 ret_val; - u16 phy_saved_data; - - DEBUGFUNC("e1000_phy_init_script_82541"); - - if (!dev_spec->phy_init_script) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Delay after phy reset to enable NVM configuration to load */ - msec_delay(20); - - /* - * Save off the current value of register 0x2F5B to be restored at - * the end of this routine. - */ - ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data); - - /* Disabled the PHY transmitter */ - hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003); - - msec_delay(20); - - hw->phy.ops.write_reg(hw, 0x0000, 0x0140); - - msec_delay(5); - - switch (hw->mac.type) { - case e1000_82541: - case e1000_82547: - hw->phy.ops.write_reg(hw, 0x1F95, 0x0001); - - hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21); - - hw->phy.ops.write_reg(hw, 0x1F79, 0x0018); - - hw->phy.ops.write_reg(hw, 0x1F30, 0x1600); - - hw->phy.ops.write_reg(hw, 0x1F31, 0x0014); - - hw->phy.ops.write_reg(hw, 0x1F32, 0x161C); - - hw->phy.ops.write_reg(hw, 0x1F94, 0x0003); - - hw->phy.ops.write_reg(hw, 0x1F96, 0x003F); - - hw->phy.ops.write_reg(hw, 0x2010, 0x0008); - break; - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->phy.ops.write_reg(hw, 0x1F73, 0x0099); - break; - default: - break; - } - - hw->phy.ops.write_reg(hw, 0x0000, 0x3300); - - msec_delay(20); - - /* Now enable the transmitter */ - hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data); - - if (hw->mac.type == e1000_82547) { - u16 fused, fine, coarse; - - /* Move to analog registers page */ - hw->phy.ops.read_reg(hw, - IGP01E1000_ANALOG_SPARE_FUSE_STATUS, - &fused); - - if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { - hw->phy.ops.read_reg(hw, - IGP01E1000_ANALOG_FUSE_STATUS, - &fused); - - fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; - coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; - - if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { - coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; - fine -= IGP01E1000_ANALOG_FUSE_FINE_1; - } else if (coarse == - IGP01E1000_ANALOG_FUSE_COARSE_THRESH) - fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - - fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | - (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); - - hw->phy.ops.write_reg(hw, - IGP01E1000_ANALOG_FUSE_CONTROL, - fused); - hw->phy.ops.write_reg(hw, - IGP01E1000_ANALOG_FUSE_BYPASS, - IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); - } - } - -out: - return ret_val; -} - -/** - * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) - e1000_power_down_phy_copper(hw); - - return; -} - -/** - * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_clear_hw_cntrs_82541"); - - e1000_clear_hw_cntrs_base_generic(hw); - -#if 0 - E1000_READ_REG(hw, E1000_PRC64); - E1000_READ_REG(hw, E1000_PRC127); - E1000_READ_REG(hw, E1000_PRC255); - E1000_READ_REG(hw, E1000_PRC511); - E1000_READ_REG(hw, E1000_PRC1023); - E1000_READ_REG(hw, E1000_PRC1522); - E1000_READ_REG(hw, E1000_PTC64); - E1000_READ_REG(hw, E1000_PTC127); - E1000_READ_REG(hw, E1000_PTC255); - E1000_READ_REG(hw, E1000_PTC511); - E1000_READ_REG(hw, E1000_PTC1023); - E1000_READ_REG(hw, E1000_PTC1522); - - E1000_READ_REG(hw, E1000_ALGNERRC); - E1000_READ_REG(hw, E1000_RXERRC); - E1000_READ_REG(hw, E1000_TNCRS); - E1000_READ_REG(hw, E1000_CEXTERR); - E1000_READ_REG(hw, E1000_TSCTC); - E1000_READ_REG(hw, E1000_TSCTFC); - - E1000_READ_REG(hw, E1000_MGTPRC); - E1000_READ_REG(hw, E1000_MGTPDC); - E1000_READ_REG(hw, E1000_MGTPTC); -#endif -} - -static struct pci_device_id e1000_82541_nics[] = { - PCI_ROM(0x8086, 0x1013, "E1000_DEV_ID_82541EI", "E1000_DEV_ID_82541EI", e1000_82541), - PCI_ROM(0x8086, 0x1014, "E1000_DEV_ID_82541ER_LOM", "E1000_DEV_ID_82541ER_LOM", e1000_82541), - PCI_ROM(0x8086, 0x1018, "E1000_DEV_ID_82541EI_MOBILE", "E1000_DEV_ID_82541EI_MOBILE", e1000_82541), - PCI_ROM(0x8086, 0x1019, "E1000_DEV_ID_82547EI", "E1000_DEV_ID_82547EI", e1000_82547), - PCI_ROM(0x8086, 0x101A, "E1000_DEV_ID_82547EI_MOBILE", "E1000_DEV_ID_82547EI_MOBILE", e1000_82547), - PCI_ROM(0x8086, 0x1075, "E1000_DEV_ID_82547GI", "E1000_DEV_ID_82547GI", e1000_82547_rev_2), - PCI_ROM(0x8086, 0x1076, "E1000_DEV_ID_82541GI", "E1000_DEV_ID_82541GI", e1000_82541_rev_2), - PCI_ROM(0x8086, 0x1077, "E1000_DEV_ID_82541GI_MOBILE", "E1000_DEV_ID_82541GI_MOBILE", e1000_82541_rev_2), - PCI_ROM(0x8086, 0x1078, "E1000_DEV_ID_82541ER", "E1000_DEV_ID_82541ER", e1000_82541_rev_2), - PCI_ROM(0x8086, 0x107C, "E1000_DEV_ID_82541GI_LF", "E1000_DEV_ID_82541GI_LF", e1000_82541_rev_2), -}; - -struct pci_driver e1000_82541_driver __pci_driver = { - .ids = e1000_82541_nics, - .id_count = (sizeof (e1000_82541_nics) / sizeof (e1000_82541_nics[0])), - .probe = e1000_probe, - .remove = e1000_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82541.h b/roms/ipxe/src/drivers/net/e1000/e1000_82541.h deleted file mode 100644 index f86a1482e..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82541.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_82541_H_ -#define _E1000_82541_H_ - -#define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1) - -#define IGP01E1000_PHY_CHANNEL_NUM 4 - -#define IGP01E1000_PHY_AGC_A 0x1172 -#define IGP01E1000_PHY_AGC_B 0x1272 -#define IGP01E1000_PHY_AGC_C 0x1472 -#define IGP01E1000_PHY_AGC_D 0x1872 - -#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 -#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 -#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 -#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 - -#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 -#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 - -#define IGP01E1000_PHY_DSP_RESET 0x1F33 - -#define IGP01E1000_PHY_DSP_FFE 0x1F35 -#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 -#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A - -#define IGP01E1000_IEEE_FORCE_GIG 0x0140 -#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 - -#define IGP01E1000_AGC_LENGTH_SHIFT 7 -#define IGP01E1000_AGC_RANGE 10 - -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE - -#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 -#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 -#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 -#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 -#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 -#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 -#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 -#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 -#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 - -#define IGP01E1000_MSE_CHANNEL_D 0x000F -#define IGP01E1000_MSE_CHANNEL_C 0x00F0 -#define IGP01E1000_MSE_CHANNEL_B 0x0F00 -#define IGP01E1000_MSE_CHANNEL_A 0xF000 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82542.c b/roms/ipxe/src/drivers/net/e1000/e1000_82542.c deleted file mode 100644 index b6d5202cc..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82542.c +++ /dev/null @@ -1,571 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82542 Gigabit Ethernet Controller - */ - -#include "e1000_api.h" - -static s32 e1000_init_phy_params_82542(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw); -static s32 e1000_init_mac_params_82542(struct e1000_hw *hw); -static s32 e1000_get_bus_info_82542(struct e1000_hw *hw); -static s32 e1000_reset_hw_82542(struct e1000_hw *hw); -static s32 e1000_init_hw_82542(struct e1000_hw *hw); -static s32 e1000_setup_link_82542(struct e1000_hw *hw); -static s32 e1000_led_on_82542(struct e1000_hw *hw); -static s32 e1000_led_off_82542(struct e1000_hw *hw); -static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index); -static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw); - -/** - * e1000_init_phy_params_82542 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82542(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_init_phy_params_82542"); - - phy->type = e1000_phy_none; - - return ret_val; -} - -/** - * e1000_init_nvm_params_82542 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - - DEBUGFUNC("e1000_init_nvm_params_82542"); - - nvm->address_bits = 6; - nvm->delay_usec = 50; - nvm->opcode_bits = 3; - nvm->type = e1000_nvm_eeprom_microwire; - nvm->word_size = 64; - - /* Function Pointers */ - nvm->ops.read = e1000_read_nvm_microwire; - nvm->ops.release = e1000_stop_nvm; - nvm->ops.write = e1000_write_nvm_microwire; - nvm->ops.update = e1000_update_nvm_checksum_generic; - nvm->ops.validate = e1000_validate_nvm_checksum_generic; - - return E1000_SUCCESS; -} - -/** - * e1000_init_mac_params_82542 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82542(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("e1000_init_mac_params_82542"); - - /* Set media type */ - hw->phy.media_type = e1000_media_type_fiber; - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000_get_bus_info_82542; - /* function id */ - mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; - /* reset */ - mac->ops.reset_hw = e1000_reset_hw_82542; - /* hw initialization */ - mac->ops.init_hw = e1000_init_hw_82542; - /* link setup */ - mac->ops.setup_link = e1000_setup_link_82542; - /* phy/fiber/serdes setup */ - mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic; - /* check for link */ - mac->ops.check_for_link = e1000_check_for_fiber_link_generic; - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000_clear_vfta_generic; - /* setting MTA */ - mac->ops.mta_set = e1000_mta_set_generic; - /* set RAR */ - mac->ops.rar_set = e1000_rar_set_82542; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_82542; - mac->ops.led_off = e1000_led_off_82542; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542; - /* link info */ - mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic; - - return E1000_SUCCESS; -} - -/** - * e1000_init_function_pointers_82542 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000_init_function_pointers_82542(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_init_function_pointers_82542"); - - hw->mac.ops.init_params = e1000_init_mac_params_82542; - hw->nvm.ops.init_params = e1000_init_nvm_params_82542; - hw->phy.ops.init_params = e1000_init_phy_params_82542; -} - -/** - * e1000_get_bus_info_82542 - Obtain bus information for adapter - * @hw: pointer to the HW structure - * - * This will obtain information about the HW bus for which the - * adapter is attached and stores it in the hw structure. - **/ -static s32 e1000_get_bus_info_82542(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_get_bus_info_82542"); - - hw->bus.type = e1000_bus_type_pci; - hw->bus.speed = e1000_bus_speed_unknown; - hw->bus.width = e1000_bus_width_unknown; - - return E1000_SUCCESS; -} - -/** - * e1000_reset_hw_82542 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82542(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - s32 ret_val = E1000_SUCCESS; - u32 ctrl; - - DEBUGFUNC("e1000_reset_hw_82542"); - - if (hw->revision_id == E1000_REVISION_2) { - DEBUGOUT("Disabling MWI on 82542 rev 2\n"); - e1000_pci_clear_mwi(hw); - } - - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - /* - * Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - msec_delay(10); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n"); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - - hw->nvm.ops.reload(hw); - msec_delay(2); - - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - E1000_READ_REG(hw, E1000_ICR); - - if (hw->revision_id == E1000_REVISION_2) { - if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - return ret_val; -} - -/** - * e1000_init_hw_82542 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82542(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542; - s32 ret_val = E1000_SUCCESS; - u32 ctrl; - u16 i; - - DEBUGFUNC("e1000_init_hw_82542"); - - /* Disabling VLAN filtering */ - E1000_WRITE_REG(hw, E1000_VET, 0); - mac->ops.clear_vfta(hw); - - /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if (hw->revision_id == E1000_REVISION_2) { - DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - E1000_WRITE_REG(hw, E1000_RCTL, E1000_RCTL_RST); - E1000_WRITE_FLUSH(hw); - msec_delay(5); - } - - /* Setup the receive address. */ - e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); - - /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if (hw->revision_id == E1000_REVISION_2) { - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_FLUSH(hw); - msec_delay(1); - if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* - * Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. - */ - if (dev_spec->dma_fairness) { - ctrl = E1000_READ_REG(hw, E1000_CTRL); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); - } - - /* Setup link and flow control */ - ret_val = e1000_setup_link_82542(hw); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82542(hw); - - return ret_val; -} - -/** - * e1000_setup_link_82542 - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_82542(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_link_82542"); - - ret_val = e1000_set_default_fc_generic(hw); - if (ret_val) - goto out; - - hw->fc.requested_mode &= ~e1000_fc_tx_pause; - - if (mac->report_tx_early == 1) - hw->fc.requested_mode &= ~e1000_fc_rx_pause; - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); - - /* Call the necessary subroutine to configure the link. */ - ret_val = mac->ops.setup_physical_interface(hw); - if (ret_val) - goto out; - - /* - * Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - DEBUGOUT("Initializing Flow Control address, type and timer regs\n"); - - E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); - E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); - - E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); - - ret_val = e1000_set_fc_watermarks_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_led_on_82542 - Turn on SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED on. - **/ -static s32 e1000_led_on_82542(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGFUNC("e1000_led_on_82542"); - - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_led_off_82542 - Turn off SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED off. - **/ -static s32 e1000_led_off_82542(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGFUNC("e1000_led_off_82542"); - - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_rar_set_82542 - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - DEBUGFUNC("e1000_rar_set_82542"); - - /* - * HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | - ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low); - E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high); -} - -/** - * e1000_translate_register_82542 - Translate the proper register offset - * @reg: e1000 register to be read - * - * Registers in 82542 are located in different offsets than other adapters - * even though they function in the same manner. This function takes in - * the name of the register to read and returns the correct offset for - * 82542 silicon. - **/ -u32 e1000_translate_register_82542(u32 reg) -{ - /* - * Some of the 82542 registers are located at different - * offsets than they are in newer adapters. - * Despite the difference in location, the registers - * function in the same manner. - */ - switch (reg) { - case E1000_RA: - reg = 0x00040; - break; - case E1000_RDTR: - reg = 0x00108; - break; - case E1000_RDBAL(0): - reg = 0x00110; - break; - case E1000_RDBAH(0): - reg = 0x00114; - break; - case E1000_RDLEN(0): - reg = 0x00118; - break; - case E1000_RDH(0): - reg = 0x00120; - break; - case E1000_RDT(0): - reg = 0x00128; - break; - case E1000_RDBAL(1): - reg = 0x00138; - break; - case E1000_RDBAH(1): - reg = 0x0013C; - break; - case E1000_RDLEN(1): - reg = 0x00140; - break; - case E1000_RDH(1): - reg = 0x00148; - break; - case E1000_RDT(1): - reg = 0x00150; - break; - case E1000_FCRTH: - reg = 0x00160; - break; - case E1000_FCRTL: - reg = 0x00168; - break; - case E1000_MTA: - reg = 0x00200; - break; - case E1000_TDBAL(0): - reg = 0x00420; - break; - case E1000_TDBAH(0): - reg = 0x00424; - break; - case E1000_TDLEN(0): - reg = 0x00428; - break; - case E1000_TDH(0): - reg = 0x00430; - break; - case E1000_TDT(0): - reg = 0x00438; - break; - case E1000_TIDV: - reg = 0x00440; - break; - case E1000_VFTA: - reg = 0x00600; - break; - case E1000_TDFH: - reg = 0x08010; - break; - case E1000_TDFT: - reg = 0x08018; - break; - default: - break; - } - - return reg; -} - -/** - * e1000_clear_hw_cntrs_82542 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_clear_hw_cntrs_82542"); - - e1000_clear_hw_cntrs_base_generic(hw); - -#if 0 - E1000_READ_REG(hw, E1000_PRC64); - E1000_READ_REG(hw, E1000_PRC127); - E1000_READ_REG(hw, E1000_PRC255); - E1000_READ_REG(hw, E1000_PRC511); - E1000_READ_REG(hw, E1000_PRC1023); - E1000_READ_REG(hw, E1000_PRC1522); - E1000_READ_REG(hw, E1000_PTC64); - E1000_READ_REG(hw, E1000_PTC127); - E1000_READ_REG(hw, E1000_PTC255); - E1000_READ_REG(hw, E1000_PTC511); - E1000_READ_REG(hw, E1000_PTC1023); - E1000_READ_REG(hw, E1000_PTC1522); -#endif -} - -static struct pci_device_id e1000_82542_nics[] = { - PCI_ROM(0x8086, 0x1000, "E1000_DEV_ID_82542", "E1000_DEV_ID_82542", e1000_82542), -}; - -struct pci_driver e1000_82542_driver __pci_driver = { - .ids = e1000_82542_nics, - .id_count = (sizeof (e1000_82542_nics) / sizeof (e1000_82542_nics[0])), - .probe = e1000_probe, - .remove = e1000_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82543.c b/roms/ipxe/src/drivers/net/e1000/e1000_82543.c deleted file mode 100644 index 848c99e76..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82543.c +++ /dev/null @@ -1,1635 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82543GC Gigabit Ethernet Controller (Fiber) - * 82543GC Gigabit Ethernet Controller (Copper) - * 82544EI Gigabit Ethernet Controller (Copper) - * 82544EI Gigabit Ethernet Controller (Fiber) - * 82544GC Gigabit Ethernet Controller (Copper) - * 82544GC Gigabit Ethernet Controller (LOM) - */ - -#include "e1000_api.h" - -static s32 e1000_init_phy_params_82543(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw); -static s32 e1000_init_mac_params_82543(struct e1000_hw *hw); -static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, - u16 data); -#if 0 -static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw); -#endif -static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw); -static s32 e1000_reset_hw_82543(struct e1000_hw *hw); -static s32 e1000_init_hw_82543(struct e1000_hw *hw); -static s32 e1000_setup_link_82543(struct e1000_hw *hw); -static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw); -static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw); -static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw); -static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw); -static s32 e1000_led_on_82543(struct e1000_hw *hw); -static s32 e1000_led_off_82543(struct e1000_hw *hw); -static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, - u32 value); -static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value); -static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw); -static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw); -static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw); -static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); -static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw); -static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); -static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw); -static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, - u16 count); -static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw); -static void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state); -static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state); - -/** - * e1000_init_phy_params_82543 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82543(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_init_phy_params_82543"); - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - goto out; - } else { - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 10000; - phy->type = e1000_phy_m88; - - /* Function Pointers */ - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.commit = e1000_phy_sw_reset_generic; -#if 0 - phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543; -#endif -#if 0 - phy->ops.get_cable_length = e1000_get_cable_length_m88; -#endif - phy->ops.get_cfg_done = e1000_get_cfg_done_generic; - phy->ops.read_reg = (hw->mac.type == e1000_82543) - ? e1000_read_phy_reg_82543 - : e1000_read_phy_reg_m88; - phy->ops.reset = (hw->mac.type == e1000_82543) - ? e1000_phy_hw_reset_82543 - : e1000_phy_hw_reset_generic; - phy->ops.write_reg = (hw->mac.type == e1000_82543) - ? e1000_write_phy_reg_82543 - : e1000_write_phy_reg_m88; - phy->ops.get_info = e1000_get_phy_info_m88; - - /* - * The external PHY of the 82543 can be in a funky state. - * Resetting helps us read the PHY registers for acquiring - * the PHY ID. - */ - if (!e1000_init_phy_disabled_82543(hw)) { - ret_val = phy->ops.reset(hw); - if (ret_val) { - DEBUGOUT("Resetting PHY during init failed.\n"); - goto out; - } - msec_delay(20); - } - - ret_val = e1000_get_phy_id(hw); - if (ret_val) - goto out; - - /* Verify phy id */ - switch (hw->mac.type) { - case e1000_82543: - if (phy->id != M88E1000_E_PHY_ID) { - ret_val = -E1000_ERR_PHY; - goto out; - } - break; - case e1000_82544: - if (phy->id != M88E1000_I_PHY_ID) { - ret_val = -E1000_ERR_PHY; - goto out; - } - break; - default: - ret_val = -E1000_ERR_PHY; - goto out; - break; - } - -out: - return ret_val; -} - -/** - * e1000_init_nvm_params_82543 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - - DEBUGFUNC("e1000_init_nvm_params_82543"); - - nvm->type = e1000_nvm_eeprom_microwire; - nvm->word_size = 64; - nvm->delay_usec = 50; - nvm->address_bits = 6; - nvm->opcode_bits = 3; - - /* Function Pointers */ - nvm->ops.read = e1000_read_nvm_microwire; - nvm->ops.update = e1000_update_nvm_checksum_generic; - nvm->ops.valid_led_default = e1000_valid_led_default_generic; - nvm->ops.validate = e1000_validate_nvm_checksum_generic; - nvm->ops.write = e1000_write_nvm_microwire; - - return E1000_SUCCESS; -} - -/** - * e1000_init_mac_params_82543 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82543(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("e1000_init_mac_params_82543"); - - /* Set media type */ - switch (hw->device_id) { - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82544EI_FIBER: - hw->phy.media_type = e1000_media_type_fiber; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; - /* function id */ - mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; - /* reset */ - mac->ops.reset_hw = e1000_reset_hw_82543; - /* hw initialization */ - mac->ops.init_hw = e1000_init_hw_82543; - /* link setup */ - mac->ops.setup_link = e1000_setup_link_82543; - /* physical interface setup */ - mac->ops.setup_physical_interface = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000_setup_copper_link_82543 - : e1000_setup_fiber_link_82543; - /* check for link */ - mac->ops.check_for_link = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000_check_for_copper_link_82543 - : e1000_check_for_fiber_link_82543; - /* link info */ - mac->ops.get_link_up_info = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000_get_speed_and_duplex_copper_generic - : e1000_get_speed_and_duplex_fiber_serdes_generic; - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000_write_vfta_82543; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000_clear_vfta_generic; - /* setting MTA */ - mac->ops.mta_set = e1000_mta_set_82543; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_82543; - mac->ops.led_off = e1000_led_off_82543; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543; - - /* Set tbi compatibility */ - if ((hw->mac.type != e1000_82543) || - (hw->phy.media_type == e1000_media_type_fiber)) - e1000_set_tbi_compatibility_82543(hw, false); - - return E1000_SUCCESS; -} - -/** - * e1000_init_function_pointers_82543 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000_init_function_pointers_82543(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_init_function_pointers_82543"); - - hw->mac.ops.init_params = e1000_init_mac_params_82543; - hw->nvm.ops.init_params = e1000_init_nvm_params_82543; - hw->phy.ops.init_params = e1000_init_phy_params_82543; -} - -/** - * e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status - * @hw: pointer to the HW structure - * - * Returns the current status of 10-bit Interface (TBI) compatibility - * (enabled/disabled). - **/ -static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw) -{ - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - bool state = false; - - DEBUGFUNC("e1000_tbi_compatibility_enabled_82543"); - - if (hw->mac.type != e1000_82543) { - DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); - goto out; - } - - state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED) - ? true : false; - -out: - return state; -} - -/** - * e1000_set_tbi_compatibility_82543 - Set TBI compatibility - * @hw: pointer to the HW structure - * @state: enable/disable TBI compatibility - * - * Enables or disabled 10-bit Interface (TBI) compatibility. - **/ -static void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state) -{ - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - - DEBUGFUNC("e1000_set_tbi_compatibility_82543"); - - if (hw->mac.type != e1000_82543) { - DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); - goto out; - } - - if (state) - dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED; - else - dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED; - -out: - return; -} - -/** - * e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status - * @hw: pointer to the HW structure - * - * Returns the current status of 10-bit Interface (TBI) store bad packet (SBP) - * (enabled/disabled). - **/ -bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw) -{ - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - bool state = false; - - DEBUGFUNC("e1000_tbi_sbp_enabled_82543"); - - if (hw->mac.type != e1000_82543) { - DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); - goto out; - } - - state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED) - ? true : false; - -out: - return state; -} - -/** - * e1000_set_tbi_sbp_82543 - Set TBI SBP - * @hw: pointer to the HW structure - * @state: enable/disable TBI store bad packet - * - * Enables or disabled 10-bit Interface (TBI) store bad packet (SBP). - **/ -static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state) -{ - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - - DEBUGFUNC("e1000_set_tbi_sbp_82543"); - - if (state && e1000_tbi_compatibility_enabled_82543(hw)) - dev_spec->tbi_compatibility |= TBI_SBP_ENABLED; - else - dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED; - - return; -} - -/** - * e1000_init_phy_disabled_82543 - Returns init PHY status - * @hw: pointer to the HW structure - * - * Returns the current status of whether PHY initialization is disabled. - * True if PHY initialization is disabled else false. - **/ -static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw) -{ - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - bool ret_val; - - DEBUGFUNC("e1000_init_phy_disabled_82543"); - - if (hw->mac.type != e1000_82543) { - ret_val = false; - goto out; - } - - ret_val = dev_spec->init_phy_disabled; - -out: - return ret_val; -} - -#if 0 -/** - * e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled - * @hw: pointer to the HW structure - * @stats: Struct containing statistic register values - * @frame_len: The length of the frame in question - * @mac_addr: The Ethernet destination address of the frame in question - * @max_frame_size: The maximum frame size - * - * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT - **/ -void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw, - struct e1000_hw_stats *stats, u32 frame_len, - u8 *mac_addr, u32 max_frame_size) -{ - if (!(e1000_tbi_sbp_enabled_82543(hw))) - goto out; - - /* First adjust the frame length. */ - frame_len--; - /* - * We need to adjust the statistics counters, since the hardware - * counters overcount this packet as a CRC error and undercount - * the packet as a good packet - */ - /* This packet should not be counted as a CRC error. */ - stats->crcerrs--; - /* This packet does count as a Good Packet Received. */ - stats->gprc++; - - /* Adjust the Good Octets received counters */ - stats->gorc += frame_len; - - /* - * Is this a broadcast or multicast? Check broadcast first, - * since the test for a multicast frame will test positive on - * a broadcast frame. - */ - if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff)) - /* Broadcast packet */ - stats->bprc++; - else if (*mac_addr & 0x01) - /* Multicast packet */ - stats->mprc++; - - /* - * In this case, the hardware has overcounted the number of - * oversize frames. - */ - if ((frame_len == max_frame_size) && (stats->roc > 0)) - stats->roc--; - - /* - * Adjust the bin counters when the extra byte put the frame in the - * wrong bin. Remember that the frame_len was adjusted above. - */ - if (frame_len == 64) { - stats->prc64++; - stats->prc127--; - } else if (frame_len == 127) { - stats->prc127++; - stats->prc255--; - } else if (frame_len == 255) { - stats->prc255++; - stats->prc511--; - } else if (frame_len == 511) { - stats->prc511++; - stats->prc1023--; - } else if (frame_len == 1023) { - stats->prc1023++; - stats->prc1522--; - } else if (frame_len == 1522) { - stats->prc1522++; - } - -out: - return; -} -#endif - -/** - * e1000_read_phy_reg_82543 - Read PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY at offset and stores the information read to data. - **/ -static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data) -{ - u32 mdic; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_phy_reg_82543"); - - if (offset > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", offset); - ret_val = -E1000_ERR_PARAM; - goto out; - } - - /* - * We must first send a preamble through the MDIO pin to signal the - * beginning of an MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* - * Now combine the next few fields that are required for a read - * operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine five different times. The format - * of an MII read instruction consists of a shift out of 14 bits and - * is defined as follows: - * - * followed by a shift in of 18 bits. This first two bits shifted in - * are TurnAround bits used to avoid contention on the MDIO pin when a - * READ operation is performed. These two bits are thrown away - * followed by a shift in of 16 bits which contains the desired data. - */ - mdic = (offset | (hw->phy.addr << 5) | - (PHY_OP_READ << 10) | (PHY_SOF << 12)); - - e1000_shift_out_mdi_bits_82543(hw, mdic, 14); - - /* - * Now that we've shifted out the read command to the MII, we need to - * "shift in" the 16-bit value (18 total bits) of the requested PHY - * register address. - */ - *data = e1000_shift_in_mdi_bits_82543(hw); - -out: - return ret_val; -} - -/** - * e1000_write_phy_reg_82543 - Write PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be written - * @data: pointer to the data to be written at offset - * - * Writes data to the PHY at offset. - **/ -static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data) -{ - u32 mdic; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_phy_reg_82543"); - - if (offset > MAX_PHY_REG_ADDRESS) { - DEBUGOUT1("PHY Address %d is out of range\n", offset); - ret_val = -E1000_ERR_PARAM; - goto out; - } - - /* - * We'll need to use the SW defined pins to shift the write command - * out to the PHY. We first send a preamble to the PHY to signal the - * beginning of the MII instruction. This is done by sending 32 - * consecutive "1" bits. - */ - e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* - * Now combine the remaining required fields that will indicate a - * write operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine for each field in the command. The - * format of a MII write instruction is as follows: - * . - */ - mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) | - (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); - mdic <<= 16; - mdic |= (u32) data; - - e1000_shift_out_mdi_bits_82543(hw, mdic, 32); - -out: - return ret_val; -} - -/** - * e1000_raise_mdi_clk_82543 - Raise Management Data Input clock - * @hw: pointer to the HW structure - * @ctrl: pointer to the control register - * - * Raise the management data input clock by setting the MDC bit in the control - * register. - **/ -static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) -{ - /* - * Raise the clock input to the Management Data Clock (by setting the - * MDC bit), and then delay a sufficient amount of time. - */ - E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - usec_delay(10); -} - -/** - * e1000_lower_mdi_clk_82543 - Lower Management Data Input clock - * @hw: pointer to the HW structure - * @ctrl: pointer to the control register - * - * Lower the management data input clock by clearing the MDC bit in the - * control register. - **/ -static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) -{ - /* - * Lower the clock input to the Management Data Clock (by clearing the - * MDC bit), and then delay a sufficient amount of time. - */ - E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(hw); - usec_delay(10); -} - -/** - * e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY - * @hw: pointer to the HW structure - * @data: data to send to the PHY - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the PHY. So, the value in the - * "data" parameter will be shifted out to the PHY one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, - u16 count) -{ - u32 ctrl, mask; - - /* - * We need to shift "count" number of bits out to the PHY. So, the - * value in the "data" parameter will be shifted out to the PHY one - * bit at a time. In order to do this, "data" must be broken down - * into bits. - */ - mask = 0x01; - mask <<= (count -1); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ - ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - - while (mask) { - /* - * A "1" is shifted out to the PHY by setting the MDIO bit to - * "1" and then raising and lowering the Management Data Clock. - * A "0" is shifted out to the PHY by setting the MDIO bit to - * "0" and then raising and lowering the clock. - */ - if (data & mask) ctrl |= E1000_CTRL_MDIO; - else ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - usec_delay(10); - - e1000_raise_mdi_clk_82543(hw, &ctrl); - e1000_lower_mdi_clk_82543(hw, &ctrl); - - mask >>= 1; - } -} - -/** - * e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY - * @hw: pointer to the HW structure - * - * In order to read a register from the PHY, we need to shift 18 bits - * in from the PHY. Bits are "shifted in" by raising the clock input to - * the PHY (setting the MDC bit), and then reading the value of the data out - * MDIO bit. - **/ -static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw) -{ - u32 ctrl; - u16 data = 0; - u8 i; - - /* - * In order to read a register from the PHY, we need to shift in a - * total of 18 bits from the PHY. The first two bit (turnaround) - * times are used to avoid contention on the MDIO pin when a read - * operation is performed. These two bits are ignored by us and - * thrown away. Bits are "shifted in" by raising the input to the - * Management Data Clock (setting the MDC bit) and then reading the - * value of the MDIO bit. - */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* - * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as - * input. - */ - ctrl &= ~E1000_CTRL_MDIO_DIR; - ctrl &= ~E1000_CTRL_MDIO; - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - /* - * Raise and lower the clock before reading in the data. This accounts - * for the turnaround bits. The first clock occurred when we clocked - * out the last bit of the Register Address. - */ - e1000_raise_mdi_clk_82543(hw, &ctrl); - e1000_lower_mdi_clk_82543(hw, &ctrl); - - for (data = 0, i = 0; i < 16; i++) { - data <<= 1; - e1000_raise_mdi_clk_82543(hw, &ctrl); - ctrl = E1000_READ_REG(hw, E1000_CTRL); - /* Check to see if we shifted in a "1". */ - if (ctrl & E1000_CTRL_MDIO) - data |= 1; - e1000_lower_mdi_clk_82543(hw, &ctrl); - } - - e1000_raise_mdi_clk_82543(hw, &ctrl); - e1000_lower_mdi_clk_82543(hw, &ctrl); - - return data; -} - -#if 0 -/** - * e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY - * @hw: pointer to the HW structure - * - * Calls the function to force speed and duplex for the m88 PHY, and - * if the PHY is not auto-negotiating and the speed is forced to 10Mbit, - * then call the function for polarity reversal workaround. - **/ -static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw) -{ - s32 ret_val; - - DEBUGFUNC("e1000_phy_force_speed_duplex_82543"); - - ret_val = e1000_phy_force_speed_duplex_m88(hw); - if (ret_val) - goto out; - - if (!hw->mac.autoneg && - (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)) - ret_val = e1000_polarity_reversal_workaround_82543(hw); - -out: - return ret_val; -} -#endif - -/** - * e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal - * @hw: pointer to the HW structure - * - * When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity - * inadvertently. To workaround the issue, we disable the transmitter on - * the PHY until we have established the link partner's link parameters. - **/ -static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 mii_status_reg; - u16 i; - bool link; - - if (!(hw->phy.ops.write_reg)) - goto out; - - /* Polarity reversal workaround for forced 10F/10H links. */ - - /* Disable the transmitter on the PHY */ - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - goto out; - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - goto out; - - /* - * This loop will early-out if the NO link condition has been met. - * In other words, DO NOT use e1000_phy_has_link_generic() here. - */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* - * Read the MII Status Register and wait for Link Status bit - * to be clear. - */ - - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - - if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) - break; - msec_delay_irq(100); - } - - /* Recommended delay time after link has been lost */ - msec_delay_irq(1000); - - /* Now we will re-enable the transmitter on the PHY */ - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - goto out; - msec_delay_irq(50); - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); - if (ret_val) - goto out; - msec_delay_irq(50); - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); - if (ret_val) - goto out; - msec_delay_irq(50); - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - goto out; - - /* - * Read the MII Status Register and wait for Link Status bit - * to be set. - */ - ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link); - if (ret_val) - goto out; - -out: - return ret_val; -} - -/** - * e1000_phy_hw_reset_82543 - PHY hardware reset - * @hw: pointer to the HW structure - * - * Sets the PHY_RESET_DIR bit in the extended device control register - * to put the PHY into a reset and waits for completion. Once the reset - * has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out - * of reset. - **/ -static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) -{ - u32 ctrl_ext; - s32 ret_val; - - DEBUGFUNC("e1000_phy_hw_reset_82543"); - - /* - * Read the Extended Device Control Register, assert the PHY_RESET_DIR - * bit to put the PHY into reset... - */ - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; - ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - - msec_delay(10); - - /* ...then take it out of reset. */ - ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - - usec_delay(150); - - if (!(hw->phy.ops.get_cfg_done)) - return E1000_SUCCESS; - - ret_val = hw->phy.ops.get_cfg_done(hw); - - return ret_val; -} - -/** - * e1000_reset_hw_82543 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82543(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_reset_hw_82543"); - - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - e1000_set_tbi_sbp_82543(hw, false); - - /* - * Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - msec_delay(10); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n"); - if (hw->mac.type == e1000_82543) { - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - } else { - /* - * The 82544 can't ACK the 64-bit write when issuing the - * reset, so use IO-mapping as a workaround. - */ - E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - } - - /* - * After MAC reset, force reload of NVM to restore power-on - * settings to device. - */ - hw->nvm.ops.reload(hw); - msec_delay(2); - - /* Masking off and clearing any pending interrupts */ - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - E1000_READ_REG(hw, E1000_ICR); - - return ret_val; -} - -/** - * e1000_init_hw_82543 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82543(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; - u32 ctrl; - s32 ret_val; - u16 i; - - DEBUGFUNC("e1000_init_hw_82543"); - - /* Disabling VLAN filtering */ - E1000_WRITE_REG(hw, E1000_VET, 0); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. */ - e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - E1000_WRITE_FLUSH(hw); - } - - /* - * Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. - */ - if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) { - ctrl = E1000_READ_REG(hw, E1000_CTRL); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); - } - - e1000_pcix_mmrbc_workaround_generic(hw); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82543(hw); - - return ret_val; -} - -/** - * e1000_setup_link_82543 - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Read the EEPROM to determine the initial polarity value and write the - * extended device control register with the information before calling - * the generic setup link function, which does the following: - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_82543(struct e1000_hw *hw) -{ - u32 ctrl_ext; - s32 ret_val; - u16 data; - - DEBUGFUNC("e1000_setup_link_82543"); - - /* - * Take the 4 bits from NVM word 0xF that determine the initial - * polarity value for the SW controlled pins, and setup the - * Extended Device Control reg with that info. - * This is needed because one of the SW controlled pins is used for - * signal detection. So this should be done before phy setup. - */ - if (hw->mac.type == e1000_82543) { - ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) << - NVM_SWDPIO_EXT_SHIFT); - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - } - - ret_val = e1000_setup_link_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_setup_copper_link_82543 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Configures the link for auto-neg or forced speed and duplex. Then we check - * for link, once link is established calls to configure collision distance - * and flow control are called. - **/ -static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - bool link; - - DEBUGFUNC("e1000_setup_copper_link_82543"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU; - /* - * With 82543, we need to force speed and duplex on the MAC - * equal to what the PHY speed and duplex configuration is. - * In addition, we need to perform a hardware reset on the - * PHY to take it out of reset. - */ - if (hw->mac.type == e1000_82543) { - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - ret_val = hw->phy.ops.reset(hw); - if (ret_val) - goto out; - hw->phy.reset_disable = false; - } else { - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - } - - /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */ - ret_val = e1000_copper_link_setup_m88(hw); - if (ret_val) - goto out; - - if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - goto out; - } else { - /* - * PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ -#if 0 - DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = e1000_phy_force_speed_duplex_82543(hw); - if (ret_val) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - goto out; - } -#endif - } - - /* - * Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000_phy_has_link_generic(hw, - COPPER_LINK_UP_LIMIT, - 10, - &link); - if (ret_val) - goto out; - - - if (link) { - DEBUGOUT("Valid link established!!!\n"); - /* Config the MAC and PHY after link is up */ - if (hw->mac.type == e1000_82544) { - e1000_config_collision_dist_generic(hw); - } else { - ret_val = e1000_config_mac_to_phy_82543(hw); - if (ret_val) - goto out; - } - ret_val = e1000_config_fc_after_link_up_generic(hw); - } else { - DEBUGOUT("Unable to establish link!!!\n"); - } - -out: - return ret_val; -} - -/** - * e1000_setup_fiber_link_82543 - Setup link for fiber - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber links. Upon - * successful setup, poll for link. - **/ -static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - DEBUGFUNC("e1000_setup_fiber_link_82543"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - e1000_config_collision_dist_generic(hw); - - ret_val = e1000_commit_fc_settings_generic(hw); - if (ret_val) - goto out; - - DEBUGOUT("Auto-negotiation enabled\n"); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - msec_delay(1); - - /* - * For these adapters, the SW definable pin 1 is cleared when the - * optics detect a signal. If we have a signal, then poll for a - * "Link-Up" indication. - */ - if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000_poll_fiber_serdes_link_generic(hw); - } else { - DEBUGOUT("No signal detected\n"); - } - -out: - return ret_val; -} - -/** - * e1000_check_for_copper_link_82543 - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks the phy for link, if link exists, do the following: - * - check for downshift - * - do polarity workaround (if necessary) - * - configure collision distance - * - configure flow control after link up - * - configure tbi compatibility - **/ -static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 icr, rctl; - s32 ret_val; - u16 speed, duplex; - bool link; - - DEBUGFUNC("e1000_check_for_copper_link_82543"); - - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) - goto out; /* No link detected */ - - mac->get_link_status = false; - - e1000_check_downshift_generic(hw); - - /* - * If we are forcing speed/duplex, then we can return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - /* - * If speed and duplex are forced to 10H or 10F, then we will - * implement the polarity reversal workaround. We disable - * interrupts first, and upon returning, place the devices - * interrupt state to its previous value except for the link - * status change interrupt which will happened due to the - * execution of this workaround. - */ - if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) { - E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); - ret_val = e1000_polarity_reversal_workaround_82543(hw); - icr = E1000_READ_REG(hw, E1000_ICR); - E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC)); - E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); - } - - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * We have a M88E1000 PHY and Auto-Neg is enabled. If we - * have Si on board that is 82544 or newer, Auto - * Speed Detection takes care of MAC speed/duplex - * configuration. So we only need to configure Collision - * Distance in the MAC. Otherwise, we need to force - * speed/duplex on the MAC to the current PHY speed/duplex - * settings. - */ - if (mac->type == e1000_82544) - e1000_config_collision_dist_generic(hw); - else { - ret_val = e1000_config_mac_to_phy_82543(hw); - if (ret_val) { - DEBUGOUT("Error configuring MAC to PHY settings\n"); - goto out; - } - } - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - } - - /* - * At this point we know that we are on copper and we have - * auto-negotiated link. These are conditions for checking the link - * partner capability register. We use the link speed to determine if - * TBI compatibility needs to be turned on or off. If the link is not - * at gigabit speed, then TBI compatibility is not needed. If we are - * at gigabit speed, we turn on TBI compatibility. - */ - if (e1000_tbi_compatibility_enabled_82543(hw)) { - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - DEBUGOUT("Error getting link speed and duplex\n"); - return ret_val; - } - if (speed != SPEED_1000) { - /* - * If link speed is not set to gigabit speed, - * we do not need to enable TBI compatibility. - */ - if (e1000_tbi_sbp_enabled_82543(hw)) { - /* - * If we previously were in the mode, - * turn it off. - */ - e1000_set_tbi_sbp_82543(hw, false); - rctl = E1000_READ_REG(hw, E1000_RCTL); - rctl &= ~E1000_RCTL_SBP; - E1000_WRITE_REG(hw, E1000_RCTL, rctl); - } - } else { - /* - * If TBI compatibility is was previously off, - * turn it on. For compatibility with a TBI link - * partner, we will store bad packets. Some - * frames have an additional byte on the end and - * will look like CRC errors to to the hardware. - */ - if (!e1000_tbi_sbp_enabled_82543(hw)) { - e1000_set_tbi_sbp_82543(hw, true); - rctl = E1000_READ_REG(hw, E1000_RCTL); - rctl |= E1000_RCTL_SBP; - E1000_WRITE_REG(hw, E1000_RCTL, rctl); - } - } - } -out: - return ret_val; -} - -/** - * e1000_check_for_fiber_link_82543 - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw, ctrl, status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_check_for_fiber_link_82543"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - status = E1000_READ_REG(hw, E1000_STATUS); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */ - if ((!(ctrl & E1000_CTRL_SWDPIN1)) && - (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - ret_val = 0; - goto out; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); - E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - -out: - return ret_val; -} - -/** - * e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings - * @hw: pointer to the HW structure - * - * For the 82543 silicon, we need to set the MAC to match the settings - * of the PHY, even if the PHY is auto-negotiating. - **/ -static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - u16 phy_data; - - DEBUGFUNC("e1000_config_mac_to_phy_82543"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - /* Set the bits to force speed and duplex */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); - - /* - * Set up duplex in the Device Control and Transmit Control - * registers depending on negotiated values. - */ - ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - ctrl &= ~E1000_CTRL_FD; - if (phy_data & M88E1000_PSSR_DPLX) - ctrl |= E1000_CTRL_FD; - - e1000_config_collision_dist_generic(hw); - - /* - * Set up speed in the Device Control register depending on - * negotiated values. - */ - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - -out: - return ret_val; -} - -/** - * e1000_write_vfta_82543 - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: the 32-bit offset in which to write the value to. - * @value: the 32-bit value to write at location offset. - * - * This writes a 32-bit value to a 32-bit offset in the VLAN filter - * table. - **/ -static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value) -{ - u32 temp; - - DEBUGFUNC("e1000_write_vfta_82543"); - - if ((hw->mac.type == e1000_82544) && (offset & 1)) { - temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1); - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - E1000_WRITE_FLUSH(hw); - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp); - E1000_WRITE_FLUSH(hw); - } else { - e1000_write_vfta_generic(hw, offset, value); - } -} - -/** - * e1000_mta_set_82543 - Set multicast filter table address - * @hw: pointer to the HW structure - * @hash_value: determines the MTA register and bit to set - * - * The multicast table address is a register array of 32-bit registers. - * The hash_value is used to determine what register the bit is in, the - * current value is read, the new bit is OR'd in and the new value is - * written back into the register. - **/ -static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg, mta, temp; - - DEBUGFUNC("e1000_mta_set_82543"); - - hash_reg = (hash_value >> 5); - - /* - * If we are on an 82544 and we are trying to write an odd offset - * in the MTA, save off the previous entry before writing and - * restore the old value after writing. - */ - if ((hw->mac.type == e1000_82544) && (hash_reg & 1)) { - hash_reg &= (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); - mta |= (1 << hash_bit); - temp = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg - 1); - - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); - E1000_WRITE_FLUSH(hw); - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg - 1, temp); - E1000_WRITE_FLUSH(hw); - } else { - e1000_mta_set_generic(hw, hash_value); - } -} - -/** - * e1000_led_on_82543 - Turn on SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED on. - **/ -static s32 e1000_led_on_82543(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGFUNC("e1000_led_on_82543"); - - if (hw->mac.type == e1000_82544 && - hw->phy.media_type == e1000_media_type_copper) { - /* Clear SW-definable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Fiber 82544 and all 82543 use this method */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_led_off_82543 - Turn off SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED off. - **/ -static s32 e1000_led_off_82543(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGFUNC("e1000_led_off_82543"); - - if (hw->mac.type == e1000_82544 && - hw->phy.media_type == e1000_media_type_copper) { - /* Set SW-definable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw) -{ - DEBUGFUNC("e1000_clear_hw_cntrs_82543"); - - e1000_clear_hw_cntrs_base_generic(hw); - -#if 0 - E1000_READ_REG(hw, E1000_PRC64); - E1000_READ_REG(hw, E1000_PRC127); - E1000_READ_REG(hw, E1000_PRC255); - E1000_READ_REG(hw, E1000_PRC511); - E1000_READ_REG(hw, E1000_PRC1023); - E1000_READ_REG(hw, E1000_PRC1522); - E1000_READ_REG(hw, E1000_PTC64); - E1000_READ_REG(hw, E1000_PTC127); - E1000_READ_REG(hw, E1000_PTC255); - E1000_READ_REG(hw, E1000_PTC511); - E1000_READ_REG(hw, E1000_PTC1023); - E1000_READ_REG(hw, E1000_PTC1522); - - E1000_READ_REG(hw, E1000_ALGNERRC); - E1000_READ_REG(hw, E1000_RXERRC); - E1000_READ_REG(hw, E1000_TNCRS); - E1000_READ_REG(hw, E1000_CEXTERR); - E1000_READ_REG(hw, E1000_TSCTC); - E1000_READ_REG(hw, E1000_TSCTFC); -#endif -} - -static struct pci_device_id e1000_82543_nics[] = { - PCI_ROM(0x8086, 0x1001, "E1000_DEV_ID_82543GC_FIBER", "E1000_DEV_ID_82543GC_FIBER", e1000_82543), - PCI_ROM(0x8086, 0x1004, "E1000_DEV_ID_82543GC_COPPER", "E1000_DEV_ID_82543GC_COPPER", e1000_82543), - PCI_ROM(0x8086, 0x1008, "E1000_DEV_ID_82544EI_COPPER", "E1000_DEV_ID_82544EI_COPPER", e1000_82544), - PCI_ROM(0x8086, 0x1009, "E1000_DEV_ID_82544EI_FIBER", "E1000_DEV_ID_82544EI_FIBER", e1000_82544), - PCI_ROM(0x8086, 0x100C, "E1000_DEV_ID_82544GC_COPPER", "E1000_DEV_ID_82544GC_COPPER", e1000_82544), - PCI_ROM(0x8086, 0x100D, "E1000_DEV_ID_82544GC_LOM", "E1000_DEV_ID_82544GC_LOM", e1000_82544), -}; - -struct pci_driver e1000_82543_driver __pci_driver = { - .ids = e1000_82543_nics, - .id_count = (sizeof (e1000_82543_nics) / sizeof (e1000_82543_nics[0])), - .probe = e1000_probe, - .remove = e1000_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_82543.h b/roms/ipxe/src/drivers/net/e1000/e1000_82543.h deleted file mode 100644 index 30073e8bf..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_82543.h +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_82543_H_ -#define _E1000_82543_H_ - -#define PHY_PREAMBLE 0xFFFFFFFF -#define PHY_PREAMBLE_SIZE 32 -#define PHY_SOF 0x1 -#define PHY_OP_READ 0x2 -#define PHY_OP_WRITE 0x1 -#define PHY_TURNAROUND 0x2 - -#define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */ -/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */ -#define TBI_SBP_ENABLED 0x2 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_api.c b/roms/ipxe/src/drivers/net/e1000/e1000_api.c deleted file mode 100644 index 72aac4c48..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_api.c +++ /dev/null @@ -1,1108 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000_api.h" - -/** - * e1000_init_mac_params - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the MAC - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 e1000_init_mac_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->mac.ops.init_params) { - ret_val = hw->mac.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("MAC Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("mac.init_mac_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -/** - * e1000_init_nvm_params - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the NVM - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 e1000_init_nvm_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->nvm.ops.init_params) { - ret_val = hw->nvm.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("NVM Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("nvm.init_nvm_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -/** - * e1000_init_phy_params - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the PHY - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 e1000_init_phy_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.ops.init_params) { - ret_val = hw->phy.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("PHY Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("phy.init_phy_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -/** - * e1000_set_mac_type - Sets MAC type - * @hw: pointer to the HW structure - * - * This function sets the mac type of the adapter based on the - * device ID stored in the hw structure. - * MUST BE FIRST FUNCTION CALLED (explicitly or through - * e1000_setup_init_funcs()). - **/ -s32 e1000_set_mac_type(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_set_mac_type"); - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - mac->type = e1000_82542; - break; - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - mac->type = e1000_82543; - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - mac->type = e1000_82544; - break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - mac->type = e1000_82540; - break; - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - mac->type = e1000_82545; - break; - case E1000_DEV_ID_82545GM_COPPER: - case E1000_DEV_ID_82545GM_FIBER: - case E1000_DEV_ID_82545GM_SERDES: - mac->type = e1000_82545_rev_3; - break; - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - mac->type = e1000_82546; - break; - case E1000_DEV_ID_82546GB_COPPER: - case E1000_DEV_ID_82546GB_FIBER: - case E1000_DEV_ID_82546GB_SERDES: - case E1000_DEV_ID_82546GB_PCIE: - case E1000_DEV_ID_82546GB_QUAD_COPPER: - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - mac->type = e1000_82546_rev_3; - break; - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - case E1000_DEV_ID_82541ER_LOM: - mac->type = e1000_82541; - break; - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_LF: - case E1000_DEV_ID_82541GI_MOBILE: - mac->type = e1000_82541_rev_2; - break; - case E1000_DEV_ID_82547EI: - case E1000_DEV_ID_82547EI_MOBILE: - mac->type = e1000_82547; - break; - case E1000_DEV_ID_82547GI: - mac->type = e1000_82547_rev_2; - break; - default: - /* Should never have loaded on this device */ - ret_val = -E1000_ERR_MAC_INIT; - break; - } - - return ret_val; -} - -/** - * e1000_setup_init_funcs - Initializes function pointers - * @hw: pointer to the HW structure - * @init_device: true will initialize the rest of the function pointers - * getting the device ready for use. false will only set - * MAC type and the function pointers for the other init - * functions. Passing false will not generate any hardware - * reads or writes. - * - * This function must be called by a driver in order to use the rest - * of the 'shared' code files. Called by drivers only. - **/ -s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) -{ - s32 ret_val; - - /* Can't do much good without knowing the MAC type. */ - ret_val = e1000_set_mac_type(hw); - if (ret_val) { - DEBUGOUT("ERROR: MAC type could not be set properly.\n"); - goto out; - } - - if (!hw->hw_addr) { - DEBUGOUT("ERROR: Registers not mapped\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Init function pointers to generic implementations. We do this first - * allowing a driver module to override it afterward. - */ - e1000_init_mac_ops_generic(hw); - e1000_init_phy_ops_generic(hw); - e1000_init_nvm_ops_generic(hw); - - /* - * Set up the init function pointers. These are functions within the - * adapter family file that sets up function pointers for the rest of - * the functions in that family. - */ - switch (hw->mac.type) { - case e1000_82542: - e1000_init_function_pointers_82542(hw); - break; - case e1000_82543: - case e1000_82544: - e1000_init_function_pointers_82543(hw); - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - e1000_init_function_pointers_82540(hw); - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - e1000_init_function_pointers_82541(hw); - break; - default: - DEBUGOUT("Hardware not supported\n"); - ret_val = -E1000_ERR_CONFIG; - break; - } - - /* - * Initialize the rest of the function pointers. These require some - * register reads/writes in some cases. - */ - if (!(ret_val) && init_device) { - ret_val = e1000_init_mac_params(hw); - if (ret_val) - goto out; - - ret_val = e1000_init_nvm_params(hw); - if (ret_val) - goto out; - - ret_val = e1000_init_phy_params(hw); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_get_bus_info - Obtain bus information for adapter - * @hw: pointer to the HW structure - * - * This will obtain information about the HW bus for which the - * adapter is attached and stores it in the hw structure. This is a - * function pointer entry point called by drivers. - **/ -s32 e1000_get_bus_info(struct e1000_hw *hw) -{ - if (hw->mac.ops.get_bus_info) - return hw->mac.ops.get_bus_info(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_clear_vfta - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * This clears the VLAN filter table on the adapter. This is a function - * pointer entry point called by drivers. - **/ -void e1000_clear_vfta(struct e1000_hw *hw) -{ - if (hw->mac.ops.clear_vfta) - hw->mac.ops.clear_vfta(hw); -} - -/** - * e1000_write_vfta - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: the 32-bit offset in which to write the value to. - * @value: the 32-bit value to write at location offset. - * - * This writes a 32-bit value to a 32-bit offset in the VLAN filter - * table. This is a function pointer entry point called by drivers. - **/ -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) -{ - if (hw->mac.ops.write_vfta) - hw->mac.ops.write_vfta(hw, offset, value); -} - -/** - * e1000_update_mc_addr_list - 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 e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count) -{ - if (hw->mac.ops.update_mc_addr_list) - hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, - mc_addr_count); -} - -/** - * e1000_force_mac_fc - Force MAC flow control - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Currently no func pointer exists - * and all implementations are handled in the generic version of this - * function. - **/ -s32 e1000_force_mac_fc(struct e1000_hw *hw) -{ - return e1000_force_mac_fc_generic(hw); -} - -/** - * e1000_check_for_link - Check/Store link connection - * @hw: pointer to the HW structure - * - * This checks the link condition of the adapter and stores the - * results in the hw->mac structure. This is a function pointer entry - * point called by drivers. - **/ -s32 e1000_check_for_link(struct e1000_hw *hw) -{ - if (hw->mac.ops.check_for_link) - return hw->mac.ops.check_for_link(hw); - - return -E1000_ERR_CONFIG; -} - -#if 0 -/** - * e1000_check_mng_mode - Check management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has manageability enabled. - * This is a function pointer entry point called by drivers. - **/ -bool e1000_check_mng_mode(struct e1000_hw *hw) -{ - if (hw->mac.ops.check_mng_mode) - return hw->mac.ops.check_mng_mode(hw); - - return false; -} - -/** - * e1000_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) -{ - return e1000_mng_write_dhcp_info_generic(hw, buffer, length); -} -#endif - -/** - * e1000_reset_hw - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. This is a function pointer - * entry point called by drivers. - **/ -s32 e1000_reset_hw(struct e1000_hw *hw) -{ - if (hw->mac.ops.reset_hw) - return hw->mac.ops.reset_hw(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_init_hw - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. This is a function - * pointer entry point called by drivers. - **/ -s32 e1000_init_hw(struct e1000_hw *hw) -{ - if (hw->mac.ops.init_hw) - return hw->mac.ops.init_hw(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_setup_link - Configures link and flow control - * @hw: pointer to the HW structure - * - * This configures link and flow control settings for the adapter. This - * is a function pointer entry point called by drivers. While modules can - * also call this, they probably call their own version of this function. - **/ -s32 e1000_setup_link(struct e1000_hw *hw) -{ - if (hw->mac.ops.setup_link) - return hw->mac.ops.setup_link(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_get_speed_and_duplex - Returns current speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to a 16-bit value to store the speed - * @duplex: pointer to a 16-bit value to store the duplex. - * - * This returns the speed and duplex of the adapter in the two 'out' - * variables passed in. This is a function pointer entry point called - * by drivers. - **/ -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) -{ - if (hw->mac.ops.get_link_up_info) - return hw->mac.ops.get_link_up_info(hw, speed, duplex); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_setup_led - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. This is a function pointer entry - * point called by drivers. - **/ -s32 e1000_setup_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.setup_led) - return hw->mac.ops.setup_led(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_cleanup_led - Restores SW controllable LED - * @hw: pointer to the HW structure - * - * This restores the SW controllable LED to the value saved off by - * e1000_setup_led. This is a function pointer entry point called by drivers. - **/ -s32 e1000_cleanup_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.cleanup_led) - return hw->mac.ops.cleanup_led(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_blink_led - Blink SW controllable LED - * @hw: pointer to the HW structure - * - * This starts the adapter LED blinking. Request the LED to be setup first - * and cleaned up after. This is a function pointer entry point called by - * drivers. - **/ -s32 e1000_blink_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.blink_led) - return hw->mac.ops.blink_led(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_id_led_init - store LED configurations in SW - * @hw: pointer to the HW structure - * - * Initializes the LED config in SW. This is a function pointer entry point - * called by drivers. - **/ -s32 e1000_id_led_init(struct e1000_hw *hw) -{ - if (hw->mac.ops.id_led_init) - return hw->mac.ops.id_led_init(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_led_on - Turn on SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED on. This is a function pointer entry point - * called by drivers. - **/ -s32 e1000_led_on(struct e1000_hw *hw) -{ - if (hw->mac.ops.led_on) - return hw->mac.ops.led_on(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_led_off - Turn off SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED off. This is a function pointer entry point - * called by drivers. - **/ -s32 e1000_led_off(struct e1000_hw *hw) -{ - if (hw->mac.ops.led_off) - return hw->mac.ops.led_off(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_reset_adaptive - Reset adaptive IFS - * @hw: pointer to the HW structure - * - * Resets the adaptive IFS. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -void e1000_reset_adaptive(struct e1000_hw *hw) -{ - e1000_reset_adaptive_generic(hw); -} - -/** - * e1000_update_adaptive - Update adaptive IFS - * @hw: pointer to the HW structure - * - * Updates adapter IFS. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -void e1000_update_adaptive(struct e1000_hw *hw) -{ - e1000_update_adaptive_generic(hw); -} - -/** - * e1000_disable_pcie_master - Disable PCI-Express master access - * @hw: pointer to the HW structure - * - * Disables PCI-Express master access and verifies there are no pending - * requests. Currently no func pointer exists and all implementations are - * handled in the generic version of this function. - **/ -s32 e1000_disable_pcie_master(struct e1000_hw *hw) -{ - return e1000_disable_pcie_master_generic(hw); -} - -/** - * e1000_config_collision_dist - Configure collision distance - * @hw: pointer to the HW structure - * - * Configures the collision distance to the default value and is used - * during link setup. - **/ -void e1000_config_collision_dist(struct e1000_hw *hw) -{ - if (hw->mac.ops.config_collision_dist) - hw->mac.ops.config_collision_dist(hw); -} - -/** - * e1000_rar_set - Sets a receive address register - * @hw: pointer to the HW structure - * @addr: address to set the RAR to - * @index: the RAR to set - * - * Sets a Receive Address Register (RAR) to the specified address. - **/ -void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) -{ - if (hw->mac.ops.rar_set) - hw->mac.ops.rar_set(hw, addr, index); -} - -/** - * e1000_validate_mdi_setting - Ensures valid MDI/MDIX SW state - * @hw: pointer to the HW structure - * - * Ensures that the MDI/MDIX SW state is valid. - **/ -s32 e1000_validate_mdi_setting(struct e1000_hw *hw) -{ - if (hw->mac.ops.validate_mdi_setting) - return hw->mac.ops.validate_mdi_setting(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_mta_set - Sets multicast table bit - * @hw: pointer to the HW structure - * @hash_value: Multicast hash value. - * - * This sets the bit in the multicast table corresponding to the - * hash value. This is a function pointer entry point called by drivers. - **/ -void e1000_mta_set(struct e1000_hw *hw, u32 hash_value) -{ - if (hw->mac.ops.mta_set) - hw->mac.ops.mta_set(hw, hash_value); -} - -/** - * e1000_hash_mc_addr - Determines address location in multicast table - * @hw: pointer to the HW structure - * @mc_addr: Multicast address to hash. - * - * This hashes an address to determine its location in the multicast - * table. Currently no func pointer exists and all implementations - * are handled in the generic version of this function. - **/ -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - return e1000_hash_mc_addr_generic(hw, mc_addr); -} - -#if 0 -/** - * e1000_enable_tx_pkt_filtering - Enable packet filtering on TX - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - return e1000_enable_tx_pkt_filtering_generic(hw); -} - -/** - * e1000_mng_host_if_write - Writes to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length, - u16 offset, u8 *sum) -{ - if (hw->mac.ops.mng_host_if_write) - return hw->mac.ops.mng_host_if_write(hw, buffer, length, - offset, sum); - - return E1000_NOT_IMPLEMENTED; -} - -/** - * e1000_mng_write_cmd_header - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - if (hw->mac.ops.mng_write_cmd_header) - return hw->mac.ops.mng_write_cmd_header(hw, hdr); - - return E1000_NOT_IMPLEMENTED; -} - -/** - * e1000_mng_enable_host_if - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -s32 e1000_mng_enable_host_if(struct e1000_hw * hw) -{ - if (hw->mac.ops.mng_enable_host_if) - return hw->mac.ops.mng_enable_host_if(hw); - - return E1000_NOT_IMPLEMENTED; -} -#endif - -/** - * e1000_wait_autoneg - Waits for autonegotiation completion - * @hw: pointer to the HW structure - * - * Waits for autoneg to complete. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -s32 e1000_wait_autoneg(struct e1000_hw *hw) -{ - if (hw->mac.ops.wait_autoneg) - return hw->mac.ops.wait_autoneg(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_check_reset_block - Verifies PHY can be reset - * @hw: pointer to the HW structure - * - * Checks if the PHY is in a state that can be reset or if manageability - * has it tied up. This is a function pointer entry point called by drivers. - **/ -s32 e1000_check_reset_block(struct e1000_hw *hw) -{ - if (hw->phy.ops.check_reset_block) - return hw->phy.ops.check_reset_block(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_read_phy_reg - Reads PHY register - * @hw: pointer to the HW structure - * @offset: the register to read - * @data: the buffer to store the 16-bit read. - * - * Reads the PHY register and returns the value in data. - * This is a function pointer entry point called by drivers. - **/ -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - if (hw->phy.ops.read_reg) - return hw->phy.ops.read_reg(hw, offset, data); - - return E1000_SUCCESS; -} - -/** - * e1000_write_phy_reg - Writes PHY register - * @hw: pointer to the HW structure - * @offset: the register to write - * @data: the value to write. - * - * Writes the PHY register at offset with the value in data. - * This is a function pointer entry point called by drivers. - **/ -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - if (hw->phy.ops.write_reg) - return hw->phy.ops.write_reg(hw, offset, data); - - return E1000_SUCCESS; -} - -/** - * e1000_release_phy - Generic release PHY - * @hw: pointer to the HW structure - * - * Return if silicon family does not require a semaphore when accessing the - * PHY. - **/ -void e1000_release_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.release) - hw->phy.ops.release(hw); -} - -/** - * e1000_acquire_phy - Generic acquire PHY - * @hw: pointer to the HW structure - * - * Return success if silicon family does not require a semaphore when - * accessing the PHY. - **/ -s32 e1000_acquire_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.acquire) - return hw->phy.ops.acquire(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_read_kmrn_reg - Reads register using Kumeran interface - * @hw: pointer to the HW structure - * @offset: the register to read - * @data: the location to store the 16-bit value read. - * - * Reads a register out of the Kumeran interface. Currently no func pointer - * exists and all implementations are handled in the generic version of - * this function. - **/ -s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return e1000_read_kmrn_reg_generic(hw, offset, data); -} - -/** - * e1000_write_kmrn_reg - Writes register using Kumeran interface - * @hw: pointer to the HW structure - * @offset: the register to write - * @data: the value to write. - * - * Writes a register to the Kumeran interface. Currently no func pointer - * exists and all implementations are handled in the generic version of - * this function. - **/ -s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - return e1000_write_kmrn_reg_generic(hw, offset, data); -} - -#if 0 -/** - * e1000_get_cable_length - Retrieves cable length estimation - * @hw: pointer to the HW structure - * - * This function estimates the cable length and stores them in - * hw->phy.min_length and hw->phy.max_length. This is a function pointer - * entry point called by drivers. - **/ -s32 e1000_get_cable_length(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_cable_length) - return hw->phy.ops.get_cable_length(hw); - - return E1000_SUCCESS; -} -#endif - -/** - * e1000_get_phy_info - Retrieves PHY information from registers - * @hw: pointer to the HW structure - * - * This function gets some information from various PHY registers and - * populates hw->phy values with it. This is a function pointer entry - * point called by drivers. - **/ -s32 e1000_get_phy_info(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_info) - return hw->phy.ops.get_info(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_phy_hw_reset - Hard PHY reset - * @hw: pointer to the HW structure - * - * Performs a hard PHY reset. This is a function pointer entry point called - * by drivers. - **/ -s32 e1000_phy_hw_reset(struct e1000_hw *hw) -{ - if (hw->phy.ops.reset) - return hw->phy.ops.reset(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_phy_commit - Soft PHY reset - * @hw: pointer to the HW structure - * - * Performs a soft PHY reset on those that apply. This is a function pointer - * entry point called by drivers. - **/ -s32 e1000_phy_commit(struct e1000_hw *hw) -{ - if (hw->phy.ops.commit) - return hw->phy.ops.commit(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_set_d0_lplu_state - Sets low power link up state for D0 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D0 - * and SmartSpeed is disabled when active is true, else clear lplu for D0 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. This is a function pointer entry point called by drivers. - **/ -s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) -{ - if (hw->phy.ops.set_d0_lplu_state) - return hw->phy.ops.set_d0_lplu_state(hw, active); - - return E1000_SUCCESS; -} - -/** - * e1000_set_d3_lplu_state - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. This is a function pointer entry point called by drivers. - **/ -s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - if (hw->phy.ops.set_d3_lplu_state) - return hw->phy.ops.set_d3_lplu_state(hw, active); - - return E1000_SUCCESS; -} - -/** - * e1000_read_mac_addr - Reads MAC address - * @hw: pointer to the HW structure - * - * Reads the MAC address out of the adapter and stores it in the HW structure. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -s32 e1000_read_mac_addr(struct e1000_hw *hw) -{ - if (hw->mac.ops.read_mac_addr) - return hw->mac.ops.read_mac_addr(hw); - - return e1000_read_mac_addr_generic(hw); -} - -/** - * e1000_read_pba_num - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num) -{ - return e1000_read_pba_num_generic(hw, pba_num); -} - -/** - * e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum - * @hw: pointer to the HW structure - * - * Validates the NVM checksum is correct. This is a function pointer entry - * point called by drivers. - **/ -s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) -{ - if (hw->nvm.ops.validate) - return hw->nvm.ops.validate(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_update_nvm_checksum - Updates NVM (EEPROM) checksum - * @hw: pointer to the HW structure - * - * Updates the NVM checksum. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -s32 e1000_update_nvm_checksum(struct e1000_hw *hw) -{ - if (hw->nvm.ops.update) - return hw->nvm.ops.update(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_reload_nvm - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -void e1000_reload_nvm(struct e1000_hw *hw) -{ - if (hw->nvm.ops.reload) - hw->nvm.ops.reload(hw); -} - -/** - * e1000_read_nvm - Reads NVM (EEPROM) - * @hw: pointer to the HW structure - * @offset: the word offset to read - * @words: number of 16-bit words to read - * @data: pointer to the properly sized buffer for the data. - * - * Reads 16-bit chunks of data from the NVM (EEPROM). This is a function - * pointer entry point called by drivers. - **/ -s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - if (hw->nvm.ops.read) - return hw->nvm.ops.read(hw, offset, words, data); - - return -E1000_ERR_CONFIG; -} - -/** - * e1000_write_nvm - Writes to NVM (EEPROM) - * @hw: pointer to the HW structure - * @offset: the word offset to read - * @words: number of 16-bit words to write - * @data: pointer to the properly sized buffer for the data. - * - * Writes 16-bit chunks of data to the NVM (EEPROM). This is a function - * pointer entry point called by drivers. - **/ -s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - if (hw->nvm.ops.write) - return hw->nvm.ops.write(hw, offset, words, data); - - return E1000_SUCCESS; -} - -/** - * e1000_power_up_phy - Restores link in case of PHY power down - * @hw: pointer to the HW structure - * - * The phy may be powered down to save power, to turn off link when the - * driver is unloaded, or wake on lan is not enabled (among others). - **/ -void e1000_power_up_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.power_up) - hw->phy.ops.power_up(hw); - - e1000_setup_link(hw); -} - -/** - * e1000_power_down_phy - Power down PHY - * @hw: pointer to the HW structure - * - * The phy may be powered down to save power, to turn off link when the - * driver is unloaded, or wake on lan is not enabled (among others). - **/ -void e1000_power_down_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.power_down) - hw->phy.ops.power_down(hw); -} diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_api.h b/roms/ipxe/src/drivers/net/e1000/e1000_api.h deleted file mode 100644 index fc1e533d2..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_api.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_API_H_ -#define _E1000_API_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e1000_hw.h" - -extern void e1000_init_function_pointers_82542(struct e1000_hw *hw) __attribute__((weak)); -extern void e1000_init_function_pointers_82543(struct e1000_hw *hw) __attribute__((weak)); -extern void e1000_init_function_pointers_82540(struct e1000_hw *hw) __attribute__((weak)); -extern void e1000_init_function_pointers_82541(struct e1000_hw *hw) __attribute__((weak)); - -s32 e1000_set_mac_type(struct e1000_hw *hw); -s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); -s32 e1000_init_mac_params(struct e1000_hw *hw); -s32 e1000_init_nvm_params(struct e1000_hw *hw); -s32 e1000_init_phy_params(struct e1000_hw *hw); -s32 e1000_get_bus_info(struct e1000_hw *hw); -void e1000_clear_vfta(struct e1000_hw *hw); -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); -s32 e1000_force_mac_fc(struct e1000_hw *hw); -s32 e1000_check_for_link(struct e1000_hw *hw); -s32 e1000_reset_hw(struct e1000_hw *hw); -s32 e1000_init_hw(struct e1000_hw *hw); -s32 e1000_setup_link(struct e1000_hw *hw); -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 e1000_disable_pcie_master(struct e1000_hw *hw); -void e1000_config_collision_dist(struct e1000_hw *hw); -void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); -void e1000_mta_set(struct e1000_hw *hw, u32 hash_value); -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); -void e1000_update_mc_addr_list(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 e1000_setup_led(struct e1000_hw *hw); -s32 e1000_cleanup_led(struct e1000_hw *hw); -s32 e1000_check_reset_block(struct e1000_hw *hw); -s32 e1000_blink_led(struct e1000_hw *hw); -s32 e1000_led_on(struct e1000_hw *hw); -s32 e1000_led_off(struct e1000_hw *hw); -s32 e1000_id_led_init(struct e1000_hw *hw); -void e1000_reset_adaptive(struct e1000_hw *hw); -void e1000_update_adaptive(struct e1000_hw *hw); -#if 0 -s32 e1000_get_cable_length(struct e1000_hw *hw); -#endif -s32 e1000_validate_mdi_setting(struct e1000_hw *hw); -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_get_phy_info(struct e1000_hw *hw); -void e1000_release_phy(struct e1000_hw *hw); -s32 e1000_acquire_phy(struct e1000_hw *hw); -s32 e1000_phy_hw_reset(struct e1000_hw *hw); -s32 e1000_phy_commit(struct e1000_hw *hw); -void e1000_power_up_phy(struct e1000_hw *hw); -void e1000_power_down_phy(struct e1000_hw *hw); -s32 e1000_read_mac_addr(struct e1000_hw *hw); -s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num); -void e1000_reload_nvm(struct e1000_hw *hw); -s32 e1000_update_nvm_checksum(struct e1000_hw *hw); -s32 e1000_validate_nvm_checksum(struct e1000_hw *hw); -s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 e1000_wait_autoneg(struct e1000_hw *hw); -s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); -s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); -bool e1000_check_mng_mode(struct e1000_hw *hw); -bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); -s32 e1000_mng_enable_host_if(struct e1000_hw *hw); -s32 e1000_mng_host_if_write(struct e1000_hw *hw, - u8 *buffer, u16 length, u16 offset, u8 *sum); -s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr); -s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw, - u8 *buffer, u16 length); -u32 e1000_translate_register_82542(u32 reg) __attribute__((weak)); - -extern int e1000_probe(struct pci_device *pdev); -extern void e1000_remove(struct pci_device *pdev); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_defines.h b/roms/ipxe/src/drivers/net/e1000/e1000_defines.h deleted file mode 100644 index c585f09bc..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_defines.h +++ /dev/null @@ -1,1416 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_DEFINES_H_ -#define _E1000_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_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ -/* 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_SDP7_DIR 0x00000800 /* Direction of SDP7 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_82542_TIPG_IPGT 10 -#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_82542_TIPG_IPGR1 2 -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82542_TIPG_IPGR2 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_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 - Microwire */ -#define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */ -#define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */ -#define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */ -#define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */ -#define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */ - -/* 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 PCIX_COMMAND_REGISTER 0xE6 -#define PCIX_STATUS_REGISTER_LO 0xE8 -#define PCIX_STATUS_REGISTER_HI 0xEA -#define PCI_HEADER_TYPE_REGISTER 0x0E -#define PCIE_LINK_STATUS 0x12 -#define PCIE_DEVICE_CONTROL2 0x28 - -#define PCIX_COMMAND_MMRBC_MASK 0x000C -#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -#define PCIX_STATUS_HI_MMRBC_4K 0x3 -#define PCIX_STATUS_HI_MMRBC_2K 0x2 -#define PCIX_STATUS_LO_FUNC_MASK 0x7 -#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 /* _E1000_DEFINES_H_ */ diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_hw.h b/roms/ipxe/src/drivers/net/e1000/e1000_hw.h deleted file mode 100644 index 753f75e7e..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_hw.h +++ /dev/null @@ -1,728 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "e1000_osdep.h" -#include "e1000_regs.h" -#include "e1000_defines.h" - -struct e1000_hw; - -#define E1000_DEV_ID_82542 0x1000 -#define E1000_DEV_ID_82543GC_FIBER 0x1001 -#define E1000_DEV_ID_82543GC_COPPER 0x1004 -#define E1000_DEV_ID_82544EI_COPPER 0x1008 -#define E1000_DEV_ID_82544EI_FIBER 0x1009 -#define E1000_DEV_ID_82544GC_COPPER 0x100C -#define E1000_DEV_ID_82544GC_LOM 0x100D -#define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82540EM_LOM 0x1015 -#define E1000_DEV_ID_82540EP_LOM 0x1016 -#define E1000_DEV_ID_82540EP 0x1017 -#define E1000_DEV_ID_82540EP_LP 0x101E -#define E1000_DEV_ID_82545EM_COPPER 0x100F -#define E1000_DEV_ID_82545EM_FIBER 0x1011 -#define E1000_DEV_ID_82545GM_COPPER 0x1026 -#define E1000_DEV_ID_82545GM_FIBER 0x1027 -#define E1000_DEV_ID_82545GM_SERDES 0x1028 -#define E1000_DEV_ID_82546EB_COPPER 0x1010 -#define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D -#define E1000_DEV_ID_82546GB_COPPER 0x1079 -#define E1000_DEV_ID_82546GB_FIBER 0x107A -#define E1000_DEV_ID_82546GB_SERDES 0x107B -#define E1000_DEV_ID_82546GB_PCIE 0x108A -#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 -#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 -#define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EI_MOBILE 0x1018 -#define E1000_DEV_ID_82541ER_LOM 0x1014 -#define E1000_DEV_ID_82541ER 0x1078 -#define E1000_DEV_ID_82541GI 0x1076 -#define E1000_DEV_ID_82541GI_LF 0x107C -#define E1000_DEV_ID_82541GI_MOBILE 0x1077 -#define E1000_DEV_ID_82547EI 0x1019 -#define E1000_DEV_ID_82547EI_MOBILE 0x101A -#define E1000_DEV_ID_82547GI 0x1075 -#define E1000_REVISION_0 0 -#define E1000_REVISION_1 1 -#define E1000_REVISION_2 2 -#define E1000_REVISION_3 3 -#define E1000_REVISION_4 4 - -#define E1000_FUNC_0 0 -#define E1000_FUNC_1 1 - -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 - -enum e1000_mac_type { - e1000_undefined = 0, - e1000_82542, - e1000_82543, - e1000_82544, - e1000_82540, - e1000_82545, - e1000_82545_rev_3, - e1000_82546, - e1000_82546_rev_3, - e1000_82541, - e1000_82541_rev_2, - e1000_82547, - e1000_82547_rev_2, - e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ -}; - -enum e1000_media_type { - e1000_media_type_unknown = 0, - e1000_media_type_copper = 1, - e1000_media_type_fiber = 2, - e1000_media_type_internal_serdes = 3, - e1000_num_media_types -}; - -enum e1000_nvm_type { - e1000_nvm_unknown = 0, - e1000_nvm_none, - e1000_nvm_eeprom_spi, - e1000_nvm_eeprom_microwire, - e1000_nvm_flash_hw, - e1000_nvm_flash_sw -}; - -enum e1000_nvm_override { - e1000_nvm_override_none = 0, - e1000_nvm_override_spi_small, - e1000_nvm_override_spi_large, - e1000_nvm_override_microwire_small, - e1000_nvm_override_microwire_large -}; - -enum e1000_phy_type { - e1000_phy_unknown = 0, - e1000_phy_none, - e1000_phy_m88, - e1000_phy_igp, - e1000_phy_igp_2, - e1000_phy_gg82563, - e1000_phy_igp_3, - e1000_phy_ife, -}; - -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 -}; - -enum e1000_1000t_rx_status { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -}; - -enum e1000_rev_polarity { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -}; - -enum e1000_fc_mode { - e1000_fc_none = 0, - e1000_fc_rx_pause, - e1000_fc_tx_pause, - e1000_fc_full, - e1000_fc_default = 0xFF -}; - -enum e1000_ffe_config { - e1000_ffe_config_enabled = 0, - e1000_ffe_config_active, - e1000_ffe_config_blocked -}; - -enum e1000_dsp_config { - e1000_dsp_config_disabled = 0, - e1000_dsp_config_enabled, - e1000_dsp_config_activated, - e1000_dsp_config_undefined = 0xFF -}; - -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - -enum e1000_serdes_link_state { - e1000_serdes_link_down = 0, - e1000_serdes_link_autoneg_progress, - e1000_serdes_link_autoneg_complete, - e1000_serdes_link_forced_up -}; - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorc; - u64 gotc; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 tor; - u64 tot; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; - u64 cbtmpc; - u64 htdpmc; - u64 cbrdpc; - u64 cbrmpc; - u64 rpthc; - u64 hgptc; - u64 htcbdpc; - u64 hgorc; - u64 hgotc; - u64 lenerrs; - u64 scvpc; - u64 hrmpc; - u64 doosync; -}; - - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; - -/* Host Interface "Rev 1" */ -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; - u8 checksum; -}; - -#define E1000_HI_MAX_DATA_LENGTH 252 -struct e1000_host_command_info { - struct e1000_host_command_header command_header; - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -}; - -/* Host Interface "Rev 2" */ -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -}; - -#include "e1000_mac.h" -#include "e1000_phy.h" -#include "e1000_nvm.h" -#include "e1000_manage.h" - -struct e1000_mac_operations { - /* Function pointers for the MAC. */ - s32 (*init_params)(struct e1000_hw *); - s32 (*id_led_init)(struct e1000_hw *); - s32 (*blink_led)(struct e1000_hw *); - s32 (*check_for_link)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *hw); - s32 (*cleanup_led)(struct e1000_hw *); - void (*clear_hw_cntrs)(struct e1000_hw *); - void (*clear_vfta)(struct e1000_hw *); - s32 (*get_bus_info)(struct e1000_hw *); - void (*set_lan_id)(struct e1000_hw *); - s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); - s32 (*led_on)(struct e1000_hw *); - s32 (*led_off)(struct e1000_hw *); - 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 *); - s32 (*setup_physical_interface)(struct e1000_hw *); - s32 (*setup_led)(struct e1000_hw *); - void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*mta_set)(struct e1000_hw *, u32); - void (*config_collision_dist)(struct e1000_hw *); - void (*rar_set)(struct e1000_hw *, u8*, u32); - s32 (*read_mac_addr)(struct e1000_hw *); - s32 (*validate_mdi_setting)(struct e1000_hw *); - s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); - s32 (*mng_write_cmd_header)(struct e1000_hw *hw, - struct e1000_host_mng_command_header*); - s32 (*mng_enable_host_if)(struct e1000_hw *); - s32 (*wait_autoneg)(struct e1000_hw *); -}; - -struct e1000_phy_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*check_polarity)(struct e1000_hw *); - s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit)(struct e1000_hw *); -#if 0 - s32 (*force_speed_duplex)(struct e1000_hw *); -#endif - s32 (*get_cfg_done)(struct e1000_hw *hw); -#if 0 - s32 (*get_cable_length)(struct e1000_hw *); -#endif - s32 (*get_info)(struct e1000_hw *); - s32 (*read_reg)(struct e1000_hw *, u32, u16 *); - void (*release)(struct e1000_hw *); - s32 (*reset)(struct e1000_hw *); - s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); - s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_reg)(struct e1000_hw *, u32, u16); - void (*power_up)(struct e1000_hw *); - void (*power_down)(struct e1000_hw *); -}; - -struct e1000_nvm_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*read)(struct e1000_hw *, u16, u16, u16 *); - void (*release)(struct e1000_hw *); - void (*reload)(struct e1000_hw *); - s32 (*update)(struct e1000_hw *); - s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate)(struct e1000_hw *); - s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -}; - -struct e1000_mac_info { - struct e1000_mac_operations ops; - u8 addr[6]; - u8 perm_addr[6]; - - enum e1000_mac_type type; - - u32 collision_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - u32 mc_filter_type; - u32 tx_packet_delta; - u32 txcw; - - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; - u16 mta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ - #define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; - u16 rar_entry_count; - - u8 forced_speed_duplex; - - bool adaptive_ifs; - bool arc_subsystem_valid; - bool asf_firmware_present; - bool autoneg; - bool autoneg_failed; - bool get_link_status; - bool in_ifs_mode; - bool report_tx_early; - enum e1000_serdes_link_state serdes_link_state; - bool serdes_has_link; - bool tx_pkt_filtering; -}; - -struct e1000_phy_info { - struct e1000_phy_operations ops; - enum e1000_phy_type type; - - enum e1000_1000t_rx_status local_rx; - enum e1000_1000t_rx_status remote_rx; - enum e1000_ms_type ms_type; - enum e1000_ms_type original_ms_type; - enum e1000_rev_polarity cable_polarity; - enum e1000_smart_speed smart_speed; - - u32 addr; - u32 id; - u32 reset_delay_us; /* in usec */ - u32 revision; - - enum e1000_media_type media_type; - - u16 autoneg_advertised; - u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - - u8 mdix; - - bool disable_polarity_correction; - bool is_mdix; - bool polarity_correction; - bool reset_disable; - bool speed_downgraded; - bool autoneg_wait_to_complete; -}; - -struct e1000_nvm_info { - struct e1000_nvm_operations ops; - enum e1000_nvm_type type; - enum e1000_nvm_override override; - - u32 flash_bank_size; - u32 flash_base_addr; - - u16 word_size; - u16 delay_usec; - u16 address_bits; - u16 opcode_bits; - u16 page_size; -}; - -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_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* FC mode in effect */ - enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ -}; - -struct e1000_dev_spec_82541 { - enum e1000_dsp_config dsp_config; - enum e1000_ffe_config ffe_config; - u16 spd_default; - bool phy_init_script; -}; - -struct e1000_dev_spec_82542 { - bool dma_fairness; -}; - -struct e1000_dev_spec_82543 { - u32 tbi_compatibility; - bool dma_fairness; - bool init_phy_disabled; -}; - -struct e1000_hw { - void *back; - - u8 __iomem *hw_addr; - u8 __iomem *flash_address; - unsigned long io_base; - - struct e1000_mac_info mac; - struct e1000_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; - struct e1000_host_mng_dhcp_cookie mng_cookie; - - union { - struct e1000_dev_spec_82541 _82541; - struct e1000_dev_spec_82542 _82542; - struct e1000_dev_spec_82543 _82543; - } dev_spec; - - u16 device_id; - u16 subsystem_vendor_id; - u16 subsystem_device_id; - u16 vendor_id; - - u8 revision_id; -}; - -#include "e1000_82541.h" -#include "e1000_82543.h" - -/* These functions must be implemented by drivers */ -void e1000_pci_clear_mwi(struct e1000_hw *hw); -void e1000_pci_set_mwi(struct e1000_hw *hw); -s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); -void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_mac.c b/roms/ipxe/src/drivers/net/e1000/e1000_mac.c deleted file mode 100644 index 235138798..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_mac.c +++ /dev/null @@ -1,2196 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000_api.h" - -static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); -static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); - -/** - * e1000_init_mac_ops_generic - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void e1000_init_mac_ops_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - DEBUGFUNC("e1000_init_mac_ops_generic"); - - /* General Setup */ - mac->ops.init_params = e1000_null_ops_generic; - mac->ops.init_hw = e1000_null_ops_generic; - mac->ops.reset_hw = e1000_null_ops_generic; - mac->ops.setup_physical_interface = e1000_null_ops_generic; - mac->ops.get_bus_info = e1000_null_ops_generic; - mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; - mac->ops.read_mac_addr = e1000_read_mac_addr_generic; - mac->ops.config_collision_dist = e1000_config_collision_dist_generic; - mac->ops.clear_hw_cntrs = e1000_null_mac_generic; - /* LED */ - mac->ops.cleanup_led = e1000_null_ops_generic; - mac->ops.setup_led = e1000_null_ops_generic; - mac->ops.blink_led = e1000_null_ops_generic; - mac->ops.led_on = e1000_null_ops_generic; - mac->ops.led_off = e1000_null_ops_generic; - /* LINK */ - mac->ops.setup_link = e1000_null_ops_generic; - mac->ops.get_link_up_info = e1000_null_link_info; - mac->ops.check_for_link = e1000_null_ops_generic; - mac->ops.wait_autoneg = e1000_wait_autoneg_generic; -#if 0 - /* Management */ - mac->ops.check_mng_mode = e1000_null_mng_mode; - mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic; - mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; - mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic; -#endif - /* VLAN, MC, etc. */ - mac->ops.update_mc_addr_list = e1000_null_update_mc; - mac->ops.clear_vfta = e1000_null_mac_generic; - mac->ops.write_vfta = e1000_null_write_vfta; - mac->ops.mta_set = e1000_null_mta_set; - mac->ops.rar_set = e1000_rar_set_generic; - mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; -} - -/** - * e1000_null_ops_generic - No-op function, returns 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_ops_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_null_ops_generic"); - return E1000_SUCCESS; -} - -/** - * e1000_null_mac_generic - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_mac_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_null_mac_generic"); - return; -} - -/** - * e1000_null_link_info - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_link_info(struct e1000_hw *hw __unused, - u16 *s __unused, u16 *d __unused) -{ - DEBUGFUNC("e1000_null_link_info"); - return E1000_SUCCESS; -} - -/** - * e1000_null_mng_mode - No-op function, return false - * @hw: pointer to the HW structure - **/ -bool e1000_null_mng_mode(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_null_mng_mode"); - return false; -} - -/** - * e1000_null_update_mc - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_update_mc(struct e1000_hw *hw __unused, - u8 *h __unused, u32 a __unused) -{ - DEBUGFUNC("e1000_null_update_mc"); - return; -} - -/** - * e1000_null_write_vfta - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_write_vfta(struct e1000_hw *hw __unused, - u32 a __unused, u32 b __unused) -{ - DEBUGFUNC("e1000_null_write_vfta"); - return; -} - -/** - * e1000_null_set_mta - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_mta_set(struct e1000_hw *hw __unused, u32 a __unused) -{ - DEBUGFUNC("e1000_null_mta_set"); - return; -} - -/** - * e1000_null_rar_set - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_rar_set(struct e1000_hw *hw __unused, u8 *h __unused, - u32 a __unused) -{ - DEBUGFUNC("e1000_null_rar_set"); - return; -} - -/** - * e1000_get_bus_info_pci_generic - Get PCI(x) bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCI/PCIx), and PCI(-x) function. - **/ -s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - u32 status = E1000_READ_REG(hw, E1000_STATUS); - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_get_bus_info_pci_generic"); - - /* PCI or PCI-X? */ - bus->type = (status & E1000_STATUS_PCIX_MODE) - ? e1000_bus_type_pcix - : e1000_bus_type_pci; - - /* Bus speed */ - if (bus->type == e1000_bus_type_pci) { - bus->speed = (status & E1000_STATUS_PCI66) - ? e1000_bus_speed_66 - : e1000_bus_speed_33; - } else { - switch (status & E1000_STATUS_PCIX_SPEED) { - case E1000_STATUS_PCIX_SPEED_66: - bus->speed = e1000_bus_speed_66; - break; - case E1000_STATUS_PCIX_SPEED_100: - bus->speed = e1000_bus_speed_100; - break; - case E1000_STATUS_PCIX_SPEED_133: - bus->speed = e1000_bus_speed_133; - break; - default: - bus->speed = e1000_bus_speed_reserved; - break; - } - } - - /* Bus width */ - bus->width = (status & E1000_STATUS_BUS64) - ? e1000_bus_width_64 - : e1000_bus_width_32; - - /* Which PCI(-X) function? */ - mac->ops.set_lan_id(hw); - - return ret_val; -#endif - return 0; -} - -/** - * e1000_get_bus_info_pcie_generic - Get PCIe bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCIe), and PCIe function. - **/ -s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - - s32 ret_val; - u16 pcie_link_status; - - DEBUGFUNC("e1000_get_bus_info_pcie_generic"); - - bus->type = e1000_bus_type_pci_express; - bus->speed = e1000_bus_speed_2500; - - ret_val = e1000_read_pcie_cap_reg(hw, - PCIE_LINK_STATUS, - &pcie_link_status); - if (ret_val) - bus->width = e1000_bus_width_unknown; - else - bus->width = (enum e1000_bus_width)((pcie_link_status & - PCIE_LINK_WIDTH_MASK) >> - PCIE_LINK_WIDTH_SHIFT); - - mac->ops.set_lan_id(hw); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices - * - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading memory-mapped registers - * and swaps the port value if requested. - **/ -static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u32 reg; - - /* - * The status register reports the correct function number - * for the device regardless of function swap state. - */ - reg = E1000_READ_REG(hw, E1000_STATUS); - bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; -} - -/** - * e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading PCI config space. - **/ -void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u16 pci_header_type; - u32 status; - - e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); - if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { - status = E1000_READ_REG(hw, E1000_STATUS); - bus->func = (status & E1000_STATUS_FUNC_MASK) - >> E1000_STATUS_FUNC_SHIFT; - } else { - bus->func = 0; - } -} - -/** - * e1000_set_lan_id_single_port - Set LAN id for a single port device - * @hw: pointer to the HW structure - * - * Sets the LAN function id to zero for a single port device. - **/ -void e1000_set_lan_id_single_port(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - - bus->func = 0; -} - -/** - * e1000_clear_vfta_generic - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -void e1000_clear_vfta_generic(struct e1000_hw *hw) -{ - u32 offset; - - DEBUGFUNC("e1000_clear_vfta_generic"); - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); - E1000_WRITE_FLUSH(hw); - } -} - -/** - * e1000_write_vfta_generic - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: register offset in VLAN filter table - * @value: register value written to VLAN filter table - * - * Writes value at the given offset in the register array which stores - * the VLAN filter table. - **/ -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) -{ - DEBUGFUNC("e1000_write_vfta_generic"); - - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - E1000_WRITE_FLUSH(hw); -} - -/** - * e1000_init_rx_addrs_generic - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setups the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ADDR_LEN] = {0}; - - DEBUGFUNC("e1000_init_rx_addrs_generic"); - - /* Setup the receive address */ - DEBUGOUT("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - -/** - * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr - * @hw: pointer to the HW structure - * - * Checks the nvm for an alternate MAC address. An alternate MAC address - * can be setup by pre-boot software and must be treated like a permanent - * address and must override the actual permanent MAC address. If an - * alternate MAC address is found it is programmed into RAR0, replacing - * the permanent address that was installed into RAR0 by the Si on reset. - * This function will return SUCCESS unless it encounters an error while - * reading the EEPROM. - **/ -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) -{ - u32 i; - s32 ret_val = E1000_SUCCESS; - u16 offset, nvm_alt_mac_addr_offset, nvm_data; - u8 alt_mac_addr[ETH_ADDR_LEN]; - - DEBUGFUNC("e1000_check_alt_mac_addr_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if (nvm_alt_mac_addr_offset == 0xFFFF) { - /* There is no Alternate MAC Address */ - goto out; - } - - if (hw->bus.func == E1000_FUNC_1) - nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; - for (i = 0; i < ETH_ADDR_LEN; i += 2) { - offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - alt_mac_addr[i] = (u8)(nvm_data & 0xFF); - alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); - } - - /* if multicast bit is set, the alternate address will not be used */ - if (alt_mac_addr[0] & 0x01) { - DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); - goto out; - } - - /* - * We have a valid alternate MAC address, and we want to treat it the - * same as the normal permanent MAC address stored by the HW into the - * RAR. Do this by mapping this address into RAR0. - */ - hw->mac.ops.rar_set(hw, alt_mac_addr, 0); - -out: - return ret_val; -} - -/** - * e1000_rar_set_generic - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - DEBUGFUNC("e1000_rar_set_generic"); - - /* - * HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | - ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - /* - * Some bridges will combine consecutive 32-bit writes into - * a single burst write, which will malfunction on some parts. - * The flushes avoid this. - */ - E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); - E1000_WRITE_FLUSH(hw); - E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); - E1000_WRITE_FLUSH(hw); -} - -/** - * e1000_mta_set_generic - Set multicast filter table address - * @hw: pointer to the HW structure - * @hash_value: determines the MTA register and bit to set - * - * The multicast table address is a register array of 32-bit registers. - * The hash_value is used to determine what register the bit is in, the - * current value is read, the new bit is OR'd in and the new value is - * written back into the register. - **/ -void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg, mta; - - DEBUGFUNC("e1000_mta_set_generic"); - /* - * The MTA is a register array of 32-bit registers. It is - * treated like an array of (32*mta_reg_count) bits. We want to - * set bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The (hw->mac.mta_reg_count - 1) serves as a - * mask to bits 31:5 of the hash value which gives us the - * register we're modifying. The hash bit within that register - * is determined by the lower 5 bits of the hash value. - */ - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); - - mta |= (1 << hash_bit); - - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); - E1000_WRITE_FLUSH(hw); -} - -/** - * e1000_update_mc_addr_list_generic - 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 entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - DEBUGFUNC("e1000_update_mc_addr_list_generic"); - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32) i < mc_addr_count; i++) { - hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ADDR_LEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - E1000_WRITE_FLUSH(hw); -} - -/** - * e1000_hash_mc_addr_generic - 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 - * e1000_mta_set_generic() - **/ -u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value, hash_mask; - u8 bit_shift = 0; - - DEBUGFUNC("e1000_hash_mc_addr_generic"); - - /* Register count multiplied by bits per register */ - hash_mask = (hw->mac.mta_reg_count * 32) - 1; - - /* - * For a mc_filter_type of 0, 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++; - - /* - * The portion of the address that is used for the hash table - * is determined by the mc_filter_type setting. - * The algorithm is such that there is a total of 8 bits of shifting. - * The bit_shift for a mc_filter_type of 0 represents the number of - * left-shifts where the MSB of mc_addr[5] would still fall within - * the hash_mask. Case 0 does this exactly. Since there are a total - * of 8 bits of shifting, then mc_addr[4] will shift right the - * remaining number of bits. Thus 8 - bit_shift. The rest of the - * cases are a variation of this algorithm...essentially raising the - * number of bits to shift mc_addr[5] left, while still keeping the - * 8-bit shifting total. - * - * For example, given the following Destination MAC Address and an - * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), - * we can see that the bit_shift for case 0 is 4. These are the hash - * values resulting from each mc_filter_type... - * [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - * - * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 - * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 - * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 - * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 - */ - switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; - } - - hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16) mc_addr[5]) << bit_shift))); - - return hash_value; -} - -/** - * e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value - * @hw: pointer to the HW structure - * - * In certain situations, a system BIOS may report that the PCIx maximum - * memory read byte count (MMRBC) value is higher than than the actual - * value. We check the PCIx command register with the current PCIx status - * register. - **/ -void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw) -{ - u16 cmd_mmrbc; - u16 pcix_cmd; - u16 pcix_stat_hi_word; - u16 stat_mmrbc; - - DEBUGFUNC("e1000_pcix_mmrbc_workaround_generic"); - - /* Workaround for PCI-X issue when BIOS sets MMRBC incorrectly */ - if (hw->bus.type != e1000_bus_type_pcix) - return; - - e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd); - e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); - cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >> - PCIX_COMMAND_MMRBC_SHIFT; - stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> - PCIX_STATUS_HI_MMRBC_SHIFT; - if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) - stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if (cmd_mmrbc > stat_mmrbc) { - pcix_cmd &= ~PCIX_COMMAND_MMRBC_MASK; - pcix_cmd |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; - e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd); - } -} - -/** - * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters - * @hw: pointer to the HW structure - * - * Clears the base hardware counters by reading the counter registers. - **/ -void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); - -#if 0 - E1000_READ_REG(hw, E1000_CRCERRS); - E1000_READ_REG(hw, E1000_SYMERRS); - E1000_READ_REG(hw, E1000_MPC); - E1000_READ_REG(hw, E1000_SCC); - E1000_READ_REG(hw, E1000_ECOL); - E1000_READ_REG(hw, E1000_MCC); - E1000_READ_REG(hw, E1000_LATECOL); - E1000_READ_REG(hw, E1000_COLC); - E1000_READ_REG(hw, E1000_DC); - E1000_READ_REG(hw, E1000_SEC); - E1000_READ_REG(hw, E1000_RLEC); - E1000_READ_REG(hw, E1000_XONRXC); - E1000_READ_REG(hw, E1000_XONTXC); - E1000_READ_REG(hw, E1000_XOFFRXC); - E1000_READ_REG(hw, E1000_XOFFTXC); - E1000_READ_REG(hw, E1000_FCRUC); - E1000_READ_REG(hw, E1000_GPRC); - E1000_READ_REG(hw, E1000_BPRC); - E1000_READ_REG(hw, E1000_MPRC); - E1000_READ_REG(hw, E1000_GPTC); - E1000_READ_REG(hw, E1000_GORCL); - E1000_READ_REG(hw, E1000_GORCH); - E1000_READ_REG(hw, E1000_GOTCL); - E1000_READ_REG(hw, E1000_GOTCH); - E1000_READ_REG(hw, E1000_RNBC); - E1000_READ_REG(hw, E1000_RUC); - E1000_READ_REG(hw, E1000_RFC); - E1000_READ_REG(hw, E1000_ROC); - E1000_READ_REG(hw, E1000_RJC); - E1000_READ_REG(hw, E1000_TORL); - E1000_READ_REG(hw, E1000_TORH); - E1000_READ_REG(hw, E1000_TOTL); - E1000_READ_REG(hw, E1000_TOTH); - E1000_READ_REG(hw, E1000_TPR); - E1000_READ_REG(hw, E1000_TPT); - E1000_READ_REG(hw, E1000_MPTC); - E1000_READ_REG(hw, E1000_BPTC); -#endif -} - -/** - * e1000_check_for_copper_link_generic - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - DEBUGFUNC("e1000_check_for_copper_link"); - - /* - * We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) - goto out; /* No link detected */ - - mac->get_link_status = false; - - /* - * Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000_check_downshift_generic(hw); - - /* - * If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - e1000_config_collision_dist_generic(hw); - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) - DEBUGOUT("Error configuring flow control\n"); - -out: - return ret_val; -} - -/** - * e1000_check_for_fiber_link_generic - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_check_for_fiber_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - status = E1000_READ_REG(hw, E1000_STATUS); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); - E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - -out: - return ret_val; -} - -/** - * e1000_check_for_serdes_link_generic - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_check_for_serdes_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - status = E1000_READ_REG(hw, E1000_STATUS); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); - E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { - /* - * If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - usec_delay(10); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - DEBUGOUT("SERDES: Link up - forced.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { - status = E1000_READ_REG(hw, E1000_STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - usec_delay(10); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - DEBUGOUT("SERDES: Link up - autoneg " - "completed sucessfully.\n"); - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - no sync.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - autoneg failed\n"); - } - } - -out: - return ret_val; -} - -/** - * e1000_setup_link_generic - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -s32 e1000_setup_link_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_link_generic"); - - /* - * In the case of the phy reset being blocked, we already have a link. - * We do not need to set it up again. - */ - if (hw->phy.ops.check_reset_block) - if (hw->phy.ops.check_reset_block(hw)) - goto out; - - /* - * If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = e1000_set_default_fc_generic(hw); - if (ret_val) - goto out; - } - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); - - /* Call the necessary media_type subroutine to configure the link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - goto out; - - /* - * Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); - E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); - E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); - - E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); - - ret_val = e1000_set_fc_watermarks_generic(hw); - -out: - return ret_val; -} - -/** - * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. - **/ -s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - e1000_config_collision_dist_generic(hw); - - ret_val = e1000_commit_fc_settings_generic(hw); - if (ret_val) - goto out; - - /* - * Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - DEBUGOUT("Auto-negotiation enabled\n"); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - msec_delay(1); - - /* - * For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. - */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000_poll_fiber_serdes_link_generic(hw); - } else { - DEBUGOUT("No signal detected\n"); - } - -out: - return ret_val; -} - -/** - * e1000_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 e1000_config_collision_dist_generic(struct e1000_hw *hw) -{ - u32 tctl; - - DEBUGFUNC("e1000_config_collision_dist_generic"); - - tctl = E1000_READ_REG(hw, E1000_TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - E1000_WRITE_REG(hw, E1000_TCTL, tctl); - E1000_WRITE_FLUSH(hw); -} - -/** - * e1000_poll_fiber_serdes_link_generic - Poll for link up - * @hw: pointer to the HW structure - * - * Polls for link up by reading the status register, if link fails to come - * up with auto-negotiation, then the link is forced if a signal is detected. - **/ -s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 i, status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); - - /* - * If we have a signal (the cable is plugged in, or assumed true for - * serdes media) then poll for a "Link-Up" indication in the Device - * Status Register. Time-out if a link isn't seen in 500 milliseconds - * seconds (Auto-negotiation should complete in less than 500 - * milliseconds even if the other end is doing it in SW). - */ - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - msec_delay(10); - status = E1000_READ_REG(hw, E1000_STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == FIBER_LINK_UP_LIMIT) { - DEBUGOUT("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = 1; - /* - * AutoNeg failed to achieve a link, so we'll call - * mac->check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = hw->mac.ops.check_for_link(hw); - if (ret_val) { - DEBUGOUT("Error while checking for link\n"); - goto out; - } - mac->autoneg_failed = 0; - } else { - mac->autoneg_failed = 0; - DEBUGOUT("Valid Link Found\n"); - } - -out: - return ret_val; -} - -/** - * e1000_commit_fc_settings_generic - Configure flow control - * @hw: pointer to the HW structure - * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. - **/ -s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_commit_fc_settings_generic"); - - /* - * Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric RX - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - - E1000_WRITE_REG(hw, E1000_TXCW, txcw); - mac->txcw = txcw; - -out: - return ret_val; -} - -/** - * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks - * @hw: pointer to the HW structure - * - * Sets the flow control high/low threshold (watermark) registers. If - * flow control XON frame transmission is enabled, then set XON frame - * transmission as well. - **/ -s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u32 fcrtl = 0, fcrth = 0; - - DEBUGFUNC("e1000_set_fc_watermarks_generic"); - - /* - * Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames is not enabled, then these - * registers will be set to 0. - */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - fcrtl = hw->fc.low_water; - if (hw->fc.send_xon) - fcrtl |= E1000_FCRTL_XONE; - - fcrth = hw->fc.high_water; - } - E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); - E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); - - return ret_val; -} - -/** - * e1000_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -s32 e1000_set_default_fc_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 nvm_data; - - DEBUGFUNC("e1000_set_default_fc_generic"); - - /* - * Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); - - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == - NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - -out: - return ret_val; -} - -/** - * e1000_force_mac_fc_generic - Force the MAC's flow control settings - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the - * device control register to reflect the adapter settings. TFCE and RFCE - * need to be explicitly set by software when a copper PHY is used because - * autonegotiation is managed by the PHY rather than the MAC. Software must - * also configure these bits when link is forced on a fiber connection. - **/ -s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_force_mac_fc_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* - * Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and Tx flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); - - switch (hw->fc.current_mode) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - -out: - return ret_val; -} - -/** - * e1000_config_fc_after_link_up_generic - Configures flow control after link - * @hw: pointer to the HW structure - * - * Checks the status of auto-negotiation after link up to ensure that the - * speed and duplex were not forced. If the link needed to be forced, then - * flow control needs to be forced also. If auto-negotiation is enabled - * and did not fail, then we configure flow control based on our link - * partner. - **/ -s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; - u16 speed, duplex; - - DEBUGFUNC("e1000_config_fc_after_link_up_generic"); - - /* - * Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) - ret_val = e1000_force_mac_fc_generic(hw); - } else { - if (hw->phy.media_type == e1000_media_type_copper) - ret_val = e1000_force_mac_fc_generic(hw); - } - - if (ret_val) { - DEBUGOUT("Error forcing flow control settings\n"); - goto out; - } - - /* - * Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* - * Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - - if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { - DEBUGOUT("Copper PHY and Auto Neg " - "has not completed.\n"); - goto out; - } - - /* - * The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (Address 4) and the Auto_Negotiation Base - * Page Ability Register (Address 5) to determine how - * flow control was negotiated. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg); - if (ret_val) - goto out; - ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg); - if (ret_val) - goto out; - - /* - * Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | E1000_fc_full - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = " - "RX PAUSE frames only.\r\n"); - } - } - /* - * For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); - } - /* - * For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); - } else { - /* - * Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); - } - - /* - * Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - DEBUGOUT("Error getting link speed and duplex\n"); - goto out; - } - - if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; - - /* - * Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000_force_mac_fc_generic(hw); - if (ret_val) { - DEBUGOUT("Error forcing flow control settings\n"); - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Read the status register for the current speed/duplex and store the current - * speed and duplex for copper connections. - **/ -s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - u32 status; - - DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic"); - - 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; -} - -/** - * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Sets the speed and duplex to gigabit full duplex (the only possible option) - * for fiber/serdes links. - **/ -s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw __unused, - u16 *speed, u16 *duplex) -{ - DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); - - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - - return E1000_SUCCESS; -} - -/** - * e1000_get_hw_semaphore_generic - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 swsm; - s32 ret_val = E1000_SUCCESS; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - DEBUGFUNC("e1000_get_hw_semaphore_generic"); - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = E1000_READ_REG(hw, E1000_SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usec_delay(50); - i++; - } - - if (i == timeout) { - DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = E1000_READ_REG(hw, E1000_SWSM); - E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) - break; - - usec_delay(50); - } - - if (i == timeout) { - /* Release semaphores */ - e1000_put_hw_semaphore_generic(hw); - DEBUGOUT("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_put_hw_semaphore_generic - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void e1000_put_hw_semaphore_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 swsm; - - DEBUGFUNC("e1000_put_hw_semaphore_generic"); - - swsm = E1000_READ_REG(hw, E1000_SWSM); - - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - - E1000_WRITE_REG(hw, E1000_SWSM, swsm); -#endif -} - -/** - * e1000_get_auto_rd_done_generic - Check for auto read completion - * @hw: pointer to the HW structure - * - * Check EEPROM for Auto Read done bit. - **/ -s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) -{ - s32 i = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_get_auto_rd_done_generic"); - - while (i < AUTO_READ_DONE_TIMEOUT) { - if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) - break; - msec_delay(1); - i++; - } - - if (i == AUTO_READ_DONE_TIMEOUT) { - DEBUGOUT("Auto read by HW from NVM has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_valid_led_default_generic - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - DEBUGFUNC("e1000_valid_led_default_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - -out: - return ret_val; -} - -/** - * e1000_id_led_init_generic - - * @hw: pointer to the HW structure - * - **/ -s32 e1000_id_led_init_generic(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 data, i, temp; - const u16 led_mask = 0x0F; - - DEBUGFUNC("e1000_id_led_init_generic"); - - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - goto out; - - mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_setup_led_generic - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -s32 e1000_setup_led_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ledctl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_setup_led_generic"); - - if (hw->mac.ops.setup_led != e1000_setup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - if (hw->phy.media_type == e1000_media_type_fiber) { - ledctl = E1000_READ_REG(hw, E1000_LEDCTL); - hw->mac.ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); - } else if (hw->phy.media_type == e1000_media_type_copper) { - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); - } - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_cleanup_led_generic - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -s32 e1000_cleanup_led_generic(struct e1000_hw *hw __unused) -{ -#if 0 - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_cleanup_led_generic"); - - if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); - -out: - return ret_val; -#endif - return 0; -} - -/** - * e1000_blink_led_generic - Blink LED - * @hw: pointer to the HW structure - * - * Blink the LEDs which are set to be on. - **/ -s32 e1000_blink_led_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ledctl_blink = 0; - u32 i; - - DEBUGFUNC("e1000_blink_led_generic"); - - if (hw->phy.media_type == e1000_media_type_fiber) { - /* always blink LED0 for PCI-E fiber */ - ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); - } else { - /* - * set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); - } - - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_led_on_generic - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -s32 e1000_led_on_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl; - - DEBUGFUNC("e1000_led_on_generic"); - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - break; - case e1000_media_type_copper: - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); - break; - default: - break; - } - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_led_off_generic - Turn LED off - * @hw: pointer to the HW structure - * - * Turn LED off. - **/ -s32 e1000_led_off_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl; - - DEBUGFUNC("e1000_led_off_generic"); - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - break; - case e1000_media_type_copper: - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); - break; - default: - break; - } - - return E1000_SUCCESS; -#endif - return 0; -} - -/** - * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities - * @hw: pointer to the HW structure - * @no_snoop: bitmap of snoop events - * - * Set the PCI-express register to snoop for events enabled in 'no_snoop'. - **/ -void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) -{ - u32 gcr; - - DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - if (no_snoop) { - gcr = E1000_READ_REG(hw, E1000_GCR); - gcr &= ~(PCIE_NO_SNOOP_ALL); - gcr |= no_snoop; - E1000_WRITE_REG(hw, E1000_GCR, gcr); - } -out: - return; -} - -/** - * e1000_disable_pcie_master_generic - Disables PCI-express master access - * @hw: pointer to the HW structure - * - * Returns 0 (E1000_SUCCESS) if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused - * the master requests to be disabled. - * - * Disables PCI-Express master access and verifies there are no pending - * requests. - **/ -s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 timeout = MASTER_DISABLE_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_disable_pcie_master_generic"); - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - while (timeout) { - if (!(E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE)) - break; - usec_delay(100); - timeout--; - } - - if (!timeout) { - DEBUGOUT("Master requests are pending.\n"); - ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void e1000_reset_adaptive_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("e1000_reset_adaptive_generic"); - - if (!mac->adaptive_ifs) { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; - } - - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - E1000_WRITE_REG(hw, E1000_AIT, 0); -out: - return; -} - -/** - * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void e1000_update_adaptive_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("e1000_update_adaptive_generic"); - - if (!mac->adaptive_ifs) { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - E1000_WRITE_REG(hw, E1000_AIT, 0); - } - } -out: - return; -} - -/** - * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings - * @hw: pointer to the HW structure - * - * Verify that when not using auto-negotiation that MDI/MDIx is correctly - * set, which is forced to MDI mode only. - **/ -static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_validate_mdi_setting_generic"); - - if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { - DEBUGOUT("Invalid MDI setting detected\n"); - hw->phy.mdix = 1; - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: - return ret_val; -} diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_mac.h b/roms/ipxe/src/drivers/net/e1000/e1000_mac.h deleted file mode 100644 index 51acae088..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_mac.h +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_MAC_H_ -#define _E1000_MAC_H_ - -/* - * Functions that should not be called directly from drivers but can be used - * by other files in this 'shared code' - */ -void e1000_init_mac_ops_generic(struct e1000_hw *hw); -void e1000_null_mac_generic(struct e1000_hw *hw); -s32 e1000_null_ops_generic(struct e1000_hw *hw); -s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); -bool e1000_null_mng_mode(struct e1000_hw *hw); -void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a); -void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b); -void e1000_null_mta_set(struct e1000_hw *hw, u32 a); -void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a); -s32 e1000_blink_led_generic(struct e1000_hw *hw); -s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); -s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); -s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); -s32 e1000_cleanup_led_generic(struct e1000_hw *hw); -s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); -s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); -s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); -s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); -s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); -s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); -s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw); -s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); -void e1000_set_lan_id_single_port(struct e1000_hw *hw); -void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw); -s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); -s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -s32 e1000_id_led_init_generic(struct e1000_hw *hw); -s32 e1000_led_on_generic(struct e1000_hw *hw); -s32 e1000_led_off_generic(struct e1000_hw *hw); -void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 e1000_set_default_fc_generic(struct e1000_hw *hw); -s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); -s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); -s32 e1000_setup_led_generic(struct e1000_hw *hw); -s32 e1000_setup_link_generic(struct e1000_hw *hw); - -u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); - -void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw); -void e1000_clear_vfta_generic(struct e1000_hw *hw); -void e1000_config_collision_dist_generic(struct e1000_hw *hw); -void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); -void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value); -void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); -void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); -void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); -void e1000_reset_adaptive_generic(struct e1000_hw *hw); -void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); -void e1000_update_adaptive_generic(struct e1000_hw *hw); -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_main.c b/roms/ipxe/src/drivers/net/e1000/e1000_main.c deleted file mode 100644 index 653323b51..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_main.c +++ /dev/null @@ -1,909 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2008 Intel Corporation. - - Portions Copyright(c) 2010 Marty Connor - Portions Copyright(c) 2010 Entity Cyber, Inc. - - 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "e1000.h" - -/** - * e1000_irq_disable - Disable interrupt generation - * - * @adapter: board private structure - **/ -static void e1000_irq_disable ( struct e1000_adapter *adapter ) -{ - E1000_WRITE_REG ( &adapter->hw, E1000_IMC, ~0 ); - E1000_WRITE_FLUSH ( &adapter->hw ); -} - -/** - * e1000_irq_enable - Enable interrupt generation - * - * @adapter: board private structure - **/ -static void e1000_irq_enable ( struct e1000_adapter *adapter ) -{ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(&adapter->hw); -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_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 e1000_sw_init(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct pci_device *pdev = adapter->pdev; - - /* PCI config space info */ - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &hw->subsystem_vendor_id); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_device_id); - - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); - - pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); - - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE + - ETH_HLEN + ETH_FCS_LEN; - adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - - hw->fc.requested_mode = e1000_fc_none; - - /* Initialize the hardware-specific values */ - if (e1000_setup_init_funcs(hw, false)) { - DBG ("Hardware Initialization Failure\n"); - return -EIO; - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000_irq_disable ( adapter ); - - return 0; -} - -int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct e1000_adapter *adapter = hw->back; - uint16_t cap_offset; - -#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_read_config_word(adapter->pdev, cap_offset + reg, value); - - return 0; -} - -void e1000_pci_clear_mwi ( struct e1000_hw *hw ) -{ - struct e1000_adapter *adapter = hw->back; - - pci_write_config_word ( adapter->pdev, PCI_COMMAND, - hw->bus.pci_cmd_word & ~PCI_COMMAND_INVALIDATE ); -} - -void e1000_pci_set_mwi ( struct e1000_hw *hw ) -{ - struct e1000_adapter *adapter = hw->back; - - pci_write_config_word ( adapter->pdev, PCI_COMMAND, - hw->bus.pci_cmd_word ); -} - -void e1000_read_pci_cfg ( struct e1000_hw *hw, uint32_t reg, uint16_t *value ) -{ - struct e1000_adapter *adapter = hw->back; - - pci_read_config_word ( adapter->pdev, reg, value ); -} - -void e1000_write_pci_cfg ( struct e1000_hw *hw, uint32_t reg, uint16_t *value ) -{ - struct e1000_adapter *adapter = hw->back; - - pci_write_config_word ( adapter->pdev, reg, *value ); -} - -/** - * e1000_init_manageability - disable interception of ARP packets - * - * @v adapter e1000 private structure - **/ -static void e1000_init_manageability ( struct e1000_adapter *adapter ) -{ - if (adapter->en_mng_pt) { - u32 manc = E1000_READ_REG(&adapter->hw, E1000_MANC); - - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - - E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc); - } -} - -/** - * e1000_setup_tx_resources - allocate Tx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000_setup_tx_resources ( struct e1000_adapter *adapter ) -{ - DBG ( "e1000_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; -} - -/** - * e1000_process_tx_packets - process transmitted packets - * - * @v netdev network interface device structure - **/ -static void e1000_process_tx_packets ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t tx_status; - struct e1000_tx_desc *tx_curr_desc; - - /* Check status of transmitted packets - */ - 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->upper.data; - - /* 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 ); - - if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | - E1000_TXD_STAT_TU ) ) { - netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL ); - DBG ( "Error transmitting packet, tx_status: %#08x\n", - tx_status ); - } else { - 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; - } -} - -static void e1000_free_tx_resources ( struct e1000_adapter *adapter ) -{ - DBG ( "e1000_free_tx_resources\n" ); - - free_dma ( adapter->tx_base, adapter->tx_ring_size ); -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000_configure_tx ( struct e1000_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - uint32_t tctl; - - DBG ( "e1000_configure_tx\n" ); - - E1000_WRITE_REG ( hw, E1000_TDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDBAL(0), virt_to_bus ( adapter->tx_base ) ); - E1000_WRITE_REG ( hw, E1000_TDLEN(0), adapter->tx_ring_size ); - - DBG ( "E1000_TDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_TDBAL(0) ) ); - DBG ( "E1000_TDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_TDLEN(0) ) ); - - /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG ( hw, E1000_TDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDT(0), 0 ); - - adapter->tx_head = 0; - adapter->tx_tail = 0; - adapter->tx_fill_ctr = 0; - - /* Setup Transmit Descriptor Settings for eop descriptor */ - tctl = E1000_TCTL_PSP | E1000_TCTL_EN | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) | - (E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - e1000_config_collision_dist ( hw ); - - E1000_WRITE_REG ( hw, E1000_TCTL, tctl ); - E1000_WRITE_FLUSH ( hw ); -} - -static void e1000_free_rx_resources ( struct e1000_adapter *adapter ) -{ - int i; - - DBG ( "e1000_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] ); - } -} - -/** - * e1000_refill_rx_ring - allocate Rx io_buffers - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000_refill_rx_ring ( struct e1000_adapter *adapter ) -{ - int i, rx_curr; - int rc = 0; - struct e1000_rx_desc *rx_curr_desc; - struct e1000_hw *hw = &adapter->hw; - struct io_buffer *iob; - - DBG ("e1000_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->status & 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; - - if ( ! iob ) { - DBG ( "alloc_iob failed\n" ); - rc = -ENOMEM; - break; - } else { - rx_curr_desc->buffer_addr = virt_to_bus ( iob->data ); - - E1000_WRITE_REG ( hw, E1000_RDT(0), rx_curr ); - } - } - return rc; -} - -/** - * e1000_setup_rx_resources - allocate Rx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000_setup_rx_resources ( struct e1000_adapter *adapter ) -{ - int i, rc = 0; - - DBG ( "e1000_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++ ) { - /* let e1000_refill_rx_ring() io_buffer allocations */ - adapter->rx_iobuf[i] = NULL; - } - - /* allocate io_buffers */ - rc = e1000_refill_rx_ring ( adapter ); - if ( rc < 0 ) - e1000_free_rx_resources ( adapter ); - - return rc; -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000_configure_rx ( struct e1000_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; - - DBG ( "e1000_configure_rx\n" ); - - /* disable receives while setting up the descriptors */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - E1000_WRITE_FLUSH ( hw ); - mdelay(10); - - adapter->rx_curr = 0; - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring */ - - E1000_WRITE_REG ( hw, E1000_RDBAL(0), virt_to_bus ( adapter->rx_base ) ); - E1000_WRITE_REG ( hw, E1000_RDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDLEN(0), adapter->rx_ring_size ); - - E1000_WRITE_REG ( hw, E1000_RDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDT(0), NUM_RX_DESC - 1 ); - - /* Enable Receives */ - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_MPE | E1000_RCTL_SECRC; - E1000_WRITE_REG ( hw, E1000_RCTL, rctl ); - E1000_WRITE_FLUSH ( hw ); - - DBG ( "E1000_RDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_RDBAL(0) ) ); - DBG ( "E1000_RDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_RDLEN(0) ) ); - DBG ( "E1000_RCTL: %#08x\n", E1000_READ_REG ( hw, E1000_RCTL ) ); -} - -/** - * e1000_process_rx_packets - process received packets - * - * @v netdev network interface device structure - **/ -static void e1000_process_rx_packets ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t rx_status; - uint32_t rx_len; - uint32_t rx_err; - struct e1000_rx_desc *rx_curr_desc; - - /* 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->status; - - DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status ); - - if ( ! ( rx_status & E1000_RXD_STAT_DD ) ) - break; - - if ( adapter->rx_iobuf[i] == NULL ) - break; - - DBG ( "E1000_RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RCTL ) ); - - rx_len = rx_curr_desc->length; - - DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n", - i, rx_status, rx_len ); - - rx_err = rx_curr_desc->errors; - - iob_put ( adapter->rx_iobuf[i], rx_len ); - - if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) { - - netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL ); - DBG ( "e1000_poll: 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; - } -} - -/** - * e1000_reset - Put e1000 NIC in known initial state - * - * @v adapter e1000 private structure - **/ -void e1000_reset ( struct e1000_adapter *adapter ) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - u32 pba = 0; - - DBG ( "e1000_reset\n" ); - - switch (mac->type) { - case e1000_82542: - case e1000_82543: - case e1000_82544: - case e1000_82540: - case e1000_82541: - case e1000_82541_rev_2: - pba = E1000_PBA_48K; - break; - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - pba = E1000_PBA_48K; - break; - case e1000_82547: - case e1000_82547_rev_2: - pba = E1000_PBA_30K; - break; - case e1000_undefined: - case e1000_num_macs: - break; - } - - E1000_WRITE_REG ( &adapter->hw, E1000_PBA, pba ); - - /* Allow time for pending master requests to run */ - e1000_reset_hw ( &adapter->hw ); - - if ( mac->type >= e1000_82544 ) - E1000_WRITE_REG ( &adapter->hw, E1000_WUC, 0 ); - - if ( e1000_init_hw ( &adapter->hw ) ) - DBG ( "Hardware Error\n" ); - - e1000_reset_adaptive ( &adapter->hw ); - e1000_get_phy_info ( &adapter->hw ); - - e1000_init_manageability ( adapter ); -} - -/** Functions that implement the iPXE driver API **/ - -/** - * e1000_close - Disables a network interface - * - * @v netdev network interface device structure - * - **/ -static void e1000_close ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; - - DBG ( "e1000_close\n" ); - - /* Disable and acknowledge interrupts */ - e1000_irq_disable ( adapter ); - E1000_READ_REG ( hw, E1000_ICR ); - - /* disable receives */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - E1000_WRITE_FLUSH ( hw ); - - e1000_reset_hw ( hw ); - - e1000_free_tx_resources ( adapter ); - e1000_free_rx_resources ( adapter ); -} - -/** - * e1000_transmit - Transmit a packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * - * @ret rc Returns 0 on success, negative on failure - */ -static int e1000_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) -{ - struct e1000_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t tx_curr = adapter->tx_tail; - struct e1000_tx_desc *tx_curr_desc; - - DBG ("e1000_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->buffer_addr = - virt_to_bus ( iobuf->data ); - tx_curr_desc->lower.data = - E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | iob_len ( iobuf ); - tx_curr_desc->upper.data = 0; - - 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 - */ - wmb(); - E1000_WRITE_REG ( hw, E1000_TDT(0), adapter->tx_tail ); - - return 0; -} - -/** - * e1000_poll - Poll for received packets - * - * @v netdev Network device - */ -static void e1000_poll ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - - uint32_t icr; - - DBGP ( "e1000_poll\n" ); - - /* Acknowledge interrupts */ - icr = E1000_READ_REG ( hw, E1000_ICR ); - if ( ! icr ) - return; - - DBG ( "e1000_poll: intr_status = %#08x\n", icr ); - - e1000_process_tx_packets ( netdev ); - - e1000_process_rx_packets ( netdev ); - - e1000_refill_rx_ring(adapter); -} - -/** - * e1000_irq - enable or Disable interrupts - * - * @v adapter e1000 adapter - * @v action requested interrupt action - **/ -static void e1000_irq ( struct net_device *netdev, int enable ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - - DBG ( "e1000_irq\n" ); - - if ( enable ) { - e1000_irq_enable ( adapter ); - } else { - e1000_irq_disable ( adapter ); - } -} - -static struct net_device_operations e1000_operations; - -/** - * e1000_probe - Initial configuration of e1000 NIC - * - * @v pci PCI device - * @v id PCI IDs - * - * @ret rc Return status code - **/ -int e1000_probe ( struct pci_device *pdev ) -{ - int i, err; - struct net_device *netdev; - struct e1000_adapter *adapter; - unsigned long mmio_start, mmio_len; - - DBG ( "e1000_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 e1000_adapter ) ); - if ( ! netdev ) - goto err_alloc_etherdev; - - /* Associate e1000-specific network operations operations with - * generic network device layer */ - netdev_init ( netdev, &e1000_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; - - adapter->irqno = pdev->irq; - adapter->netdev = netdev; - adapter->hw.back = adapter; - - adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC; - adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC; - - 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 ); - - /* Fix up PCI device */ - adjust_pci_device ( pdev ); - - err = -EIO; - - 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 ) - goto err_ioremap; - - /* Hardware features, flags and workarounds */ - if (adapter->hw.mac.type >= e1000_82540) { - adapter->flags |= E1000_FLAG_HAS_SMBUS; - adapter->flags |= E1000_FLAG_HAS_INTR_MODERATION; - } - - if (adapter->hw.mac.type == e1000_82543) - adapter->flags |= E1000_FLAG_BAD_TX_CARRIER_STATS_FD; - - adapter->hw.phy.autoneg_wait_to_complete = true; - adapter->hw.mac.adaptive_ifs = true; - - /* setup the private structure */ - if ( ( err = e1000_sw_init ( adapter ) ) ) - goto err_sw_init; - - if ((err = e1000_init_mac_params(&adapter->hw))) - goto err_hw_init; - - if ((err = e1000_init_nvm_params(&adapter->hw))) - goto err_hw_init; - - /* Force auto-negotiated speed and duplex */ - adapter->hw.mac.autoneg = 1; - - if ((err = e1000_init_phy_params(&adapter->hw))) - goto err_hw_init; - - DBG ( "adapter->hw.mac.type: %#08x\n", adapter->hw.mac.type ); - - /* before reading the EEPROM, reset the controller to - * put the device in a known good starting state - */ - err = e1000_reset_hw ( &adapter->hw ); - if ( err < 0 ) { - DBG ( "Hardware Initialization Failed\n" ); - goto err_reset; - } - /* make sure the NVM is good */ - - if ( e1000_validate_nvm_checksum(&adapter->hw) < 0 ) { - DBG ( "The NVM Checksum Is Not Valid\n" ); - err = -EIO; - goto err_eeprom; - } - - /* copy the MAC address out of the EEPROM */ - if ( e1000_read_mac_addr ( &adapter->hw ) ) - DBG ( "EEPROM Read Error\n" ); - - memcpy ( netdev->hw_addr, adapter->hw.mac.perm_addr, ETH_ALEN ); - - /* reset the hardware with the new settings */ - e1000_reset ( adapter ); - - if ( ( err = register_netdev ( netdev ) ) != 0) - goto err_register; - - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); - - for (i = 0; i < 6; i++) - DBG ("%02x%s", netdev->ll_addr[i], i == 5 ? "\n" : ":"); - - DBG ( "e1000_probe succeeded!\n" ); - - /* No errors, return success */ - return 0; - -/* Error return paths */ -err_reset: -err_register: -err_hw_init: -err_eeprom: - if (!e1000_check_reset_block(&adapter->hw)) - e1000_phy_hw_reset(&adapter->hw); - if (adapter->hw.flash_address) - iounmap(adapter->hw.flash_address); -err_sw_init: - iounmap ( adapter->hw.hw_addr ); -err_ioremap: - netdev_put ( netdev ); -err_alloc_etherdev: - return err; -} - -/** - * e1000_remove - Device Removal Routine - * - * @v pdev PCI device information struct - * - **/ -void e1000_remove ( struct pci_device *pdev ) -{ - struct net_device *netdev = pci_get_drvdata ( pdev ); - struct e1000_adapter *adapter = netdev_priv ( netdev ); - - DBG ( "e1000_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 ); - e1000_reset_hw ( &adapter->hw ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** - * e1000_open - Called when a network interface is made active - * - * @v netdev network interface device structure - * @ret rc Return status code, 0 on success, negative value on failure - * - **/ -static int e1000_open ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int err; - - DBG ( "e1000_open\n" ); - - /* allocate transmit descriptors */ - err = e1000_setup_tx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up TX resources!\n" ); - goto err_setup_tx; - } - - /* allocate receive descriptors */ - err = e1000_setup_rx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up RX resources!\n" ); - goto err_setup_rx; - } - - e1000_configure_tx ( adapter ); - - e1000_configure_rx ( adapter ); - - DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) ); - - return 0; - -err_setup_rx: - e1000_free_tx_resources ( adapter ); -err_setup_tx: - e1000_reset ( adapter ); - - return err; -} - -/** e1000 net device operations */ -static struct net_device_operations e1000_operations = { - .open = e1000_open, - .close = e1000_close, - .transmit = e1000_transmit, - .poll = e1000_poll, - .irq = e1000_irq, -}; diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_manage.c b/roms/ipxe/src/drivers/net/e1000/e1000_manage.c deleted file mode 100644 index 3362942e1..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_manage.c +++ /dev/null @@ -1,389 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#if 0 - -#include "e1000_api.h" - -static u8 e1000_calculate_checksum(u8 *buffer, u32 length); - -/** - * e1000_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - DEBUGFUNC("e1000_calculate_checksum"); - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8) (0 - sum); -} - -/** - * e1000_mng_enable_host_if_generic - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) -{ - u32 hicr; - s32 ret_val = E1000_SUCCESS; - u8 i; - - DEBUGFUNC("e1000_mng_enable_host_if_generic"); - - /* Check that the host interface is enabled. */ - hicr = E1000_READ_REG(hw, E1000_HICR); - if ((hicr & E1000_HICR_EN) == 0) { - DEBUGOUT("E1000_HOST_EN bit disabled.\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = E1000_READ_REG(hw, E1000_HICR); - if (!(hicr & E1000_HICR_C)) - break; - msec_delay_irq(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - DEBUGOUT("Previous command timeout failed .\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_check_mng_mode_generic - Generic check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm; - - DEBUGFUNC("e1000_check_mng_mode_generic"); - - fwsm = E1000_READ_REG(hw, E1000_FWSM); - - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - bool tx_filter = true; - - DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); - - /* No manageability, no filtering */ - if (!hw->mac.ops.check_mng_mode(hw)) { - tx_filter = false; - goto out; - } - - /* - * If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val != E1000_SUCCESS) { - tx_filter = false; - goto out; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) { - *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, - E1000_HOST_IF, - offset + i); - } - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if (hdr_csum != csum) - goto out; - if (hdr->signature != E1000_IAMT_SIGNATURE) - goto out; - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - tx_filter = false; - -out: - hw->mac.tx_pkt_filtering = tx_filter; - return tx_filter; -} - -/** - * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, - u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val) - goto out; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - goto out; - - /* Write the manageability command header */ - ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); - if (ret_val) - goto out; - - /* Tell the ARC a new command is pending. */ - hicr = E1000_READ_REG(hw, E1000_HICR); - E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); - -out: - return ret_val; -} - -/** - * e1000_mng_write_cmd_header_generic - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - DEBUGFUNC("e1000_mng_write_cmd_header_generic"); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, - *((u32 *) hdr + i)); - E1000_WRITE_FLUSH(hw); - } - - return E1000_SUCCESS; -} - -/** - * e1000_mng_host_if_write_generic - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - s32 ret_val = E1000_SUCCESS; - u16 remaining, i, j, prev_bytes; - - DEBUGFUNC("e1000_mng_host_if_write_generic"); - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { - ret_val = -E1000_ERR_PARAM; - goto out; - } - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* - * The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, - data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); - } - -out: - return ret_val; -} - -/** - * e1000_enable_mng_pass_thru - Enable processing of ARP's - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to allow ARPs to be processed by the host. - **/ -bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - bool ret_val = false; - - DEBUGFUNC("e1000_enable_mng_pass_thru"); - - if (!hw->mac.asf_firmware_present) - goto out; - - manc = E1000_READ_REG(hw, E1000_MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - goto out; - - if (hw->mac.arc_subsystem_valid) { - fwsm = E1000_READ_REG(hw, E1000_FWSM); - factps = E1000_READ_REG(hw, E1000_FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { - ret_val = true; - goto out; - } - } else { - if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - ret_val = true; - goto out; - } - } - -out: - return ret_val; -} - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_manage.h b/roms/ipxe/src/drivers/net/e1000/e1000_manage.h deleted file mode 100644 index 14467aa6c..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_manage.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_MANAGE_H_ -#define _E1000_MANAGE_H_ - -bool e1000_check_mng_mode_generic(struct e1000_hw *hw); -bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); -s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); -s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum); -s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr); -s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, - u8 *buffer, u16 length); -bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); - -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -#define E1000_FWSM_MODE_MASK 0xE -#define E1000_FWSM_MODE_SHIFT 1 - -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 - -#define E1000_VFTA_ENTRY_SHIFT 5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ -#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ -#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ - -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 -#define E1000_HICR_SV 0x04 /* Status Validity */ -#define E1000_HICR_FW_RESET_ENABLE 0x40 -#define E1000_HICR_FW_RESET 0x80 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_nvm.c b/roms/ipxe/src/drivers/net/e1000/e1000_nvm.c deleted file mode 100644 index 488252f42..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_nvm.c +++ /dev/null @@ -1,923 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000_api.h" - -static void e1000_reload_nvm_generic(struct e1000_hw *hw); - -/** - * e1000_init_nvm_ops_generic - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void e1000_init_nvm_ops_generic(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - DEBUGFUNC("e1000_init_nvm_ops_generic"); - - /* Initialize function pointers */ - nvm->ops.init_params = e1000_null_ops_generic; - nvm->ops.acquire = e1000_null_ops_generic; - nvm->ops.read = e1000_null_read_nvm; - nvm->ops.release = e1000_null_nvm_generic; - nvm->ops.reload = e1000_reload_nvm_generic; - nvm->ops.update = e1000_null_ops_generic; - nvm->ops.valid_led_default = e1000_null_led_default; - nvm->ops.validate = e1000_null_ops_generic; - nvm->ops.write = e1000_null_write_nvm; -} - -/** - * e1000_null_nvm_read - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_read_nvm(struct e1000_hw *hw __unused, u16 a __unused, - u16 b __unused, u16 *c __unused) -{ - DEBUGFUNC("e1000_null_read_nvm"); - return E1000_SUCCESS; -} - -/** - * e1000_null_nvm_generic - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_nvm_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_null_nvm_generic"); - return; -} - -/** - * e1000_null_led_default - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_led_default(struct e1000_hw *hw __unused, - u16 *data __unused) -{ - DEBUGFUNC("e1000_null_led_default"); - return E1000_SUCCESS; -} - -/** - * e1000_null_write_nvm - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_write_nvm(struct e1000_hw *hw __unused, u16 a __unused, - u16 b __unused, u16 *c __unused) -{ - DEBUGFUNC("e1000_null_write_nvm"); - return E1000_SUCCESS; -} - -/** - * e1000_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - E1000_WRITE_REG(hw, E1000_EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->nvm.delay_usec); -} - -/** - * e1000_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - E1000_WRITE_REG(hw, E1000_EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->nvm.delay_usec); -} - -/** - * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - u32 mask; - - DEBUGFUNC("e1000_shift_out_eec_bits"); - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_microwire) - eecd &= ~E1000_EECD_DO; - else - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - - usec_delay(nvm->delay_usec); - - e1000_raise_eec_clk(hw, &eecd); - e1000_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - E1000_WRITE_REG(hw, E1000_EECD, eecd); -} - -/** - * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - DEBUGFUNC("e1000_shift_in_eec_bits"); - - eecd = E1000_READ_REG(hw, E1000_EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - e1000_raise_eec_clk(hw, &eecd); - - eecd = E1000_READ_REG(hw, E1000_EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - s32 ret_val = -E1000_ERR_NVM; - - DEBUGFUNC("e1000_poll_eerd_eewr_done"); - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = E1000_READ_REG(hw, E1000_EERD); - else - reg = E1000_READ_REG(hw, E1000_EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) { - ret_val = E1000_SUCCESS; - break; - } - - usec_delay(5); - } - - return ret_val; -} - -/** - * e1000_acquire_nvm_generic - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) -{ - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_acquire_nvm_generic"); - - E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); - eecd = E1000_READ_REG(hw, E1000_EECD); - - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - usec_delay(5); - eecd = E1000_READ_REG(hw, E1000_EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - DEBUGOUT("Could not acquire NVM grant\n"); - ret_val = -E1000_ERR_NVM; - } - - return ret_val; -} - -/** - * e1000_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void e1000_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - - DEBUGFUNC("e1000_standby_nvm"); - - if (nvm->type == e1000_nvm_eeprom_microwire) { - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - - e1000_raise_eec_clk(hw, &eecd); - - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - - e1000_lower_eec_clk(hw, &eecd); - } else - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - } -} - -/** - * e1000_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -void e1000_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - DEBUGFUNC("e1000_stop_nvm"); - - eecd = E1000_READ_REG(hw, E1000_EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - e1000_lower_eec_clk(hw, &eecd); - } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { - /* CS on Microwire is active-high */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); - E1000_WRITE_REG(hw, E1000_EECD, eecd); - e1000_raise_eec_clk(hw, &eecd); - e1000_lower_eec_clk(hw, &eecd); - } -} - -/** - * e1000_release_nvm_generic - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void e1000_release_nvm_generic(struct e1000_hw *hw) -{ - u32 eecd; - - DEBUGFUNC("e1000_release_nvm_generic"); - - e1000_stop_nvm(hw); - - eecd = E1000_READ_REG(hw, E1000_EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, E1000_EECD, eecd); -} - -/** - * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - s32 ret_val = E1000_SUCCESS; - u16 timeout = 0; - u8 spi_stat_reg; - - DEBUGFUNC("e1000_ready_nvm_eeprom"); - - if (nvm->type == e1000_nvm_eeprom_microwire) { - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); - E1000_WRITE_REG(hw, E1000_EECD, eecd); - /* Set CS */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - } else - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, E1000_EECD, eecd); - usec_delay(1); - timeout = NVM_MAX_RETRY_SPI; - - /* - * Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - usec_delay(5); - e1000_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - DEBUGOUT("SPI NVM Status error\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000_read_nvm_spi - Read EEPROM's using SPI - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM. - **/ -s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i = 0; - s32 ret_val; - u16 word_in; - u8 read_opcode = NVM_READ_OPCODE_SPI; - - DEBUGFUNC("e1000_read_nvm_spi"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - e1000_standby_nvm(hw); - - if ((nvm->address_bits == 8) && (offset >= 128)) - read_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); - - /* - * Read the data. SPI NVMs increment the address with each byte - * read and will roll over if reading beyond the end. This allows - * us to read the whole NVM from any offset - */ - for (i = 0; i < words; i++) { - word_in = e1000_shift_in_eec_bits(hw, 16); - data[i] = (word_in >> 8) | (word_in << 8); - } - -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_read_nvm_microwire - Reads EEPROM's using microwire - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM. - **/ -s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i = 0; - s32 ret_val; - u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; - - DEBUGFUNC("e1000_read_nvm_microwire"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - for (i = 0; i < words; i++) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)(offset + i), - nvm->address_bits); - - /* - * Read the data. For microwire, each word requires the - * overhead of setup and tear-down. - */ - data[i] = e1000_shift_in_eec_bits(hw, 16); - e1000_standby_nvm(hw); - } - -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_nvm_eerd"); - - /* - * A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - for (i = 0; i < words; i++) { - eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - E1000_WRITE_REG(hw, E1000_EERD, eerd); - ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) - break; - - data[i] = (E1000_READ_REG(hw, E1000_EERD) >> - E1000_NVM_RW_REG_DATA); - } - -out: - return ret_val; -} - -/** - * e1000_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 widx = 0; - - DEBUGFUNC("e1000_write_nvm_spi"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - e1000_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - e1000_standby_nvm(hw); - - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - e1000_standby_nvm(hw); - break; - } - } - } - - msec_delay(10); -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_write_nvm_microwire - Writes EEPROM using microwire - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using microwire interface. - * - * If e1000_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u32 eecd; - u16 words_written = 0; - u16 widx = 0; - - DEBUGFUNC("e1000_write_nvm_microwire"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, - (u16)(nvm->opcode_bits + 2)); - - e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); - - e1000_standby_nvm(hw); - - while (words_written < words) { - e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, - nvm->opcode_bits); - - e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), - nvm->address_bits); - - e1000_shift_out_eec_bits(hw, data[words_written], 16); - - e1000_standby_nvm(hw); - - for (widx = 0; widx < 200; widx++) { - eecd = E1000_READ_REG(hw, E1000_EECD); - if (eecd & E1000_EECD_DO) - break; - usec_delay(50); - } - - if (widx == 200) { - DEBUGOUT("NVM Write did not complete\n"); - ret_val = -E1000_ERR_NVM; - goto release; - } - - e1000_standby_nvm(hw); - - words_written++; - } - - e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, - (u16)(nvm->opcode_bits + 2)); - - e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); - -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_read_pba_num_generic - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) -{ - s32 ret_val; - u16 nvm_data; - - DEBUGFUNC("e1000_read_pba_num_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - *pba_num = (u32)(nvm_data << 16); - - ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - *pba_num |= nvm_data; - -out: - return ret_val; -} - -/** - * e1000_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = E1000_READ_REG(hw, E1000_RAH(0)); - rar_low = E1000_READ_REG(hw, E1000_RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); - - for (i = 0; i < ETH_ADDR_LEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return E1000_SUCCESS; -} - -/** - * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 checksum = 0; - u16 i, nvm_data; - - DEBUGFUNC("e1000_validate_nvm_checksum_generic"); - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - checksum += nvm_data; - } - - if (checksum != (u16) NVM_SUM) { - DEBUGOUT("NVM Checksum Invalid\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - DEBUGFUNC("e1000_update_nvm_checksum"); - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error while updating checksum.\n"); - goto out; - } - checksum += nvm_data; - } - checksum = (u16) NVM_SUM - checksum; - ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) - DEBUGOUT("NVM Write Error while updating checksum.\n"); - -out: - return ret_val; -} - -/** - * e1000_reload_nvm_generic - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -static void e1000_reload_nvm_generic(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - DEBUGFUNC("e1000_reload_nvm_generic"); - - usec_delay(10); - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); -} diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_nvm.h b/roms/ipxe/src/drivers/net/e1000/e1000_nvm.h deleted file mode 100644 index 1585417cf..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_nvm.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_NVM_H_ -#define _E1000_NVM_H_ - -void e1000_init_nvm_ops_generic(struct e1000_hw *hw); -s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); -void e1000_null_nvm_generic(struct e1000_hw *hw); -s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data); -s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); -s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); - -s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); -s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); -s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); -s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); -s32 e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); -void e1000_stop_nvm(struct e1000_hw *hw); -void e1000_release_nvm_generic(struct e1000_hw *hw); - -#define E1000_STM_OPCODE 0xDB00 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_osdep.h b/roms/ipxe/src/drivers/net/e1000/e1000_osdep.h deleted file mode 100644 index 5cd8e3910..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_osdep.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* glue for the OS-dependent part of e1000 - * includes register access macros - */ - -#ifndef _E1000_OSDEP_H_ -#define _E1000_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 ETH_FCS_LEN 4 - -typedef int spinlock_t; -typedef enum { - false = 0, - true = 1 -} boolean_t; - -#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 DEBUGFUNC(F) DBG(F "\n") - -#define DEBUGOUT(S) DBG(S) -#define DEBUGOUT1(S, A...) DBG(S, A) - -#define DEBUGOUT2 DEBUGOUT1 -#define DEBUGOUT3 DEBUGOUT2 -#define DEBUGOUT7 DEBUGOUT3 - -#define E1000_REGISTER(a, reg) (((a)->mac.type >= e1000_82543) \ - ? reg \ - : e1000_translate_register_82542(reg)) - -#define E1000_WRITE_REG(a, reg, value) \ - writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg))) - -#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg))) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ - writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + E1000_REGISTER(a, 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 + E1000_REGISTER(a, reg) + ((offset) << 1)))) - -#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ - readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))) - -#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ - writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))) - -#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ - readb((a)->hw_addr + E1000_REGISTER(a, 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 /* _E1000_OSDEP_H_ */ diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_phy.c b/roms/ipxe/src/drivers/net/e1000/e1000_phy.c deleted file mode 100644 index b3cad4809..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_phy.c +++ /dev/null @@ -1,2308 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000_api.h" - -#if 0 -/* Cable length tables */ -static const u16 e1000_m88_cable_length_table[] = - { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_m88_cable_length_table) / \ - sizeof(e1000_m88_cable_length_table[0])) - -static const u16 e1000_igp_2_cable_length_table[] = - { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, - 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, - 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, - 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, - 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, - 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, - 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, - 104, 109, 114, 118, 121, 124}; -#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_igp_2_cable_length_table) / \ - sizeof(e1000_igp_2_cable_length_table[0])) -#endif - -/** - * e1000_init_phy_ops_generic - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void e1000_init_phy_ops_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - DEBUGFUNC("e1000_init_phy_ops_generic"); - - /* Initialize function pointers */ - phy->ops.init_params = e1000_null_ops_generic; - phy->ops.acquire = e1000_null_ops_generic; - phy->ops.check_polarity = e1000_null_ops_generic; - phy->ops.check_reset_block = e1000_null_ops_generic; - phy->ops.commit = e1000_null_ops_generic; -#if 0 - phy->ops.force_speed_duplex = e1000_null_ops_generic; -#endif - phy->ops.get_cfg_done = e1000_null_ops_generic; -#if 0 - phy->ops.get_cable_length = e1000_null_ops_generic; -#endif - phy->ops.get_info = e1000_null_ops_generic; - phy->ops.read_reg = e1000_null_read_reg; - phy->ops.release = e1000_null_phy_generic; - phy->ops.reset = e1000_null_ops_generic; - phy->ops.set_d0_lplu_state = e1000_null_lplu_state; - phy->ops.set_d3_lplu_state = e1000_null_lplu_state; - phy->ops.write_reg = e1000_null_write_reg; - phy->ops.power_up = e1000_null_phy_generic; - phy->ops.power_down = e1000_null_phy_generic; -} - -/** - * e1000_null_read_reg - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_read_reg(struct e1000_hw *hw __unused, u32 offset __unused, - u16 *data __unused) -{ - DEBUGFUNC("e1000_null_read_reg"); - return E1000_SUCCESS; -} - -/** - * e1000_null_phy_generic - No-op function, return void - * @hw: pointer to the HW structure - **/ -void e1000_null_phy_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_null_phy_generic"); - return; -} - -/** - * e1000_null_lplu_state - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_lplu_state(struct e1000_hw *hw __unused, bool active __unused) -{ - DEBUGFUNC("e1000_null_lplu_state"); - return E1000_SUCCESS; -} - -/** - * e1000_null_write_reg - No-op function, return 0 - * @hw: pointer to the HW structure - **/ -s32 e1000_null_write_reg(struct e1000_hw *hw __unused, u32 offset __unused, - u16 data __unused) -{ - DEBUGFUNC("e1000_null_write_reg"); - return E1000_SUCCESS; -} - -/** - * e1000_check_reset_block_generic - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Read the PHY management control register and check whether a PHY reset - * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise - * return E1000_BLK_PHY_RESET (12). - **/ -s32 e1000_check_reset_block_generic(struct e1000_hw *hw) -{ - u32 manc; - - DEBUGFUNC("e1000_check_reset_block"); - - manc = E1000_READ_REG(hw, E1000_MANC); - - return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? - E1000_BLK_PHY_RESET : E1000_SUCCESS; -} - -/** - * e1000_get_phy_id - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -s32 e1000_get_phy_id(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_id; - - DEBUGFUNC("e1000_get_phy_id"); - - if (!(phy->ops.read_reg)) - goto out; - - ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); - if (ret_val) - goto out; - - phy->id = (u32)(phy_id << 16); - usec_delay(20); - ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); - if (ret_val) - goto out; - - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - -out: - return ret_val; -} - -/** - * e1000_phy_reset_dsp_generic - Reset PHY DSP - * @hw: pointer to the HW structure - * - * Reset the digital signal processor. - **/ -s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_phy_reset_dsp_generic"); - - if (!(hw->phy.ops.write_reg)) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); - -out: - return ret_val; -} - -/** - * e1000_read_phy_reg_mdic - Read MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the MDI control register in the PHY at offset and stores the - * information read to data. - **/ -s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_phy_reg_mdic"); - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - E1000_WRITE_REG(hw, E1000_MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, E1000_MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Read did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - *data = (u16) mdic; - -out: - return ret_val; -} - -/** - * e1000_write_phy_reg_mdic - Write MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write to register at offset - * - * Writes data to MDI control register in the PHY at offset. - **/ -s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_phy_reg_mdic"); - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = (((u32)data) | - (offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - E1000_WRITE_REG(hw, E1000_MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, E1000_MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Write did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_read_phy_reg_m88 - Read m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_phy_reg_m88"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_write_phy_reg_m88 - Write m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_phy_reg_m88"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_phy_reg_igp"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = e1000_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) { - hw->phy.ops.release(hw); - goto out; - } - } - - ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_phy_reg_igp"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = e1000_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) { - hw->phy.ops.release(hw); - goto out; - } - } - - ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_read_kmrn_reg_generic - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary. Then reads the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release any acquired semaphores before exiting. - **/ -s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_read_kmrn_reg_generic"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); - - usec_delay(2); - - kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_write_kmrn_reg_generic - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary. Then write the data to PHY register - * at the offset using the kumeran interface. Release any acquired semaphores - * before exiting. - **/ -s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_kmrn_reg_generic"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); - - usec_delay(2); - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock - * and downshift values are set also. - **/ -s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - DEBUGFUNC("e1000_copper_link_setup_m88"); - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* - * Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* - * Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - if (phy->revision < E1000_REVISION_4) { - /* - * Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((phy->revision == E1000_REVISION_2) && - (phy->id == M88E1111_I_PHY_ID)) { - /* 82573L PHY - set the downshift counter to 5x. */ - phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - } - ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - goto out; - } - - /* Commit the changes. */ - ret_val = phy->ops.commit(hw); - if (ret_val) { - DEBUGOUT("Error committing the PHY changes\n"); - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_copper_link_setup_igp - Setup igp PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for - * igp PHY's. - **/ -s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("e1000_copper_link_setup_igp"); - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = hw->phy.ops.reset(hw); - if (ret_val) { - DEBUGOUT("Error resetting the PHY.\n"); - goto out; - } - - /* - * Wait 100ms for MAC to configure PHY from NVM settings, to avoid - * timeout issues when LFS is enabled. - */ - msec_delay(100); - - /* - * The NVM settings will configure LPLU in D3 for - * non-IGP1 PHYs. - */ - if (phy->type == e1000_phy_igp) { - /* disable lplu d3 during driver init */ - ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); - if (ret_val) { - DEBUGOUT("Error Disabling LPLU D3\n"); - goto out; - } - } - - /* disable lplu d0 during driver init */ - if (hw->phy.ops.set_d0_lplu_state) { - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); - if (ret_val) { - DEBUGOUT("Error Disabling LPLU D0\n"); - goto out; - } - } - /* Configure mdi-mdix settings */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (phy->mdix) { - case 1: - data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); - if (ret_val) - goto out; - - /* set auto-master slave resolution settings */ - if (hw->mac.autoneg) { - /* - * when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - - /* Set auto Master/Slave resolution process */ - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - data &= ~CR_1000T_MS_ENABLE; - ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - /* load defaults for future use */ - phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? - ((data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : - e1000_ms_auto; - - switch (phy->ms_type) { - case e1000_ms_force_master: - data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - data |= CR_1000T_MS_ENABLE; - data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link - * @hw: pointer to the HW structure - * - * Performs initial bounds checking on autoneg advertisement parameter, then - * configure to advertise the full capability. Setup the PHY to autoneg - * and restart the negotiation process between the link partner. If - * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. - **/ -s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_ctrl; - - DEBUGFUNC("e1000_copper_link_autoneg"); - - /* - * Perform some bounds checking on the autoneg advertisement - * parameter. - */ - phy->autoneg_advertised &= phy->autoneg_mask; - - /* - * If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (phy->autoneg_advertised == 0) - phy->autoneg_advertised = phy->autoneg_mask; - - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if (ret_val) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - goto out; - } - DEBUGOUT("Restarting Auto-Neg\n"); - - /* - * Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - /* - * Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (phy->autoneg_wait_to_complete) { - ret_val = hw->mac.ops.wait_autoneg(hw); - if (ret_val) { - DEBUGOUT("Error while waiting for " - "autoneg to complete\n"); - goto out; - } - } - - hw->mac.get_link_status = true; - -out: - return ret_val; -} - -/** - * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation - * @hw: pointer to the HW structure - * - * Reads the MII auto-neg advertisement register and/or the 1000T control - * register and if the PHY is already setup for auto-negotiation, then - * return successful. Otherwise, setup advertisement and flow control to - * the appropriate values for the wanted auto-negotiation. - **/ -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg = 0; - - DEBUGFUNC("e1000_phy_setup_autoneg"); - - phy->autoneg_advertised &= phy->autoneg_mask; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if (ret_val) - goto out; - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, - &mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - - /* - * Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* - * 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 &= ~(NWAY_AR_100TX_FD_CAPS | - NWAY_AR_100TX_HD_CAPS | - NWAY_AR_10T_FD_CAPS | - NWAY_AR_10T_HD_CAPS); - mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); - - DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_HALF) { - DEBUGOUT("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_FULL) { - DEBUGOUT("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_HALF) { - DEBUGOUT("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_FULL) { - DEBUGOUT("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) - DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { - DEBUGOUT("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* - * Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- - * negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* - * Flow control (Rx & Tx) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled, and Tx Flow control is - * disabled, by a software over-ride. - * - * Since there really isn't a way to advertise that we are - * capable of Rx Pause ONLY, we will advertise that we - * support both symmetric and asymmetric Rx PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if (ret_val) - goto out; - - DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = phy->ops.write_reg(hw, - PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_setup_copper_link_generic - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) -{ - s32 ret_val; - bool link; - - DEBUGFUNC("e1000_setup_copper_link_generic"); - - if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - goto out; - } else { -#if 0 - /* - * PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - goto out; - } -#endif - } - - /* - * Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000_phy_has_link_generic(hw, - COPPER_LINK_UP_LIMIT, - 10, - &link); - if (ret_val) - goto out; - - if (link) { - DEBUGOUT("Valid link established!!!\n"); - e1000_config_collision_dist_generic(hw); - ret_val = e1000_config_fc_after_link_up_generic(hw); - } else { - DEBUGOUT("Unable to establish link!!!\n"); - } - -out: - return ret_val; -} - -#if 0 -/** - * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* - * Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - goto out; - - DEBUGOUT1("IGP PSCR: %X\n", phy_data); - - usec_delay(1); - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); - - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) - DEBUGOUT("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Resets the PHY to commit the - * changes. If time expires while waiting for link up, we reset the DSP. - * After reset, TX_CLK and CRS on Tx must be set. Return successful upon - * successful completion, else return corresponding error code. - **/ -s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); - - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* Reset the phy to commit changes. */ - ret_val = hw->phy.ops.commit(hw); - if (ret_val) - goto out; - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); - - ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - - if (!link) { - /* - * We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = phy->ops.write_reg(hw, - M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - goto out; - ret_val = e1000_phy_reset_dsp_generic(hw); - if (ret_val) - goto out; - } - - /* Try once more */ - ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - } - - ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - /* - * Resetting the phy means we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock from - * the reset value of 2.5MHz. - */ - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - /* - * In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - -out: - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex - * @hw: pointer to the HW structure - * - * Forces the speed and duplex settings of the PHY. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - DEBUGFUNC("e1000_phy_force_speed_duplex_ife"); - - if (phy->type != e1000_phy_ife) { - ret_val = e1000_phy_force_speed_duplex_igp(hw); - goto out; - } - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); - if (ret_val) - goto out; - - e1000_phy_force_speed_duplex_setup(hw, &data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); - if (ret_val) - goto out; - - /* Disable MDI-X support for 10/100 */ - ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - goto out; - - data &= ~IFE_PMC_AUTO_MDIX; - data &= ~IFE_PMC_FORCE_MDIX; - - ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); - if (ret_val) - goto out; - - DEBUGOUT1("IFE PMC: %X\n", data); - - usec_delay(1); - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); - - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) - DEBUGOUT("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex - * @hw: pointer to the HW structure - * @phy_ctrl: pointer to current value of PHY_CONTROL - * - * Forces speed and duplex on the PHY by doing the following: disable flow - * control, force speed/duplex on the MAC, disable auto speed detection, - * disable auto-negotiation, configure duplex, configure speed, configure - * the collision distance, write configuration to CTRL register. The - * caller must write to the PHY_CONTROL register for these settings to - * take affect. - **/ -void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - - DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); - - /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; - - /* Force speed/duplex on the mac */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~E1000_CTRL_SPD_SEL; - - /* Disable Auto Speed Detection */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Disable autoneg on the phy */ - *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; - - /* Forcing Full or Half Duplex? */ - if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { - ctrl &= ~E1000_CTRL_FD; - *phy_ctrl &= ~MII_CR_FULL_DUPLEX; - DEBUGOUT("Half Duplex\n"); - } else { - ctrl |= E1000_CTRL_FD; - *phy_ctrl |= MII_CR_FULL_DUPLEX; - DEBUGOUT("Full Duplex\n"); - } - - /* Forcing 10mb or 100mb? */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { - ctrl |= E1000_CTRL_SPD_100; - *phy_ctrl |= MII_CR_SPEED_100; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - DEBUGOUT("Forcing 100mb\n"); - } else { - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl |= MII_CR_SPEED_10; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - DEBUGOUT("Forcing 10mb\n"); - } - - e1000_config_collision_dist_generic(hw); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -} -#endif - -/** - * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 data; - - DEBUGFUNC("e1000_set_d3_lplu_state_generic"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - goto out; - - if (!active) { - data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - } - -out: - return ret_val; -} - -/** - * e1000_check_downshift_generic - Checks whether a downshift in speed occurred - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns 1 - * - * A downshift is detected by querying the PHY link health. - **/ -s32 e1000_check_downshift_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - DEBUGFUNC("e1000_check_downshift_generic"); - - switch (phy->type) { - case e1000_phy_m88: - case e1000_phy_gg82563: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; - break; - case e1000_phy_igp_2: - case e1000_phy_igp: - case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; - break; - default: - /* speed downshift not supported */ - phy->speed_downgraded = false; - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = phy->ops.read_reg(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = (phy_data & mask) ? true : false; - -out: - return ret_val; -} - -/** - * e1000_check_polarity_m88 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000_check_polarity_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("e1000_check_polarity_m88"); - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); - - if (!ret_val) - phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * e1000_check_polarity_igp - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY port status register, and the - * current speed (since there is no polarity at 100Mbps). - **/ -s32 e1000_check_polarity_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data, offset, mask; - - DEBUGFUNC("e1000_check_polarity_igp"); - - /* - * Polarity is determined based on the speed of - * our connection. - */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; - } else { - /* - * This really only applies to 10Mbps since - * there is no polarity for 100Mbps (always 0). - */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; - } - - ret_val = phy->ops.read_reg(hw, offset, &data); - - if (!ret_val) - phy->cable_polarity = (data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - -out: - return ret_val; -} - -/** - * e1000_check_polarity_ife - Check cable polarity for IFE PHY - * @hw: pointer to the HW structure - * - * Polarity is determined on the polarity reversal feature being enabled. - **/ -s32 e1000_check_polarity_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - DEBUGFUNC("e1000_check_polarity_ife"); - - /* - * Polarity is determined based on the reversal feature being enabled. - */ - if (phy->polarity_correction) { - offset = IFE_PHY_EXTENDED_STATUS_CONTROL; - mask = IFE_PESC_POLARITY_REVERSED; - } else { - offset = IFE_PHY_SPECIAL_CONTROL; - mask = IFE_PSC_FORCE_POLARITY; - } - - ret_val = phy->ops.read_reg(hw, offset, &phy_data); - - if (!ret_val) - phy->cable_polarity = (phy_data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * e1000_wait_autoneg_generic - Wait for auto-neg completion - * @hw: pointer to the HW structure - * - * Waits for auto-negotiation to complete or for the auto-negotiation time - * limit to expire, which ever happens first. - **/ -s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - DEBUGFUNC("e1000_wait_autoneg_generic"); - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ - for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_AUTONEG_COMPLETE) - break; - msec_delay(100); - } - - /* - * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation - * has completed. - */ - return ret_val; -} - -/** - * e1000_phy_has_link_generic - Polls PHY for link - * @hw: pointer to the HW structure - * @iterations: number of times to poll for link - * @usec_interval: delay between polling attempts - * @success: pointer to whether polling was successful or not - * - * Polls the PHY status register for link, 'iterations' number of times. - **/ -s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - DEBUGFUNC("e1000_phy_has_link_generic"); - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - for (i = 0; i < iterations; i++) { - /* - * Some PHYs require the PHY_STATUS register to be read - * twice due to the link bit being sticky. No harm doing - * it across the board. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) { - /* - * If the first read fails, another entity may have - * ownership of the resources, wait and try again to - * see if they have relinquished the resources yet. - */ - usec_delay(usec_interval); - } - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_LINK_STATUS) - break; - if (usec_interval >= 1000) - msec_delay_irq(usec_interval/1000); - else - usec_delay(usec_interval); - } - - *success = (i < iterations) ? true : false; - - return ret_val; -} - -#if 0 -/** - * e1000_get_cable_length_m88 - Determine cable length for m88 PHY - * @hw: pointer to the HW structure - * - * Reads the PHY specific status register to retrieve the cable length - * information. The cable length is determined by averaging the minimum and - * maximum values to get the "average" cable length. The m88 PHY has four - * possible cable length values, which are: - * Register Value Cable Length - * 0 < 50 meters - * 1 50 - 80 meters - * 2 80 - 110 meters - * 3 110 - 140 meters - * 4 > 140 meters - **/ -s32 e1000_get_cable_length_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - DEBUGFUNC("e1000_get_cable_length_m88"); - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT; - if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE + 1) { - ret_val = E1000_ERR_PHY; - goto out; - } - - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index+1]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} - -/** - * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_data, i, agc_value = 0; - u16 cur_agc_index, max_agc_index = 0; - u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = - {IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D}; - - DEBUGFUNC("e1000_get_cable_length_igp_2"); - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); - if (ret_val) - goto out; - - /* - * Getting bits 15:9, which represent the combination of - * coarse and fine gain values. The result is a number - * that can be put into the lookup table to obtain the - * approximate cable length. - */ - cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK; - - /* Array index bound check. */ - if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || - (cur_agc_index == 0)) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - /* Remove min & max AGC values from calculation. */ - if (e1000_igp_2_cable_length_table[min_agc_index] > - e1000_igp_2_cable_length_table[cur_agc_index]) - min_agc_index = cur_agc_index; - if (e1000_igp_2_cable_length_table[max_agc_index] < - e1000_igp_2_cable_length_table[cur_agc_index]) - max_agc_index = cur_agc_index; - - agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; - } - - agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + - e1000_igp_2_cable_length_table[max_agc_index]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* Calculate cable length with the error range of +/- 10 meters. */ - phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0; - phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} -#endif - -/** - * e1000_get_phy_info_m88 - Retrieve PHY information - * @hw: pointer to the HW structure - * - * Valid for only copper links. Read the PHY status register (sticky read) - * to verify that link is up. Read the PHY special control register to - * determine the polarity and 10base-T extended distance. Read the PHY - * special status register to determine MDI/MDIx and current speed. If - * speed is 1000, then determine cable length, local and remote receiver. - **/ -s32 e1000_get_phy_info_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("e1000_get_phy_info_m88"); - - if (hw->phy.media_type != e1000_media_type_copper) { - DEBUGOUT("Phy info is only valid for copper media\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? true : false; - - ret_val = e1000_check_polarity_m88(hw); - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { -#if 0 - ret_val = hw->phy.ops.get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - } else { - /* Set values to "undefined" */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - -out: - return ret_val; -} - -/** - * e1000_get_phy_info_igp - Retrieve igp PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000_get_phy_info_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - DEBUGFUNC("e1000_get_phy_info_igp"); - - ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - phy->polarity_correction = true; - - ret_val = e1000_check_polarity_igp(hw); - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; - -#if 0 - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); - if (ret_val) - goto out; - - phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - } else { -#endif - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; -#if 0 - } -#endif - -out: - return ret_val; -} - -/** - * e1000_phy_sw_reset_generic - PHY software reset - * @hw: pointer to the HW structure - * - * Does a software reset of the PHY by reading the PHY control register and - * setting/write the control register reset bit to the PHY. - **/ -s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 phy_ctrl; - - DEBUGFUNC("e1000_phy_sw_reset_generic"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= MII_CR_RESET; - ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - usec_delay(1); - -out: - return ret_val; -} - -/** - * e1000_phy_hw_reset_generic - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u32 ctrl; - - DEBUGFUNC("e1000_phy_hw_reset_generic"); - - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(hw); - - usec_delay(phy->reset_delay_us); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - usec_delay(150); - - phy->ops.release(hw); - - ret_val = phy->ops.get_cfg_done(hw); - -out: - return ret_val; -} - -/** - * e1000_get_cfg_done_generic - Generic configuration done - * @hw: pointer to the HW structure - * - * Generic function to wait 10 milli-seconds for configuration to complete - * and return success. - **/ -s32 e1000_get_cfg_done_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("e1000_get_cfg_done_generic"); - - msec_delay_irq(10); - - return E1000_SUCCESS; -} - -/** - * e1000_phy_init_script_igp3 - Inits the IGP3 PHY - * @hw: pointer to the HW structure - * - * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. - **/ -s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) -{ - DEBUGOUT("Running IGP 3 PHY init script\n"); - - /* PHY init IGP 3 */ - /* Enable rise/fall, 10-mode work in class-A */ - hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); - /* Remove all caps from Replica path filter */ - hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); - /* Bias trimming for ADC, AFE and Driver (Default) */ - hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); - /* Increase Hybrid poly bias */ - hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Gig mode */ - hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); - /* Disable trimming (TTT) */ - hw->phy.ops.write_reg(hw, 0x2011, 0x0000); - /* Poly DC correction to 94.6% + 2% for all channels */ - hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); - /* ABS DC correction to 95.9% */ - hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); - /* BG temp curve trim */ - hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); - /* Increasing ADC OPAMP stage 1 currents to max */ - hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); - /* Force 1000 ( required for enabling PHY regs configuration) */ - hw->phy.ops.write_reg(hw, 0x0000, 0x0140); - /* Set upd_freq to 6 */ - hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); - /* Disable NPDFE */ - hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); - /* Disable adaptive fixed FFE (Default) */ - hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); - /* Enable FFE hysteresis */ - hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); - /* Fixed FFE for short cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); - /* Fixed FFE for medium cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); - /* Fixed FFE for long cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); - /* Enable Adaptive Clip Threshold */ - hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); - /* AHT reset limit to 1 */ - hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); - /* Set AHT master delay to 127 msec */ - hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); - /* Set scan bits for AHT */ - hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); - /* Set AHT Preset bits */ - hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); - /* Change integ_factor of channel A to 3 */ - hw->phy.ops.write_reg(hw, 0x1895, 0x0003); - /* Change prop_factor of channels BCD to 8 */ - hw->phy.ops.write_reg(hw, 0x1796, 0x0008); - /* Change cg_icount + enable integbp for channels BCD */ - hw->phy.ops.write_reg(hw, 0x1798, 0xD008); - /* - * Change cg_icount + enable integbp + change prop_factor_master - * to 8 for channel A - */ - hw->phy.ops.write_reg(hw, 0x1898, 0xD918); - /* Disable AHT in Slave mode on channel A */ - hw->phy.ops.write_reg(hw, 0x187A, 0x0800); - /* - * Enable LPLU and disable AN to 1000 in non-D0a states, - * Enable SPD+B2B - */ - hw->phy.ops.write_reg(hw, 0x0019, 0x008D); - /* Enable restart AN on an1000_dis change */ - hw->phy.ops.write_reg(hw, 0x001B, 0x2080); - /* Enable wh_fifo read clock in 10/100 modes */ - hw->phy.ops.write_reg(hw, 0x0014, 0x0045); - /* Restart AN, Speed selection is 1000 */ - hw->phy.ops.write_reg(hw, 0x0000, 0x1340); - - return E1000_SUCCESS; -} - -/** - * e1000_get_phy_type_from_id - Get PHY type from id - * @phy_id: phy_id read from the phy - * - * Returns the phy type from the id. - **/ -enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) -{ - enum e1000_phy_type phy_type = e1000_phy_unknown; - - switch (phy_id) { - case M88E1000_I_PHY_ID: - case M88E1000_E_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1011_I_PHY_ID: - phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ - phy_type = e1000_phy_igp_2; - break; - case GG82563_E_PHY_ID: - phy_type = e1000_phy_gg82563; - break; - case IGP03E1000_E_PHY_ID: - phy_type = e1000_phy_igp_3; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy_type = e1000_phy_ife; - break; - default: - phy_type = e1000_phy_unknown; - break; - } - return phy_type; -} - -/** - * e1000_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * addresses. It tests each by reading the PHY ID registers and - * checking for a match. - **/ -s32 e1000_determine_phy_address(struct e1000_hw *hw) -{ - s32 ret_val = -E1000_ERR_PHY_TYPE; - u32 phy_addr = 0; - u32 i; - enum e1000_phy_type phy_type = e1000_phy_unknown; - - hw->phy.id = phy_type; - - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - i = 0; - - do { - e1000_get_phy_id(hw); - phy_type = e1000_get_phy_type_from_id(hw->phy.id); - - /* - * If phy_type is valid, break - we found our - * PHY address - */ - if (phy_type != e1000_phy_unknown) { - ret_val = E1000_SUCCESS; - goto out; - } - msec_delay(1); - i++; - } while (i < 10); - } - -out: - return ret_val; -} - -/** - * e1000_power_up_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_up_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); - mii_reg &= ~MII_CR_POWER_DOWN; - hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); -} - -/** - * e1000_power_down_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_down_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); - mii_reg |= MII_CR_POWER_DOWN; - hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); - msec_delay(1); -} diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_phy.h b/roms/ipxe/src/drivers/net/e1000/e1000_phy.h deleted file mode 100644 index 93bd7a1b0..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_phy.h +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_PHY_H_ -#define _E1000_PHY_H_ - -void e1000_init_phy_ops_generic(struct e1000_hw *hw); -s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data); -void e1000_null_phy_generic(struct e1000_hw *hw); -s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active); -s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_check_downshift_generic(struct e1000_hw *hw); -s32 e1000_check_polarity_m88(struct e1000_hw *hw); -s32 e1000_check_polarity_igp(struct e1000_hw *hw); -s32 e1000_check_polarity_ife(struct e1000_hw *hw); -s32 e1000_check_reset_block_generic(struct e1000_hw *hw); -s32 e1000_copper_link_autoneg(struct e1000_hw *hw); -s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); -s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); -#if 0 -s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); -#endif -#if 0 -s32 e1000_get_cable_length_m88(struct e1000_hw *hw); -s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); -#endif -s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); -s32 e1000_get_phy_id(struct e1000_hw *hw); -s32 e1000_get_phy_info_igp(struct e1000_hw *hw); -s32 e1000_get_phy_info_m88(struct e1000_hw *hw); -s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); -#if 0 -void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -#endif -s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); -s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); -s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); -s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); -s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); -s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_phy_reset_dsp(struct e1000_hw *hw); -s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); -enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); -s32 e1000_determine_phy_address(struct e1000_hw *hw); -void e1000_power_up_phy_copper(struct e1000_hw *hw); -void e1000_power_down_phy_copper(struct e1000_hw *hw); -s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); - -#define E1000_MAX_PHY_ADDR 4 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -#define IGP_PAGE_SHIFT 5 -#define PHY_REG_MASK 0x1F - -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ - -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 - -/* Enable flexible speed on link-up */ -#define IGP01E1000_GMII_FLEX_SPD 0x0010 -#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ - -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 - -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 - -#define IGP02E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F -#define IGP02E1000_AGC_RANGE 15 - -#define IGP03E1000_PHY_MISC_CTRL 0x1B -#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ - -#define E1000_CABLE_LENGTH_UNDEFINED 0xFF - -#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KMRNCTRLSTA_REN 0x00200000 -#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ -#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ -#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ - -/* IFE PHY Extended Status Control */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 - -/* IFE PHY Special Control */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -#define IFE_PSC_FORCE_POLARITY 0x0020 -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 - -/* IFE PHY Special Control and LED Control */ -#define IFE_PSCL_PROBE_MODE 0x0020 -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -/* IFE PHY MDIX Control */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000/e1000_regs.h b/roms/ipxe/src/drivers/net/e1000/e1000_regs.h deleted file mode 100644 index 579c0707b..000000000 --- a/roms/ipxe/src/drivers/net/e1000/e1000_regs.h +++ /dev/null @@ -1,329 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000_REGS_H_ -#define _E1000_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_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 diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e.c b/roms/ipxe/src/drivers/net/e1000e/e1000e.c deleted file mode 100644 index b7318b7db..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e.c +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -REQUIRE_OBJECT(e1000e_main); -REQUIRE_OBJECT(e1000e_80003es2lan); -REQUIRE_OBJECT(e1000e_82571); -REQUIRE_OBJECT(e1000e_ich8lan); diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e.h b/roms/ipxe/src/drivers/net/e1000e/e1000e.h deleted file mode 100644 index bc8e7b083..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e.h +++ /dev/null @@ -1,532 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000E_H_ -#define _E1000E_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Begin OS Dependencies */ - -#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 msleep(x) mdelay(x) - -#define ETH_FCS_LEN 4 - -typedef int spinlock_t; -typedef enum { - false = 0, - true = 1 -} boolean_t; - -/* End OS Dependencies */ - -#include "e1000e_hw.h" - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -#define E1000_MAX_PER_TXD 8192 -#define E1000_MAX_TXD_PWR 12 - -#define MINIMUM_DHCP_PACKET_SIZE 282 - -struct e1000_info; - -#define e_dbg(arg...) if (0) { printf (arg); }; - -#ifdef CONFIG_E1000E_MSIX -/* Interrupt modes, as used by the IntMode paramter */ -#define E1000E_INT_MODE_LEGACY 0 -#define E1000E_INT_MODE_MSI 1 -#define E1000E_INT_MODE_MSIX 2 - -#endif /* CONFIG_E1000E_MSIX */ -#ifndef CONFIG_E1000E_NAPI -#define E1000_MAX_INTR 10 - -#endif /* CONFIG_E1000E_NAPI */ -/* Tx/Rx descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 4096 -#define E1000_MIN_TXD 64 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 4096 -#define E1000_MIN_RXD 64 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - -/* Early Receive defines */ -#define E1000_ERT_2048 0x100 - -#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 0x0400 - -#define E1000_MNG_VLAN_NONE (-1) - -/* Number of packet split data buffers (not including the header buffer) */ -#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) - -#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 - -#define DEFAULT_JUMBO 9234 - -enum e1000_boards { - board_82571, - board_82572, - board_82573, - board_82574, - board_80003es2lan, - board_ich8lan, - board_ich9lan, - board_ich10lan, - board_pchlan, - board_82583, -}; - -/* board specific private data structure */ -struct e1000_adapter { - const struct e1000_info *ei; - - /* 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; - - struct e1000_phy_info phy_info; - - u32 wol; - u32 pba; - u32 max_hw_frame_size; - - bool fc_autoneg; - - unsigned int flags; - unsigned int flags2; - -#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]; - - struct e1000_tx_desc *tx_base; - struct e1000_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 e1000_info { - enum e1000_mac_type mac; - unsigned int flags; - unsigned int flags2; - u32 pba; - u32 max_hw_frame_size; - s32 (*get_variants)(struct e1000_adapter *); - void (*init_ops)(struct e1000_hw *); -}; - -/* hardware capability, feature, and workaround flags */ -#define FLAG_HAS_AMT (1 << 0) -#define FLAG_HAS_FLASH (1 << 1) -#define FLAG_HAS_HW_VLAN_FILTER (1 << 2) -#define FLAG_HAS_WOL (1 << 3) -#define FLAG_HAS_ERT (1 << 4) -#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) -#define FLAG_HAS_SWSM_ON_LOAD (1 << 6) -#define FLAG_HAS_JUMBO_FRAMES (1 << 7) -#define FLAG_IS_ICH (1 << 9) -#ifdef CONFIG_E1000E_MSIX -#define FLAG_HAS_MSIX (1 << 10) -#endif -#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) -#define FLAG_IS_QUAD_PORT_A (1 << 12) -#define FLAG_IS_QUAD_PORT (1 << 13) -#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN (1 << 14) -#define FLAG_APME_IN_WUC (1 << 15) -#define FLAG_APME_IN_CTRL3 (1 << 16) -#define FLAG_APME_CHECK_PORT_B (1 << 17) -#define FLAG_DISABLE_FC_PAUSE_TIME (1 << 18) -#define FLAG_NO_WAKE_UCAST (1 << 19) -#define FLAG_MNG_PT_ENABLED (1 << 20) -#define FLAG_RESET_OVERWRITES_LAA (1 << 21) -#define FLAG_TARC_SPEED_MODE_BIT (1 << 22) -#define FLAG_TARC_SET_BIT_ZERO (1 << 23) -#define FLAG_RX_NEEDS_RESTART (1 << 24) -#define FLAG_LSC_GIG_SPEED_DROP (1 << 25) -#define FLAG_SMART_POWER_DOWN (1 << 26) -#define FLAG_MSI_ENABLED (1 << 27) -#define FLAG_RX_CSUM_ENABLED (1 << 28) -#define FLAG_TSO_FORCE (1 << 29) -#define FLAG_RX_RESTART_NOW (1 << 30) -#define FLAG_MSI_TEST_FAILED (1 << 31) - -/* CRC Stripping defines */ -#define FLAG2_CRC_STRIPPING (1 << 0) -#define FLAG2_HAS_PHY_WAKEUP (1 << 1) - -#define E1000_RX_DESC_PS(R, i) \ - (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -enum e1000_state_t { - __E1000E_TESTING, - __E1000E_RESETTING, - __E1000E_DOWN -}; - -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - -extern void e1000e_check_options(struct e1000_adapter *adapter); - -extern void e1000e_reset(struct e1000_adapter *adapter); -extern void e1000e_power_up_phy(struct e1000_adapter *adapter); - -extern void e1000e_init_function_pointers_82571(struct e1000_hw *hw) - __attribute__((weak)); -extern void e1000e_init_function_pointers_80003es2lan(struct e1000_hw *hw) - __attribute__((weak)); -extern void e1000e_init_function_pointers_ich8lan(struct e1000_hw *hw) - __attribute__((weak)); - -extern int e1000e_probe(struct pci_device *pdev); - -extern void e1000e_remove(struct pci_device *pdev); - -extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); - -static inline s32 e1000e_commit_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.commit) - return hw->phy.ops.commit(hw); - - return 0; -} - -extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); - -extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw); -extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); - -extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state); -extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); -extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); - -extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); -extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); -extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); -extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); -extern s32 e1000e_led_on_generic(struct e1000_hw *hw); -extern s32 e1000e_led_off_generic(struct e1000_hw *hw); -extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); -extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex); -extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex); -extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw); -extern s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); -extern s32 e1000e_id_led_init(struct e1000_hw *hw); -extern void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); -extern s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); -extern s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); -extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); -extern s32 e1000e_setup_link(struct e1000_hw *hw); -static inline void e1000e_clear_vfta(struct e1000_hw *hw) -{ - hw->mac.ops.clear_vfta(hw); -} -extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); -extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, - u32 mc_addr_count); -extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); -extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); -extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); -extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); -extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); -extern void e1000e_config_collision_dist(struct e1000_hw *hw); -extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); -extern s32 e1000e_force_mac_fc(struct e1000_hw *hw); -extern s32 e1000e_blink_led(struct e1000_hw *hw); -extern void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); -static inline void e1000e_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) -{ - if (hw->mac.ops.write_vfta) - hw->mac.ops.write_vfta(hw, offset, value); -} -extern void e1000e_reset_adaptive(struct e1000_hw *hw); -extern void e1000e_update_adaptive(struct e1000_hw *hw); - -extern s32 e1000e_setup_copper_link(struct e1000_hw *hw); -extern void e1000e_put_hw_semaphore(struct e1000_hw *hw); -extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); -#if 0 -extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); -#endif -#if 0 -extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); -#endif -extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); -extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); -extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); -extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw); -#if 0 -extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); -#endif -extern s32 e1000e_get_cfg_done(struct e1000_hw *hw); -#if 0 -extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); -#endif -extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); -extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); -extern s32 e1000e_determine_phy_address(struct e1000_hw *hw); -extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -#if 0 -extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -#endif -extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); -extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000e_check_downshift(struct e1000_hw *hw); - -static inline s32 e1000e_phy_hw_reset(struct e1000_hw *hw) -{ - if (hw->phy.ops.reset) - return hw->phy.ops.reset(hw); - - return 0; -} - -static inline s32 e1000e_check_reset_block(struct e1000_hw *hw) -{ - if (hw->phy.ops.check_reset_block) - return hw->phy.ops.check_reset_block(hw); - - return 0; -} - -static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) -{ - if (hw->phy.ops.read_reg) - return hw->phy.ops.read_reg(hw, offset, data); - - return 0; -} - -static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) -{ - if (hw->phy.ops.write_reg) - return hw->phy.ops.write_reg(hw, offset, data); - - return 0; -} - -#if 0 -static inline s32 e1000e_get_cable_length(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_cable_length) - return hw->phy.ops.get_cable_length(hw); - - return 0; -} -#endif - -extern s32 e1000e_acquire_nvm(struct e1000_hw *hw); -extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); -extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); -extern void e1000e_release_nvm(struct e1000_hw *hw); - -static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) -{ - if (hw->mac.ops.read_mac_addr) - return hw->mac.ops.read_mac_addr(hw); - - return e1000e_read_mac_addr_generic(hw); -} - -static inline s32 e1000e_validate_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.validate(hw); -} - -static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.update(hw); -} - -static inline s32 e1000e_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - return hw->nvm.ops.read(hw, offset, words, data); -} - -static inline s32 e1000e_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - return hw->nvm.ops.write(hw, offset, words, data); -} - -static inline s32 e1000e_get_phy_info(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_info) - return hw->phy.ops.get_info(hw); - - return 0; -} - -extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); -#if 0 -extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); -#endif - -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) __er32(hw, E1000_##reg) -#define ew32(reg, val) __ew32(hw, E1000_##reg, (val)) -#define e1e_flush() er32(STATUS) - -#define E1000_WRITE_REG(a, reg, value) \ - writel((value), ((a)->hw_addr + reg)) - -#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg)) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ - writel((value), ((a)->hw_addr + reg + ((offset) << 2))) - -#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 - -static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) -{ - return readw(hw->flash_address + reg); -} - -static inline u32 __er32flash(struct e1000_hw *hw, unsigned long reg) -{ - return readl(hw->flash_address + reg); -} - -static inline void __ew16flash(struct e1000_hw *hw, unsigned long reg, u16 val) -{ - writew(val, hw->flash_address + reg); -} - -static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) -{ - writel(val, hw->flash_address + reg); -} - -#define er16flash(reg) __er16flash(hw, (reg)) -#define er32flash(reg) __er32flash(hw, (reg)) -#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) -#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) - -#endif /* _E1000E_H_ */ diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.c deleted file mode 100644 index a3eed9b73..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.c +++ /dev/null @@ -1,1533 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 80003ES2LAN Gigabit Ethernet Controller (Copper) - * 80003ES2LAN Gigabit Ethernet Controller (Serdes) - */ - -#include "e1000e.h" - -static s32 e1000e_init_phy_params_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_init_nvm_params_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_init_mac_params_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_acquire_phy_80003es2lan(struct e1000_hw *hw); -static void e1000e_release_phy_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_acquire_nvm_80003es2lan(struct e1000_hw *hw); -static void e1000e_release_nvm_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, - u16 *data); -static s32 e1000e_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, - u16 data); -static s32 e1000e_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000e_get_cfg_done_80003es2lan(struct e1000_hw *hw); -#if 0 -static s32 e1000e_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw); -#endif -#if 0 -static s32 e1000e_get_cable_length_80003es2lan(struct e1000_hw *hw); -#endif -static s32 e1000e_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -static s32 e1000e_reset_hw_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_init_hw_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_setup_copper_link_80003es2lan(struct e1000_hw *hw); -static void e1000e_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static s32 e1000e_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); -static s32 e1000e_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); -static s32 e1000e_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000e_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data); -static s32 e1000e_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw); -static void e1000e_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); -static void e1000e_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static s32 e1000e_read_mac_addr_80003es2lan(struct e1000_hw *hw); -static void e1000e_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); - -#if 0 -/* - * A table for the GG82563 cable length where the range is defined - * with a lower bound at "index" and the upper bound at - * "index + 5". - */ -static const u16 e1000_gg82563_cable_length_table[] = - { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF }; -#define GG82563_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_gg82563_cable_length_table) / \ - sizeof(e1000_gg82563_cable_length_table[0])) -#endif - -/** - * e1000e_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_phy_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - goto out; - } else { - phy->ops.power_up = e1000e_power_up_phy_copper; - phy->ops.power_down = e1000e_power_down_phy_copper_80003es2lan; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - phy->type = e1000_phy_gg82563; - - phy->ops.acquire = e1000e_acquire_phy_80003es2lan; - phy->ops.check_polarity = e1000e_check_polarity_m88; - phy->ops.check_reset_block = e1000e_check_reset_block_generic; - phy->ops.commit = e1000e_phy_sw_reset; - phy->ops.get_cfg_done = e1000e_get_cfg_done_80003es2lan; - phy->ops.get_info = e1000e_get_phy_info_m88; - phy->ops.release = e1000e_release_phy_80003es2lan; - phy->ops.reset = e1000e_phy_hw_reset_generic; - phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_80003es2lan; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_80003es2lan; -#endif - phy->ops.read_reg = e1000e_read_phy_reg_gg82563_80003es2lan; - phy->ops.write_reg = e1000e_write_phy_reg_gg82563_80003es2lan; - - phy->ops.cfg_on_link_up = e1000e_cfg_on_link_up_80003es2lan; - - /* This can only be done after all function pointers are setup. */ - ret_val = e1000e_get_phy_id(hw); - - /* Verify phy id */ - if (phy->id != GG82563_E_PHY_ID) { - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_nvm_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; - - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - - /* - * Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - - /* Function Pointers */ - nvm->ops.acquire = e1000e_acquire_nvm_80003es2lan; - nvm->ops.read = e1000e_read_nvm_eerd; - nvm->ops.release = e1000e_release_nvm_80003es2lan; - nvm->ops.update = e1000e_update_nvm_checksum_generic; - nvm->ops.valid_led_default = e1000e_valid_led_default; - nvm->ops.validate = e1000e_validate_nvm_checksum_generic; - nvm->ops.write = e1000e_write_nvm_80003es2lan; - - return E1000_SUCCESS; -} - -/** - * e1000e_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_mac_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - /* Set media type */ - switch (hw->device_id) { - case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: - hw->phy.media_type = e1000_media_type_internal_serdes; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* Set if part includes ASF firmware */ - mac->asf_firmware_present = true; - /* Set if manageability features are enabled. */ - mac->arc_subsystem_valid = - (er32(FWSM) & E1000_FWSM_MODE_MASK) - ? true : false; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000e_get_bus_info_pcie; - /* reset */ - mac->ops.reset_hw = e1000e_reset_hw_80003es2lan; - /* hw initialization */ - mac->ops.init_hw = e1000e_init_hw_80003es2lan; - /* link setup */ - mac->ops.setup_link = e1000e_setup_link; - /* physical interface link setup */ - mac->ops.setup_physical_interface = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000e_setup_copper_link_80003es2lan - : e1000e_setup_fiber_serdes_link; - /* check for link */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - mac->ops.check_for_link = e1000e_check_for_copper_link; - break; - case e1000_media_type_fiber: - mac->ops.check_for_link = e1000e_check_for_fiber_link; - break; - case e1000_media_type_internal_serdes: - mac->ops.check_for_link = e1000e_check_for_serdes_link; - break; - default: - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - /* check management mode */ -#if 0 - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; -#endif - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000e_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000e_clear_vfta_generic; - /* setting MTA */ - mac->ops.mta_set = e1000e_mta_set_generic; - /* read mac address */ - mac->ops.read_mac_addr = e1000e_read_mac_addr_80003es2lan; - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init; - /* blink LED */ - mac->ops.blink_led = e1000e_blink_led; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000e_cleanup_led_generic; - /* turn on/off LED */ - mac->ops.led_on = e1000e_led_on_generic; - mac->ops.led_off = e1000e_led_off_generic; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000e_clear_hw_cntrs_80003es2lan; - /* link info */ - mac->ops.get_link_up_info = e1000e_get_link_up_info_80003es2lan; - - /* set lan id for port to determine which phy lock to use */ - hw->mac.ops.set_lan_id(hw); - -out: - return ret_val; -} - -/** - * e1000e_init_function_pointers_80003es2lan - Init ESB2 func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000e_init_function_pointers_80003es2lan(struct e1000_hw *hw) -{ - e1000e_init_mac_ops_generic(hw); - e1000e_init_nvm_ops_generic(hw); - hw->mac.ops.init_params = e1000e_init_mac_params_80003es2lan; - hw->nvm.ops.init_params = e1000e_init_nvm_params_80003es2lan; - hw->phy.ops.init_params = e1000e_init_phy_params_80003es2lan; -} - -/** - * e1000e_acquire_phy_80003es2lan - Acquire rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to acquire access rights to the correct PHY. - **/ -static s32 e1000e_acquire_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - return e1000e_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000e_release_phy_80003es2lan - Release rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to release access rights to the correct PHY. - **/ -static void e1000e_release_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - e1000e_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000e_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the Kumeran interface. - * - **/ -static s32 e1000e_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - return e1000e_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000e_release_mac_csr_80003es2lan - Release rights to access Kumeran Register - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the Kumeran interface - **/ -static void e1000e_release_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - e1000e_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000e_acquire_nvm_80003es2lan - Acquire rights to access NVM - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the EEPROM. - **/ -static s32 e1000e_acquire_nvm_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000e_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - if (ret_val) - goto out; - - ret_val = e1000e_acquire_nvm(hw); - - if (ret_val) - e1000e_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - -out: - return ret_val; -} - -/** - * e1000e_release_nvm_80003es2lan - Relinquish rights to access NVM - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the EEPROM. - **/ -static void e1000e_release_nvm_80003es2lan(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000e_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); -} - -/** - * e1000e_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Acquire the SW/FW semaphore to access the PHY or NVM. The mask - * will also specify which port we're acquiring the lock for. - **/ -static s32 e1000e_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - u32 swmask = mask; - u32 fwmask = mask << 16; - s32 ret_val = E1000_SUCCESS; - s32 i = 0, timeout = 50; - - while (i < timeout) { - if (e1000e_get_hw_semaphore(hw)) { - ret_val = -E1000_ERR_SWFW_SYNC; - goto out; - } - - swfw_sync = er32(SW_FW_SYNC); - if (!(swfw_sync & (fwmask | swmask))) - break; - - /* - * Firmware currently using resource (fwmask) - * or other software thread using resource (swmask) - */ - e1000e_put_hw_semaphore(hw); - mdelay(5); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); - ret_val = -E1000_ERR_SWFW_SYNC; - goto out; - } - - swfw_sync |= swmask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); - -out: - return ret_val; -} - -/** - * e1000e_release_swfw_sync_80003es2lan - Release SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Release the SW/FW semaphore used to access the PHY or NVM. The mask - * will also specify which port we're releasing the lock for. - **/ -static void e1000e_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - - while (e1000e_get_hw_semaphore(hw) != E1000_SUCCESS) - ; /* Empty */ - - swfw_sync = er32(SW_FW_SYNC); - swfw_sync &= ~mask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); -} - -/** - * e1000e_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: pointer to the data returned from the operation - * - * Read the GG82563 PHY register. - **/ -static s32 e1000e_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 *data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000e_acquire_phy_80003es2lan(hw); - if (ret_val) - goto out; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* - * Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000e_release_phy_80003es2lan(hw); - goto out; - } - - if (hw->dev_spec._80003es2lan.mdic_wa_enable == true) { - /* - * The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - udelay(200); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - ret_val = -E1000_ERR_PHY; - e1000e_release_phy_80003es2lan(hw); - goto out; - } - - udelay(200); - - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - udelay(200); - } else - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - e1000e_release_phy_80003es2lan(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: value to write to the register - * - * Write to the GG82563 PHY register. - **/ -static s32 e1000e_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000e_acquire_phy_80003es2lan(hw); - if (ret_val) - goto out; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* - * Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000e_release_phy_80003es2lan(hw); - goto out; - } - - if (hw->dev_spec._80003es2lan.mdic_wa_enable == true) { - /* - * The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - udelay(200); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - ret_val = -E1000_ERR_PHY; - e1000e_release_phy_80003es2lan(hw); - goto out; - } - - udelay(200); - - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - udelay(200); - } else - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - e1000e_release_phy_80003es2lan(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_nvm_80003es2lan - Write to ESB2 NVM - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @words: number of words to write - * @data: buffer of data to write to the NVM - * - * Write "words" of data to the ESB2 NVM. - **/ -static s32 e1000e_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - return e1000e_write_nvm_spi(hw, offset, words, data); -} - -/** - * e1000e_get_cfg_done_80003es2lan - Wait for configuration to complete - * @hw: pointer to the HW structure - * - * Wait a specific amount of time for manageability processes to complete. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000e_get_cfg_done_80003es2lan(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - u32 mask = E1000_NVM_CFG_DONE_PORT_0; - - if (hw->bus.func == 1) - mask = E1000_NVM_CFG_DONE_PORT_1; - - while (timeout) { - if (er32(EEMNGCTL) & mask) - break; - msleep(1); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; - } - -out: - return ret_val; -} -#if 0 -/** - * e1000e_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex - * @hw: pointer to the HW structure - * - * Force the speed and duplex settings onto the PHY. This is a - * function pointer entry point called by the phy module. - **/ -static s32 e1000e_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 phy_data; - bool link; - - if (!(hw->phy.ops.read_reg)) - goto out; - - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - e_dbg("GG82563 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - /* Reset the phy to commit changes. */ - phy_data |= MII_CR_RESET; - - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - udelay(1); - - if (hw->phy.autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link " - "on GG82563 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - - if (!link) { - /* - * We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - goto out; - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - } - - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - /* - * Resetting the phy means we need to verify the TX_CLK corresponds - * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. - */ - phy_data &= ~GG82563_MSCR_TX_CLK_MASK; - if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) - phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; - else - phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; - - /* - * In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); - -out: - return ret_val; -} -#endif - -#if 0 -/** - * e1000e_get_cable_length_80003es2lan - Set approximate cable length - * @hw: pointer to the HW structure - * - * Find the approximate cable length as measured by the GG82563 PHY. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000e_get_cable_length_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_data, index; - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); - if (ret_val) - goto out; - - index = phy_data & GG82563_DSPD_CABLE_LENGTH; - - if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - phy->min_cable_length = e1000_gg82563_cable_length_table[index]; - phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} -#endif - -/** - * e1000e_get_link_up_info_80003es2lan - Report speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to speed buffer - * @duplex: pointer to duplex buffer - * - * Retrieve the current speed and duplex configuration. - **/ -static s32 e1000e_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, - speed, - duplex); - hw->phy.ops.cfg_on_link_up(hw); - } else { - ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, - speed, - duplex); - } - - return ret_val; -} - -/** - * e1000e_reset_hw_80003es2lan - Reset the ESB2 controller - * @hw: pointer to the HW structure - * - * Perform a global reset to the ESB2 controller. - **/ -static s32 e1000e_reset_hw_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - msleep(10); - - ctrl = er32(CTRL); - - ret_val = e1000e_acquire_phy_80003es2lan(hw); - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - e1000e_release_phy_80003es2lan(hw); - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - goto out; - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - ret_val = e1000e_check_alt_mac_addr_generic(hw); - -out: - return ret_val; -} - -/** - * e1000e_init_hw_80003es2lan - Initialize the ESB2 controller - * @hw: pointer to the HW structure - * - * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. - **/ -static s32 e1000e_init_hw_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 i; - - e1000e_initialize_hw_bits_80003es2lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) { - e_dbg("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ - } - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - e1000e_clear_vfta(hw); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - reg_data = er32(TXDCTL(1)); - reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; - ew32(TXDCTL(1), reg_data); - - /* Enable retransmit on late collisions */ - reg_data = er32(TCTL); - reg_data |= E1000_TCTL_RTLC; - ew32(TCTL, reg_data); - - /* Configure Gigabit Carry Extend Padding */ - reg_data = er32(TCTL_EXT); - reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; - reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; - ew32(TCTL_EXT, reg_data); - - /* Configure Transmit Inter-Packet Gap */ - reg_data = er32(TIPG); - reg_data &= ~E1000_TIPG_IPGT_MASK; - reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, reg_data); - - reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); - reg_data &= ~0x00100000; - E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); - - /* default to true to enable the MDIC W/A */ - hw->dev_spec._80003es2lan.mdic_wa_enable = true; - - ret_val = e1000e_read_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET >> - E1000_KMRNCTRLSTA_OFFSET_SHIFT, - &i); - if (!ret_val) { - if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == - E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) - hw->dev_spec._80003es2lan.mdic_wa_enable = false; - } - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000e_clear_hw_cntrs_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000e_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000e_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - if (hw->phy.media_type != e1000_media_type_copper) - reg &= ~(1 << 20); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - - return; -} - -/** - * e1000e_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link - * @hw: pointer to the HW structure - * - * Setup some GG82563 PHY registers for obtaining link - **/ -static s32 e1000e_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u32 ctrl_ext; - u16 data; - - if (!phy->reset_disable) { - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, - &data); - if (ret_val) - goto out; - - data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ - data |= GG82563_MSCR_TX_CLK_1000MBPS_25; - - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, - data); - if (ret_val) - goto out; - - /* - * Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL, &data); - if (ret_val) - goto out; - - data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; - - switch (phy->mdix) { - case 1: - data |= GG82563_PSCR_CROSSOVER_MODE_MDI; - break; - case 2: - data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; - break; - case 0: - default: - data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; - break; - } - - /* - * Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - if (phy->disable_polarity_correction) - data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, data); - if (ret_val) - goto out; - - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000e_commit_phy(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - goto out; - } - - } - - /* Bypass Rx and Tx FIFO's */ - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, - E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | - E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); - if (ret_val) - goto out; - - ret_val = e1000e_read_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, - &data); - if (ret_val) - goto out; - data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, - data); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); - if (ret_val) - goto out; - - data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL_2, data); - if (ret_val) - goto out; - - ctrl_ext = er32(CTRL_EXT); - ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK); - ew32(CTRL_EXT, ctrl_ext); - - ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); - if (ret_val) - goto out; - - /* - * Do not init these registers when the HW is in IAMT mode, since the - * firmware will have already initialized them. We only initialize - * them if the HW is not in IAMT mode. - */ - if (!(hw->mac.ops.check_mng_mode(hw))) { - /* Enable Electrical Idle on the PHY */ - data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; - ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, - data); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - &data); - if (ret_val) - goto out; - - data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - data); - if (ret_val) - goto out; - } - - /* - * Workaround: Disable padding in Kumeran interface in the MAC - * and in the PHY to avoid CRC errors. - */ - ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); - if (ret_val) - goto out; - - data |= GG82563_ICR_DIS_PADDING; - ret_val = e1e_wphy(hw, GG82563_PHY_INBAND_CTRL, data); - if (ret_val) - goto out; - -out: - return ret_val; -} - -/** - * e1000e_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 - * @hw: pointer to the HW structure - * - * Essentially a wrapper for setting up all things "copper" related. - * This is a function pointer entry point called by the mac module. - **/ -static s32 e1000e_setup_copper_link_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* - * Set the mac to wait the maximum time between each - * iteration and increase the max iterations when - * polling the phy; this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), - 0xFFFF); - if (ret_val) - goto out; - ret_val = e1000e_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - ®_data); - if (ret_val) - goto out; - reg_data |= 0x3F; - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - reg_data); - if (ret_val) - goto out; - ret_val = e1000e_read_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - ®_data); - if (ret_val) - goto out; - reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - reg_data); - if (ret_val) - goto out; - - ret_val = e1000e_copper_link_setup_gg82563_80003es2lan(hw); - if (ret_val) - goto out; - - ret_val = e1000e_setup_copper_link(hw); - -out: - return ret_val; -} - -/** - * e1000e_cfg_on_link_up_80003es2lan - es2 link configuration after link-up - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000e_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 speed; - u16 duplex; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, - &speed, - &duplex); - if (ret_val) - goto out; - - if (speed == SPEED_1000) - ret_val = e1000e_cfg_kmrn_1000_80003es2lan(hw); - else - ret_val = e1000e_cfg_kmrn_10_100_80003es2lan(hw, duplex); - } - -out: - return ret_val; -} - -/** - * e1000e_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000e_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) -{ - s32 ret_val = E1000_SUCCESS; - u32 tipg; - u32 i = 0; - u16 reg_data, reg_data2; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - goto out; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; - ew32(TIPG, tipg); - - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data2); - if (ret_val) - goto out; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - if (duplex == HALF_DUPLEX) - reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; - else - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - - ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); - -out: - return ret_val; -} - -/** - * e1000e_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation - * @hw: pointer to the HW structure - * - * Configure the KMRN interface by applying last minute quirks for - * gigabit operation. - **/ -static s32 e1000e_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 reg_data, reg_data2; - u32 tipg; - u32 i = 0; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; - ret_val = e1000e_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - goto out; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, tipg); - - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, - ®_data2); - if (ret_val) - goto out; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); - -out: - return ret_val; -} - -/** - * e1000e_read_kmrn_reg_80003es2lan - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquire semaphore, then read the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release the semaphore before exiting. - **/ -static s32 e1000e_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - ret_val = e1000e_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - goto out; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - e1000e_release_mac_csr_80003es2lan(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_kmrn_reg_80003es2lan - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquire semaphore, then write the data to PHY register - * at the offset using the kumeran interface. Release semaphore - * before exiting. - **/ -static s32 e1000e_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - ret_val = e1000e_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - goto out; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - - udelay(2); - - e1000e_release_mac_csr_80003es2lan(hw); - -out: - return ret_val; -} - -/** - * e1000e_read_mac_addr_80003es2lan - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000e_read_mac_addr_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000e_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; - - ret_val = e1000e_read_mac_addr_generic(hw); - -out: - return ret_val; -} - -/** - * e1000e_power_down_phy_copper_80003es2lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000e_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - e1000e_check_reset_block(hw))) - e1000e_power_down_phy_copper(hw); - - return; -} - -/** - * e1000e_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000e_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw __unused) -{ -#if 0 - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -#endif -} - -static struct pci_device_id e1000e_80003es2lan_nics[] = { - PCI_ROM(0x8086, 0x1096, "E1000_DEV_ID_80003ES2LAN_COPPER_DPT", "E1000_DEV_ID_80003ES2LAN_COPPER_DPT", board_80003es2lan), - PCI_ROM(0x8086, 0x10BA, "E1000_DEV_ID_80003ES2LAN_COPPER_SPT", "E1000_DEV_ID_80003ES2LAN_COPPER_SPT", board_80003es2lan), - PCI_ROM(0x8086, 0x1098, "E1000_DEV_ID_80003ES2LAN_SERDES_DPT", "E1000_DEV_ID_80003ES2LAN_SERDES_DPT", board_80003es2lan), - PCI_ROM(0x8086, 0x10BB, "E1000_DEV_ID_80003ES2LAN_SERDES_SPT", "E1000_DEV_ID_80003ES2LAN_SERDES_SPT", board_80003es2lan), -}; - -struct pci_driver e1000e_80003es2lan_driver __pci_driver = { - .ids = e1000e_80003es2lan_nics, - .id_count = (sizeof (e1000e_80003es2lan_nics) / sizeof (e1000e_80003es2lan_nics[0])), - .probe = e1000e_probe, - .remove = e1000e_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.h deleted file mode 100644 index 93430a16a..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_80003es2lan.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_80003ES2LAN_H_ -#define _E1000E_80003ES2LAN_H_ - -#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 -#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 -#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 -#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F - -#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 -#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 -#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 - -#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 -#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 -#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 - -#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C -#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 - -#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ -#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 - -#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 -#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 - -/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ -#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disabled */ -#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 -#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ -#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ -#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ - -/* PHY Specific Control Register 2 (Page 0, Register 26) */ -#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 - /* 1=Reverse Auto-Negotiation */ - -/* MAC Specific Control Register (Page 2, Register 21) */ -/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ -#define GG82563_MSCR_TX_CLK_MASK 0x0007 -#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 -#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 -#define GG82563_MSCR_TX_CLK_1000MBPS_2_5 0x0006 -#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 - -#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ - -/* DSP Distance Register (Page 5, Register 26) */ -/* - * 0 = <50M - * 1 = 50-80M - * 2 = 80-100M - * 3 = 110-140M - * 4 = >140M - */ -#define GG82563_DSPD_CABLE_LENGTH 0x0007 - -/* Kumeran Mode Control Register (Page 193, Register 16) */ -#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 - -/* Max number of times Kumeran read/write should be validated */ -#define GG82563_MAX_KMRN_RETRY 0x5 - -/* Power Management Control Register (Page 193, Register 20) */ -#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 - /* 1=Enable SERDES Electrical Idle */ - -/* In-Band Control Register (Page 194, Register 18) */ -#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.c deleted file mode 100644 index a061d6d49..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.c +++ /dev/null @@ -1,1818 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82571EB Gigabit Ethernet Controller - * 82571EB Gigabit Ethernet Controller (Copper) - * 82571EB Gigabit Ethernet Controller (Fiber) - * 82571EB Dual Port Gigabit Mezzanine Adapter - * 82571EB Quad Port Gigabit Mezzanine Adapter - * 82571PT Gigabit PT Quad Port Server ExpressModule - * 82572EI Gigabit Ethernet Controller (Copper) - * 82572EI Gigabit Ethernet Controller (Fiber) - * 82572EI Gigabit Ethernet Controller - * 82573V Gigabit Ethernet Controller (Copper) - * 82573E Gigabit Ethernet Controller (Copper) - * 82573L Gigabit Ethernet Controller - * 82574L Gigabit Network Connection - * 82574L Gigabit Network Connection - * 82583V Gigabit Network Connection - */ - -#include "e1000e.h" - -static s32 e1000e_init_phy_params_82571(struct e1000_hw *hw); -static s32 e1000e_init_nvm_params_82571(struct e1000_hw *hw); -static s32 e1000e_init_mac_params_82571(struct e1000_hw *hw); -static s32 e1000e_acquire_nvm_82571(struct e1000_hw *hw); -static void e1000e_release_nvm_82571(struct e1000_hw *hw); -static s32 e1000e_write_nvm_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000e_update_nvm_checksum_82571(struct e1000_hw *hw); -static s32 e1000e_validate_nvm_checksum_82571(struct e1000_hw *hw); -static s32 e1000e_get_cfg_done_82571(struct e1000_hw *hw); -static s32 e1000e_set_d0_lplu_state_82571(struct e1000_hw *hw, - bool active); -static s32 e1000e_reset_hw_82571(struct e1000_hw *hw); -static s32 e1000e_init_hw_82571(struct e1000_hw *hw); -static void e1000e_clear_vfta_82571(struct e1000_hw *hw); -#if 0 -static bool e1000e_check_mng_mode_82574(struct e1000_hw *hw); -#endif -static s32 e1000e_led_on_82574(struct e1000_hw *hw); -static s32 e1000e_setup_link_82571(struct e1000_hw *hw); -static s32 e1000e_setup_copper_link_82571(struct e1000_hw *hw); -static s32 e1000e_check_for_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000e_setup_fiber_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000e_valid_led_default_82571(struct e1000_hw *hw, u16 *data); -static void e1000e_clear_hw_cntrs_82571(struct e1000_hw *hw); -static s32 e1000e_get_hw_semaphore_82571(struct e1000_hw *hw); -static s32 e1000e_fix_nvm_checksum_82571(struct e1000_hw *hw); -static s32 e1000e_get_phy_id_82571(struct e1000_hw *hw); -static void e1000e_put_hw_semaphore_82571(struct e1000_hw *hw); -static void e1000e_initialize_hw_bits_82571(struct e1000_hw *hw); -static s32 e1000e_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000e_read_mac_addr_82571(struct e1000_hw *hw); -static void e1000e_power_down_phy_copper_82571(struct e1000_hw *hw); - -/** - * e1000e_init_phy_params_82571 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_phy_params_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - goto out; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - - phy->ops.acquire = e1000e_get_hw_semaphore_82571; - phy->ops.check_polarity = e1000e_check_polarity_igp; - phy->ops.check_reset_block = e1000e_check_reset_block_generic; - phy->ops.release = e1000e_put_hw_semaphore_82571; - phy->ops.reset = e1000e_phy_hw_reset_generic; - phy->ops.set_d0_lplu_state = e1000e_set_d0_lplu_state_82571; - phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state; - phy->ops.power_up = e1000e_power_up_phy_copper; - phy->ops.power_down = e1000e_power_down_phy_copper_82571; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - phy->type = e1000_phy_igp_2; - phy->ops.get_cfg_done = e1000e_get_cfg_done_82571; - phy->ops.get_info = e1000e_get_phy_info_igp; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; -#endif - phy->ops.read_reg = e1000e_read_phy_reg_igp; - phy->ops.write_reg = e1000e_write_phy_reg_igp; - - /* This uses above function pointers */ - ret_val = e1000e_get_phy_id_82571(hw); - - /* Verify PHY ID */ - if (phy->id != IGP01E1000_I_PHY_ID) { - ret_val = -E1000_ERR_PHY; - goto out; - } - break; - case e1000_82573: - phy->type = e1000_phy_m88; - phy->ops.get_cfg_done = e1000e_get_cfg_done; - phy->ops.get_info = e1000e_get_phy_info_m88; - phy->ops.commit = e1000e_phy_sw_reset; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_m88; -#endif - phy->ops.read_reg = e1000e_read_phy_reg_m88; - phy->ops.write_reg = e1000e_write_phy_reg_m88; - - /* This uses above function pointers */ - ret_val = e1000e_get_phy_id_82571(hw); - - /* Verify PHY ID */ - if (phy->id != M88E1111_I_PHY_ID) { - ret_val = -E1000_ERR_PHY; - e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); - goto out; - } - break; - case e1000_82583: - case e1000_82574: - phy->type = e1000_phy_bm; - phy->ops.get_cfg_done = e1000e_get_cfg_done; - phy->ops.get_info = e1000e_get_phy_info_m88; - phy->ops.commit = e1000e_phy_sw_reset; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_m88; -#endif - phy->ops.read_reg = e1000e_read_phy_reg_bm2; - phy->ops.write_reg = e1000e_write_phy_reg_bm2; - - /* This uses above function pointers */ - ret_val = e1000e_get_phy_id_82571(hw); - /* Verify PHY ID */ - if (phy->id != BME1000_E_PHY_ID_R2) { - ret_val = -E1000_ERR_PHY; - e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); - goto out; - } - break; - default: - ret_val = -E1000_ERR_PHY; - goto out; - break; - } - -out: - return ret_val; -} - -/** - * e1000e_init_nvm_params_82571 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_nvm_params_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (((eecd >> 15) & 0x3) == 0x3) { - nvm->type = e1000_nvm_flash_hw; - nvm->word_size = 2048; - /* - * Autonomous Flash update bit must be cleared due - * to Flash update issue. - */ - eecd &= ~E1000_EECD_AUPDEN; - ew32(EECD, eecd); - break; - } - /* Fall Through */ - default: - nvm->type = e1000_nvm_eeprom_spi; - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - /* - * Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - break; - } - - /* Function Pointers */ - nvm->ops.acquire = e1000e_acquire_nvm_82571; - nvm->ops.read = e1000e_read_nvm_eerd; - nvm->ops.release = e1000e_release_nvm_82571; - nvm->ops.update = e1000e_update_nvm_checksum_82571; - nvm->ops.validate = e1000e_validate_nvm_checksum_82571; - nvm->ops.valid_led_default = e1000e_valid_led_default_82571; - nvm->ops.write = e1000e_write_nvm_82571; - - return E1000_SUCCESS; -} - -/** - * e1000e_init_mac_params_82571 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000e_init_mac_params_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - u32 swsm = 0; - u32 swsm2 = 0; - bool force_clear_smbi = false; - - /* Set media type */ - switch (hw->device_id) { - case E1000_DEV_ID_82571EB_FIBER: - case E1000_DEV_ID_82572EI_FIBER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - hw->phy.media_type = e1000_media_type_fiber; - break; - case E1000_DEV_ID_82571EB_SERDES: - case E1000_DEV_ID_82571EB_SERDES_DUAL: - case E1000_DEV_ID_82571EB_SERDES_QUAD: - case E1000_DEV_ID_82572EI_SERDES: - hw->phy.media_type = e1000_media_type_internal_serdes; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* Set if part includes ASF firmware */ - mac->asf_firmware_present = true; - /* Set if manageability features are enabled. */ - mac->arc_subsystem_valid = - (er32(FWSM) & E1000_FWSM_MODE_MASK) - ? true : false; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000e_get_bus_info_pcie; - /* function id */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - mac->ops.set_lan_id = e1000e_set_lan_id_single_port; - break; - default: - break; - } - /* reset */ - mac->ops.reset_hw = e1000e_reset_hw_82571; - /* hw initialization */ - mac->ops.init_hw = e1000e_init_hw_82571; - /* link setup */ - mac->ops.setup_link = e1000e_setup_link_82571; - /* physical interface link setup */ - mac->ops.setup_physical_interface = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000e_setup_copper_link_82571 - : e1000e_setup_fiber_serdes_link_82571; - /* check for link */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - mac->ops.check_for_link = e1000e_check_for_copper_link; - break; - case e1000_media_type_fiber: - mac->ops.check_for_link = e1000e_check_for_fiber_link; - break; - case e1000_media_type_internal_serdes: - mac->ops.check_for_link = e1000e_check_for_serdes_link_82571; - break; - default: - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - /* check management mode */ -#if 0 - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - mac->ops.check_mng_mode = e1000e_check_mng_mode_82574; - break; - default: - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; - break; - } -#endif - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = e1000e_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = e1000e_clear_vfta_82571; - /* setting MTA */ - mac->ops.mta_set = e1000e_mta_set_generic; - /* read mac address */ - mac->ops.read_mac_addr = e1000e_read_mac_addr_82571; - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init; - /* blink LED */ - mac->ops.blink_led = e1000e_blink_led; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000e_cleanup_led_generic; - /* turn on/off LED */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - mac->ops.led_on = e1000e_led_on_82574; - break; - default: - mac->ops.led_on = e1000e_led_on_generic; - break; - } - mac->ops.led_off = e1000e_led_off_generic; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000e_clear_hw_cntrs_82571; - /* link info */ - mac->ops.get_link_up_info = - (hw->phy.media_type == e1000_media_type_copper) - ? e1000e_get_speed_and_duplex_copper - : e1000e_get_speed_and_duplex_fiber_serdes; - - /* - * Ensure that the inter-port SWSM.SMBI lock bit is clear before - * first NVM or PHY acess. This should be done for single-port - * devices, and for one port only on dual-port devices so that - * for those devices we can still use the SMBI lock to synchronize - * inter-port accesses to the PHY & NVM. - */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - swsm2 = er32(SWSM2); - - if (!(swsm2 & E1000_SWSM2_LOCK)) { - /* Only do this for the first interface on this card */ - ew32(SWSM2, - swsm2 | E1000_SWSM2_LOCK); - force_clear_smbi = true; - } else - force_clear_smbi = false; - break; - default: - force_clear_smbi = true; - break; - } - - if (force_clear_smbi) { - /* Make sure SWSM.SMBI is clear */ - swsm = er32(SWSM); - if (swsm & E1000_SWSM_SMBI) { - /* This bit should not be set on a first interface, and - * indicates that the bootagent or EFI code has - * improperly left this bit enabled - */ - e_dbg("Please update your 82571 Bootagent\n"); - } - ew32(SWSM, swsm & ~E1000_SWSM_SMBI); - } - - /* - * Initialze device specific counter of SMBI acquisition - * timeouts. - */ - hw->dev_spec._82571.smb_counter = 0; - -out: - return ret_val; -} - -/** - * e1000e_init_function_pointers_82571 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void e1000e_init_function_pointers_82571(struct e1000_hw *hw) -{ - e1000e_init_mac_ops_generic(hw); - e1000e_init_nvm_ops_generic(hw); - hw->mac.ops.init_params = e1000e_init_mac_params_82571; - hw->nvm.ops.init_params = e1000e_init_nvm_params_82571; - hw->phy.ops.init_params = e1000e_init_phy_params_82571; -} - -/** - * e1000e_get_phy_id_82571 - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -static s32 e1000e_get_phy_id_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_id = 0; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* - * The 82571 firmware may still be configuring the PHY. - * In this case, we cannot access the PHY until the - * configuration is done. So we explicitly set the - * PHY ID. - */ - phy->id = IGP01E1000_I_PHY_ID; - break; - case e1000_82573: - ret_val = e1000e_get_phy_id(hw); - break; - case e1000_82574: - case e1000_82583: - ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); - if (ret_val) - goto out; - - phy->id = (u32)(phy_id << 16); - udelay(20); - ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); - if (ret_val) - goto out; - - phy->id |= (u32)(phy_id); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } -out: - return ret_val; -} - -/** - * e1000e_get_hw_semaphore_82571 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 e1000e_get_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - s32 ret_val = E1000_SUCCESS; - s32 sw_timeout = hw->nvm.word_size + 1; - s32 fw_timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* - * If we have timedout 3 times on trying to acquire - * the inter-port SMBI semaphore, there is old code - * operating on the other port, and it is not - * releasing SMBI. Modify the number of times that - * we try for the semaphore to interwork with this - * older code. - */ - if (hw->dev_spec._82571.smb_counter > 2) - sw_timeout = 1; - - /* Get the SW semaphore */ - while (i < sw_timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - udelay(50); - i++; - } - - if (i == sw_timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - hw->dev_spec._82571.smb_counter++; - } - /* Get the FW semaphore. */ - for (i = 0; i < fw_timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - udelay(50); - } - - if (i == fw_timeout) { - /* Release semaphores */ - e1000e_put_hw_semaphore_82571(hw); - e_dbg("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_put_hw_semaphore_82571 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void e1000e_put_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} - -/** - * e1000e_acquire_nvm_82571 - Request for access to the EEPROM - * @hw: pointer to the HW structure - * - * To gain access to the EEPROM, first we must obtain a hardware semaphore. - * Then for non-82573 hardware, set the EEPROM access request bit and wait - * for EEPROM access grant bit. If the access grant bit is not set, release - * hardware semaphore. - **/ -static s32 e1000e_acquire_nvm_82571(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000e_get_hw_semaphore_82571(hw); - if (ret_val) - goto out; - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - break; - default: - ret_val = e1000e_acquire_nvm(hw); - break; - } - - if (ret_val) - e1000e_put_hw_semaphore_82571(hw); - -out: - return ret_val; -} - -/** - * e1000e_release_nvm_82571 - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -static void e1000e_release_nvm_82571(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000e_put_hw_semaphore_82571(hw); -} - -/** - * e1000e_write_nvm_82571 - Write to EEPROM using appropriate interface - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * For non-82573 silicon, write data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000e_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - s32 ret_val = E1000_SUCCESS; - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - ret_val = e1000e_write_nvm_eewr_82571(hw, offset, words, data); - break; - case e1000_82571: - case e1000_82572: - ret_val = e1000e_write_nvm_spi(hw, offset, words, data); - break; - default: - ret_val = -E1000_ERR_NVM; - break; - } - - return ret_val; -} - -/** - * e1000e_update_nvm_checksum_82571 - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -static s32 e1000e_update_nvm_checksum_82571(struct e1000_hw *hw) -{ - u32 eecd; - s32 ret_val; - u16 i; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - goto out; - - /* - * If our nvm is an EEPROM, then we're done - * otherwise, commit the checksum to the flash NVM. - */ - if (hw->nvm.type != e1000_nvm_flash_hw) - goto out; - - /* Check for pending operations. */ - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - msleep(1); - if ((er32(EECD) & E1000_EECD_FLUPD) == 0) - break; - } - - if (i == E1000_FLASH_UPDATES) { - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Reset the firmware if using STM opcode. */ - if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { - /* - * The enabling of and the actual reset must be done - * in two write cycles. - */ - ew32(HICR, E1000_HICR_FW_RESET_ENABLE); - e1e_flush(); - ew32(HICR, E1000_HICR_FW_RESET); - } - - /* Commit the write to flash */ - eecd = er32(EECD) | E1000_EECD_FLUPD; - ew32(EECD, eecd); - - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - msleep(1); - if ((er32(EECD) & E1000_EECD_FLUPD) == 0) - break; - } - - if (i == E1000_FLASH_UPDATES) { - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_validate_nvm_checksum_82571 - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -static s32 e1000e_validate_nvm_checksum_82571(struct e1000_hw *hw) -{ - if (hw->nvm.type == e1000_nvm_flash_hw) - e1000e_fix_nvm_checksum_82571(hw); - - return e1000e_validate_nvm_checksum_generic(hw); -} - -/** - * e1000e_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * After checking for invalid values, poll the EEPROM to ensure the previous - * command has completed before trying to write the next word. After write - * poll for completion. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000e_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eewr = 0; - s32 ret_val = 0; - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - for (i = 0; i < words; i++) { - eewr = (data[i] << E1000_NVM_RW_REG_DATA) | - ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | - E1000_NVM_RW_REG_START; - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - - ew32(EEWR, eewr); - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - } - -out: - return ret_val; -} - -/** - * e1000e_get_cfg_done_82571 - Poll for configuration done - * @hw: pointer to the HW structure - * - * Reads the management control register for the config done bit to be set. - **/ -static s32 e1000e_get_cfg_done_82571(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - - while (timeout) { - if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) - break; - msleep(1); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When activating LPLU - * this function also disables smart speed and vice versa. LPLU will not be - * activated unless the device autonegotiation advertisement meets standards - * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function - * pointer entry point only called by PHY setup routines. - **/ -static s32 e1000e_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 data; - - if (!(phy->ops.read_reg)) - goto out; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - goto out; - - if (active) { - data |= IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else { - data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, - data); - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000e_reset_hw_82571 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000e_reset_hw_82571(struct e1000_hw *hw) -{ - u32 ctrl, extcnf_ctrl, ctrl_ext; - s32 ret_val; - u16 i = 0; - - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - msleep(10); - - /* - * Must acquire the MDIO ownership before MAC reset. - * Ownership defaults to firmware after a reset. - */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - - do { - ew32(EXTCNF_CTRL, extcnf_ctrl); - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) - break; - - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - - msleep(2); - i++; - } while (i < MDIO_OWNERSHIP_TIMEOUT); - break; - default: - break; - } - - ctrl = er32(CTRL); - - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - - if (hw->nvm.type == e1000_nvm_flash_hw) { - udelay(10); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - } - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - goto out; - - /* - * Phy configuration from NVM just starts after EECD_AUTO_RD is set. - * Need to wait for Phy configuration completion before accessing - * NVM and Phy. - */ - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - msleep(25); - break; - default: - break; - } - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000e_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; - - e1000e_set_laa_state_82571(hw, true); - - /* Reinitialize the 82571 serdes link state machine */ - if (hw->phy.media_type == e1000_media_type_internal_serdes) - hw->mac.serdes_link_state = e1000_serdes_link_down; - -out: - return ret_val; -} - -/** - * e1000e_init_hw_82571 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000e_init_hw_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 i, rar_count = mac->rar_entry_count; - - e1000e_initialize_hw_bits_82571(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) { - e_dbg("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ - } - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - e1000e_clear_vfta(hw); - - /* Setup the receive address. */ - /* - * If, however, a locally administered address was assigned to the - * 82571, we must reserve a RAR for it to work around an issue where - * resetting one port will reload the MAC on the other port. - */ - if (e1000e_get_laa_state_82571(hw)) - rar_count--; - e1000e_init_rx_addrs(hw, rar_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | - E1000_TXDCTL_COUNT_DESC; - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - switch (mac->type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: -#if 0 - e1000e_enable_tx_pkt_filtering(hw); -#endif - reg_data = er32(GCR); - reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; - ew32(GCR, reg_data); - break; - default: - reg_data = er32(TXDCTL(1)); - reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | - E1000_TXDCTL_COUNT_DESC; - ew32(TXDCTL(1), reg_data); - break; - } - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000e_clear_hw_cntrs_82571(hw); - - return ret_val; -} - -/** - * e1000e_initialize_hw_bits_82571 - Initialize hardware-dependent bits - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000e_initialize_hw_bits_82571(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); - break; - default: - break; - } - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg &= ~((1 << 29) | (1 << 30)); - reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - break; - default: - break; - } - - /* Device Control */ - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - reg = er32(CTRL); - reg &= ~(1 << 29); - ew32(CTRL, reg); - break; - default: - break; - } - - /* Extended Device Control */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - reg = er32(CTRL_EXT); - reg &= ~(1 << 23); - reg |= (1 << 22); - ew32(CTRL_EXT, reg); - break; - default: - break; - } - - - if (hw->mac.type == e1000_82571) { - reg = er32(PBA_ECC); - reg |= E1000_PBA_ECC_CORR_EN; - ew32(PBA_ECC, reg); - } - - /* - * Workaround for hardware errata. - * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 - */ - - if ((hw->mac.type == e1000_82571) || - (hw->mac.type == e1000_82572)) { - reg = er32(CTRL_EXT); - reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; - ew32(CTRL_EXT, reg); - } - - /* PCI-Ex Control Registers */ - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - reg = er32(GCR); - reg |= (1 << 22); - ew32(GCR, reg); - /* - * Workaround for hardware errata. - * apply workaround for hardware errata documented in errata - * docs Fixes issue where some error prone or unreliable PCIe - * completions are occurring, particularly with ASPM enabled. - * Without fix, issue can cause tx timeouts. - */ - reg = er32(GCR2); - reg |= 1; - ew32(GCR2, reg); - break; - default: - break; - } - return; -} - -/** - * e1000e_clear_vfta_82571 - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -static void e1000e_clear_vfta_82571(struct e1000_hw *hw) -{ - u32 offset; - u32 vfta_value = 0; - u32 vfta_offset = 0; - u32 vfta_bit_in_reg = 0; - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - if (hw->mng_cookie.vlan_id != 0) { - /* - *The VFTA is a 4096b bit-field, each identifying - *a single VLAN ID. The following operations - *determine which 32b entry (i.e. offset) into the - *array we want to set the VLAN ID (i.e. bit) of - *the manageability unit. - */ - vfta_offset = (hw->mng_cookie.vlan_id >> - E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; - vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & - E1000_VFTA_ENTRY_BIT_SHIFT_MASK); - } - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* - *If the offset we want to clear is the same offset of - *the manageability VLAN ID, then clear all bits except - *that of the manageability unit - */ - vfta_value = (offset == vfta_offset) ? - vfta_bit_in_reg : 0; - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, - vfta_value); - e1e_flush(); - } - break; - default: - break; - } -} - -#if 0 -/** - * e1000e_check_mng_mode_82574 - Check manageability is enabled - * @hw: pointer to the HW structure - * - * Reads the NVM Initialization Control Word 2 and returns true - * (>0) if any manageability is enabled, else false (0). - **/ -static bool e1000e_check_mng_mode_82574(struct e1000_hw *hw) -{ - u16 data; - - e1000e_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; -} -#endif - -/** - * e1000e_led_on_82574 - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -static s32 e1000e_led_on_82574(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl; - u32 i; - - ctrl = hw->mac.ledctl_mode2; - if (!(E1000_STATUS_LU & er32(STATUS))) { - /* - * If no link, then turn LED on by setting the invert bit - * for each LED that's "on" (0x0E) in ledctl_mode2. - */ - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); - } - ew32(LEDCTL, ctrl); -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_setup_link_82571 - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000e_setup_link_82571(struct e1000_hw *hw) -{ - /* - * 82573 does not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - if (hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; - break; - default: - break; - } - return e1000e_setup_link(hw); -} - -/** - * e1000e_setup_copper_link_82571 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Configures the link for auto-neg or forced speed and duplex. Then we check - * for link, once link is established calls to configure collision distance - * and flow control are called. - **/ -static s32 e1000e_setup_copper_link_82571(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - switch (hw->phy.type) { - case e1000_phy_m88: - case e1000_phy_bm: - ret_val = e1000e_copper_link_setup_m88(hw); - break; - case e1000_phy_igp_2: - ret_val = e1000e_copper_link_setup_igp(hw); - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - if (ret_val) - goto out; - - ret_val = e1000e_setup_copper_link(hw); - -out: - return ret_val; -} - -/** - * e1000e_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes links. - * Upon successful setup, poll for link. - **/ -static s32 e1000e_setup_fiber_serdes_link_82571(struct e1000_hw *hw) -{ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* - * If SerDes loopback mode is entered, there is no form - * of reset to take the adapter out of that mode. So we - * have to explicitly take the adapter out of loopback - * mode. This prevents drivers from twiddling their thumbs - * if another tool failed to take it out of loopback mode. - */ - ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - break; - default: - break; - } - - return e1000e_setup_fiber_serdes_link(hw); -} - -/** - * e1000e_check_for_serdes_link_82571 - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Reports the link state as up or down. - * - * If autonegotiation is supported by the link partner, the link state is - * determined by the result of autongotiation. This is the most likely case. - * If autonegotiation is not supported by the link partner, and the link - * has a valid signal, force the link up. - * - * The link state is represented internally here by 4 states: - * - * 1) down - * 2) autoneg_progress - * 3) autoneg_complete (the link sucessfully autonegotiated) - * 4) forced_up (the link has been forced up, it did not autonegotiate) - * - **/ -s32 e1000e_check_for_serdes_link_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { - - /* Receiver is synchronized with no invalid bits. */ - switch (mac->serdes_link_state) { - case e1000_serdes_link_autoneg_complete: - if (!(status & E1000_STATUS_LU)) { - /* - * We have lost link, retry autoneg before - * reporting link failure - */ - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("AN_UP -> AN_PROG\n"); - } - break; - - case e1000_serdes_link_forced_up: - /* - * If we are receiving /C/ ordered sets, re-enable - * auto-negotiation in the TXCW register and disable - * forced link in the Device Control register in an - * attempt to auto-negotiate with our link partner. - */ - if (rxcw & E1000_RXCW_C) { - /* Enable autoneg, and unforce link up */ - ew32(TXCW, mac->txcw); - ew32(CTRL, - (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("FORCED_UP -> AN_PROG\n"); - } - break; - - case e1000_serdes_link_autoneg_progress: - if (rxcw & E1000_RXCW_C) { - /* We received /C/ ordered sets, meaning the - * link partner has autonegotiated, and we can - * trust the Link Up (LU) status bit - */ - if (status & E1000_STATUS_LU) { - mac->serdes_link_state = - e1000_serdes_link_autoneg_complete; - e_dbg("AN_PROG -> AN_UP\n"); - mac->serdes_has_link = true; - } else { - /* Autoneg completed, but failed */ - mac->serdes_link_state = - e1000_serdes_link_down; - e_dbg("AN_PROG -> DOWN\n"); - } - } else { - /* The link partner did not autoneg. - * Force link up and full duplex, and change - * state to forced. - */ - ew32(TXCW, - (mac->txcw & ~E1000_TXCW_ANE)); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after link up. */ - ret_val = - e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error config flow control\n"); - break; - } - mac->serdes_link_state = - e1000_serdes_link_forced_up; - mac->serdes_has_link = true; - e_dbg("AN_PROG -> FORCED_UP\n"); - } - break; - - case e1000_serdes_link_down: - default: - /* The link was down but the receiver has now gained - * valid sync, so lets see if we can bring the link - * up. */ - ew32(TXCW, mac->txcw); - ew32(CTRL, - (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - e_dbg("DOWN -> AN_PROG\n"); - break; - } - } else { - if (!(rxcw & E1000_RXCW_SYNCH)) { - mac->serdes_has_link = false; - mac->serdes_link_state = e1000_serdes_link_down; - e_dbg("ANYSTATE -> DOWN\n"); - } else { - /* - * We have sync, and can tolerate one - * invalid (IV) codeword before declaring - * link down, so reread to look again - */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_IV) { - mac->serdes_link_state = e1000_serdes_link_down; - mac->serdes_has_link = false; - e_dbg("ANYSTATE -> DOWN\n"); - } - } - } - - return ret_val; -} - -/** - * e1000e_valid_led_default_82571 - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -static s32 e1000e_valid_led_default_82571(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000e_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - case e1000_82573: - if(*data == ID_LED_RESERVED_F746) - *data = ID_LED_DEFAULT_82573; - break; - default: - if (*data == ID_LED_RESERVED_0000 || - *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - break; - } - -out: - return ret_val; -} - -/** - * e1000e_get_laa_state_82571 - Get locally administered address state - * @hw: pointer to the HW structure - * - * Retrieve and return the current locally administered address state. - **/ -bool e1000e_get_laa_state_82571(struct e1000_hw *hw) -{ - if (hw->mac.type != e1000_82571) - return false; - - return hw->dev_spec._82571.laa_is_present; -} - -/** - * e1000e_set_laa_state_82571 - Set locally administered address state - * @hw: pointer to the HW structure - * @state: enable/disable locally administered address - * - * Enable/Disable the current locally administered address state. - **/ -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) -{ - if (hw->mac.type != e1000_82571) - return; - - hw->dev_spec._82571.laa_is_present = state; - - /* If workaround is activated... */ - if (state) - /* - * Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed, the actual LAA is in one of the RARs and no - * incoming packets directed to this port are dropped. - * Eventually the LAA will be in RAR[0] and RAR[14]. - */ - e1000e_rar_set(hw, hw->mac.addr, - hw->mac.rar_entry_count - 1); - return; -} - -/** - * e1000e_fix_nvm_checksum_82571 - Fix EEPROM checksum - * @hw: pointer to the HW structure - * - * Verifies that the EEPROM has completed the update. After updating the - * EEPROM, we need to check bit 15 in work 0x23 for the checksum fix. If - * the checksum fix is not implemented, we need to set the bit and update - * the checksum. Otherwise, if bit 15 is set and the checksum is incorrect, - * we need to return bad checksum. - **/ -static s32 e1000e_fix_nvm_checksum_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val = E1000_SUCCESS; - u16 data; - - if (nvm->type != e1000_nvm_flash_hw) - goto out; - - /* - * Check bit 4 of word 10h. If it is 0, firmware is done updating - * 10h-12h. Checksum may need to be fixed. - */ - ret_val = e1000e_read_nvm(hw, 0x10, 1, &data); - if (ret_val) - goto out; - - if (!(data & 0x10)) { - /* - * Read 0x23 and check bit 15. This bit is a 1 - * when the checksum has already been fixed. If - * the checksum is still wrong and this bit is a - * 1, we need to return bad checksum. Otherwise, - * we need to set this bit to a 1 and update the - * checksum. - */ - ret_val = e1000e_read_nvm(hw, 0x23, 1, &data); - if (ret_val) - goto out; - - if (!(data & 0x8000)) { - data |= 0x8000; - ret_val = e1000e_write_nvm(hw, 0x23, 1, &data); - if (ret_val) - goto out; - ret_val = e1000e_update_nvm_checksum(hw); - } - } - -out: - return ret_val; -} - -/** - * e1000e_read_mac_addr_82571 - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000e_read_mac_addr_82571(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000e_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; - - ret_val = e1000e_read_mac_addr_generic(hw); - -out: - return ret_val; -} - -/** - * e1000e_power_down_phy_copper_82571 - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000e_power_down_phy_copper_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_mac_info *mac = &hw->mac; - - if (!(phy->ops.check_reset_block)) - return; - - /* If the management interface is not enabled, then power down */ - if (!(mac->ops.check_mng_mode(hw) || e1000e_check_reset_block(hw))) - e1000e_power_down_phy_copper(hw); - - return; -} - -/** - * e1000e_clear_hw_cntrs_82571 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000e_clear_hw_cntrs_82571(struct e1000_hw *hw __unused) -{ -#if 0 - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -#endif -} - -static struct pci_device_id e1000e_82571_nics[] = { - PCI_ROM(0x8086, 0x105E, "E1000_DEV_ID_82571EB_COPPER", "E1000_DEV_ID_82571EB_COPPER", board_82571), - PCI_ROM(0x8086, 0x105F, "E1000_DEV_ID_82571EB_FIBER", "E1000_DEV_ID_82571EB_FIBER", board_82571), - PCI_ROM(0x8086, 0x10A4, "E1000_DEV_ID_82571EB_QUAD_COPPER", "E1000_DEV_ID_82571EB_QUAD_COPPER", board_82571), - PCI_ROM(0x8086, 0x10BC, "E1000_DEV_ID_82571EB_QUAD_COPPER_LP", "E1000_DEV_ID_82571EB_QUAD_COPPER_LP", board_82571), - PCI_ROM(0x8086, 0x10A5, "E1000_DEV_ID_82571EB_QUAD_FIBER", "E1000_DEV_ID_82571EB_QUAD_FIBER", board_82571), - PCI_ROM(0x8086, 0x1060, "E1000_DEV_ID_82571EB_SERDES", "E1000_DEV_ID_82571EB_SERDES", board_82571), - PCI_ROM(0x8086, 0x10D9, "E1000_DEV_ID_82571EB_SERDES_DUAL", "E1000_DEV_ID_82571EB_SERDES_DUAL", board_82571), - PCI_ROM(0x8086, 0x10DA, "E1000_DEV_ID_82571EB_SERDES_QUAD", "E1000_DEV_ID_82571EB_SERDES_QUAD", board_82571), - PCI_ROM(0x8086, 0x10D5, "E1000_DEV_ID_82571PT_QUAD_COPPER", "E1000_DEV_ID_82571PT_QUAD_COPPER", board_82571), - PCI_ROM(0x8086, 0x10B9, "E1000_DEV_ID_82572EI", "E1000_DEV_ID_82572EI", board_82572), - PCI_ROM(0x8086, 0x107D, "E1000_DEV_ID_82572EI_COPPER", "E1000_DEV_ID_82572EI_COPPER", board_82572), - PCI_ROM(0x8086, 0x107E, "E1000_DEV_ID_82572EI_FIBER", "E1000_DEV_ID_82572EI_FIBER", board_82572), - PCI_ROM(0x8086, 0x107F, "E1000_DEV_ID_82572EI_SERDES", "E1000_DEV_ID_82572EI_SERDES", board_82572), - PCI_ROM(0x8086, 0x108B, "E1000_DEV_ID_82573E", "E1000_DEV_ID_82573E", board_82573), - PCI_ROM(0x8086, 0x108C, "E1000_DEV_ID_82573E_IAMT", "E1000_DEV_ID_82573E_IAMT", board_82573), - PCI_ROM(0x8086, 0x109A, "E1000_DEV_ID_82573L", "E1000_DEV_ID_82573L", board_82573), - PCI_ROM(0x8086, 0x10D3, "E1000_DEV_ID_82574L", "E1000_DEV_ID_82574L", board_82574), - PCI_ROM(0x8086, 0x10F6, "E1000_DEV_ID_82574LA", "E1000_DEV_ID_82574LA", board_82574), - PCI_ROM(0x8086, 0x150C, "E1000_DEV_ID_82583V", "E1000_DEV_ID_82583V", board_82583), -}; - -struct pci_driver e1000e_82571_driver __pci_driver = { - .ids = e1000e_82571_nics, - .id_count = (sizeof (e1000e_82571_nics) / sizeof (e1000e_82571_nics[0])), - .probe = e1000e_probe, - .remove = e1000e_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.h deleted file mode 100644 index c645e25ab..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_82571.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_82571_H_ -#define _E1000E_82571_H_ - -#define ID_LED_RESERVED_F746 0xF746 -#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_ON2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 - -/* Intr Throttling - RW */ -#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) - -#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ -#define E1000_EIAC_MASK_82574 0x01F00000 - -#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ - -#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */ - -bool e1000e_get_laa_state_82571(struct e1000_hw *hw); -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_defines.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_defines.h deleted file mode 100644 index da135d918..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_defines.h +++ /dev/null @@ -1,1469 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_DEFINES_H_ -#define _E1000E_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_PHY 0x00000800 /* Ignore WakeOn TCO packets */ -#define E1000_WUFC_FLX0_PHY 0x00001000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1_PHY 0x00002000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2_PHY 0x00004000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3_PHY 0x00008000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_FLX4_PHY 0x00000200 /* Flexible Filter 4 Enable */ -#define E1000_WUFC_FLX5_PHY 0x00000400 /* Flexible Filter 5 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_FLX4 0x00100000 /* Flexible Filter 4 Enable */ -#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ -#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/ -#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/ -#define E1000_WUFC_ALL_FILTERS_PHY_6 0x0000F6FF /*Mask for 6 wakeup filters */ -#define E1000_WUFC_FLX_FILTERS_PHY_6 0x0000F600 /*Mask for 6 flexible filters*/ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ -#define E1000_WUFC_ALL_FILTERS_6 0x003F00FF /* Mask for all 6 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 */ -#define E1000_WUFC_FLX_FILTERS_6 0x003F0000 /* Mask for 6 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_PHY E1000_WUFC_FLX0_PHY -#define E1000_WUS_FLX1_PHY E1000_WUFC_FLX1_PHY -#define E1000_WUS_FLX2_PHY E1000_WUFC_FLX2_PHY -#define E1000_WUS_FLX3_PHY E1000_WUFC_FLX3_PHY -#define E1000_WUS_FLX_FILTERS_PHY_4 E1000_WUFC_FLX_FILTERS_PHY_4 -#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_FLX4 E1000_WUFC_FLX4 -#define E1000_WUS_FLX5 E1000_WUFC_FLX5 -#define E1000_WUS_FLX4_PHY E1000_WUFC_FLX4_PHY -#define E1000_WUS_FLX5_PHY E1000_WUFC_FLX5_PHY -#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS -#define E1000_WUS_FLX_FILTERS_6 E1000_WUFC_FLX_FILTERS_6 -#define E1000_WUS_FLX_FILTERS_PHY_6 E1000_WUFC_FLX_FILTERS_PHY_6 - -/* 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 -/* Six Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX_6 6 - -/* 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_FFLT_SIZE_6 E1000_FLEXIBLE_FILTER_COUNT_MAX_6 -#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_CTRL_EXT_LSECCK 0x00001000 -#define E1000_CTRL_EXT_PHYPDEN 0x00100000 -#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 - -#define E1000_RXDEXT_LSECH 0x01000000 -#define E1000_RXDEXT_LSECE_MASK 0x60000000 -#define E1000_RXDEXT_LSECE_NO_ERROR 0x00000000 -#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000 -#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000 -#define E1000_RXDEXT_LSECE_BAD_SIG 0x60000000 - -/* 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_PHY_LED0_MODE_MASK 0x00000007 -#define E1000_PHY_LED0_IVRT 0x00000008 -#define E1000_PHY_LED0_BLINK 0x00000010 -#define E1000_PHY_LED0_MASK 0x0000001F - -#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 */ -#define E1000_TXD_CMD_LINKSEC 0x10000000 /* Apply LinkSec on packet */ -#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ - -/* 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 */ -#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ -#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ -#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ -#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ -#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ - -/* PBA ECC Register */ -#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ -#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */ -#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */ -#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ -#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */ - -/* - * 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 -#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ -#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ -#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ -#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ -#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ - -/* 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 BME1000_E_PHY_ID 0x01410CB0 -#define BME1000_E_PHY_ID_R2 0x01410CB1 -#define I82577_E_PHY_ID 0x01540050 -#define I82578_E_PHY_ID 0x004DD040 -#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 - -#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 -#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C - -/* BME1000 PHY Specific Control Register */ -#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ - -/* - * 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 /* _E1000E_DEFINES_H_ */ diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_hw.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_hw.h deleted file mode 100644 index 03ed35c92..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_hw.h +++ /dev/null @@ -1,719 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_HW_H_ -#define _E1000E_HW_H_ - -#include "e1000e_regs.h" -#include "e1000e_defines.h" - -struct e1000_hw; - -#define E1000_DEV_ID_82571EB_COPPER 0x105E -#define E1000_DEV_ID_82571EB_FIBER 0x105F -#define E1000_DEV_ID_82571EB_SERDES 0x1060 -#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 -#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA -#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 -#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 -#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 -#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC -#define E1000_DEV_ID_82572EI_COPPER 0x107D -#define E1000_DEV_ID_82572EI_FIBER 0x107E -#define E1000_DEV_ID_82572EI_SERDES 0x107F -#define E1000_DEV_ID_82572EI 0x10B9 -#define E1000_DEV_ID_82573E 0x108B -#define E1000_DEV_ID_82573E_IAMT 0x108C -#define E1000_DEV_ID_82573L 0x109A -#define E1000_DEV_ID_82574L 0x10D3 -#define E1000_DEV_ID_82574LA 0x10F6 -#define E1000_DEV_ID_82583V 0x150C -#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 -#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 -#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA -#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB -#define E1000_DEV_ID_ICH8_82567V_3 0x1501 -#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 -#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A -#define E1000_DEV_ID_ICH8_IGP_C 0x104B -#define E1000_DEV_ID_ICH8_IFE 0x104C -#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 -#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 -#define E1000_DEV_ID_ICH8_IGP_M 0x104D -#define E1000_DEV_ID_ICH9_IGP_M 0x10BF -#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 -#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB -#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD -#define E1000_DEV_ID_ICH9_BM 0x10E5 -#define E1000_DEV_ID_ICH9_IGP_C 0x294C -#define E1000_DEV_ID_ICH9_IFE 0x10C0 -#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 -#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 -#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC -#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD -#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE -#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE -#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF -#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA -#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB -#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF -#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 -#define E1000_REVISION_0 0 -#define E1000_REVISION_1 1 -#define E1000_REVISION_2 2 -#define E1000_REVISION_3 3 -#define E1000_REVISION_4 4 - -#define E1000_FUNC_0 0 -#define E1000_FUNC_1 1 - -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 - -enum e1000_mac_type { - e1000_undefined = 0, - e1000_82571, - e1000_82572, - e1000_82573, - e1000_82574, - e1000_82583, - e1000_80003es2lan, - e1000_ich8lan, - e1000_ich9lan, - e1000_ich10lan, - e1000_pchlan, - e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ -}; - -enum e1000_media_type { - e1000_media_type_unknown = 0, - e1000_media_type_copper = 1, - e1000_media_type_fiber = 2, - e1000_media_type_internal_serdes = 3, - e1000_num_media_types -}; - -enum e1000_nvm_type { - e1000_nvm_unknown = 0, - e1000_nvm_none, - e1000_nvm_eeprom_spi, - e1000_nvm_flash_hw, - e1000_nvm_flash_sw -}; - -enum e1000_nvm_override { - e1000_nvm_override_none = 0, - e1000_nvm_override_spi_small, - e1000_nvm_override_spi_large, -}; - -enum e1000_phy_type { - e1000_phy_unknown = 0, - e1000_phy_none, - e1000_phy_m88, - e1000_phy_igp, - e1000_phy_igp_2, - e1000_phy_gg82563, - e1000_phy_igp_3, - e1000_phy_ife, - e1000_phy_bm, - e1000_phy_82578, - e1000_phy_82577, -}; - -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 -}; - -enum e1000_1000t_rx_status { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -}; - -enum e1000_rev_polarity { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -}; - -enum e1000_fc_mode { - e1000_fc_none = 0, - e1000_fc_rx_pause, - e1000_fc_tx_pause, - e1000_fc_full, - e1000_fc_default = 0xFF -}; - -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - -enum e1000_serdes_link_state { - e1000_serdes_link_down = 0, - e1000_serdes_link_autoneg_progress, - e1000_serdes_link_autoneg_complete, - e1000_serdes_link_forced_up -}; - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorc; - u64 gotc; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 tor; - u64 tot; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; - u64 doosync; -}; - - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; - -/* Host Interface "Rev 1" */ -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; - u8 checksum; -}; - -#define E1000_HI_MAX_DATA_LENGTH 252 -struct e1000_host_command_info { - struct e1000_host_command_header command_header; - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -}; - -/* Host Interface "Rev 2" */ -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -}; - -#include "e1000e_mac.h" -#include "e1000e_phy.h" -#include "e1000e_nvm.h" -#include "e1000e_manage.h" - -struct e1000_mac_operations { - /* Function pointers for the MAC. */ - s32 (*init_params)(struct e1000_hw *); - s32 (*id_led_init)(struct e1000_hw *); - s32 (*blink_led)(struct e1000_hw *); - s32 (*check_for_link)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *hw); - s32 (*cleanup_led)(struct e1000_hw *); - void (*clear_hw_cntrs)(struct e1000_hw *); - void (*clear_vfta)(struct e1000_hw *); - s32 (*get_bus_info)(struct e1000_hw *); - void (*set_lan_id)(struct e1000_hw *); - s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); - s32 (*led_on)(struct e1000_hw *); - s32 (*led_off)(struct e1000_hw *); - 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 *); - s32 (*setup_physical_interface)(struct e1000_hw *); - s32 (*setup_led)(struct e1000_hw *); - void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*mta_set)(struct e1000_hw *, u32); - void (*config_collision_dist)(struct e1000_hw *); - void (*rar_set)(struct e1000_hw *, u8*, u32); - s32 (*read_mac_addr)(struct e1000_hw *); - s32 (*validate_mdi_setting)(struct e1000_hw *); - s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); - s32 (*mng_write_cmd_header)(struct e1000_hw *hw, - struct e1000_host_mng_command_header*); - s32 (*mng_enable_host_if)(struct e1000_hw *); - s32 (*wait_autoneg)(struct e1000_hw *); -}; - -struct e1000_phy_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*cfg_on_link_up)(struct e1000_hw *); - s32 (*check_polarity)(struct e1000_hw *); - s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit)(struct e1000_hw *); -#if 0 - s32 (*force_speed_duplex)(struct e1000_hw *); -#endif - s32 (*get_cfg_done)(struct e1000_hw *hw); -#if 0 - s32 (*get_cable_length)(struct e1000_hw *); -#endif - s32 (*get_info)(struct e1000_hw *); - s32 (*read_reg)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); - void (*release)(struct e1000_hw *); - s32 (*reset)(struct e1000_hw *); - s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); - s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_reg)(struct e1000_hw *, u32, u16); - s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); - void (*power_up)(struct e1000_hw *); - void (*power_down)(struct e1000_hw *); -}; - -struct e1000_nvm_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*read)(struct e1000_hw *, u16, u16, u16 *); - void (*release)(struct e1000_hw *); - void (*reload)(struct e1000_hw *); - s32 (*update)(struct e1000_hw *); - s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate)(struct e1000_hw *); - s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -}; - -struct e1000_mac_info { - struct e1000_mac_operations ops; - u8 addr[6]; - u8 perm_addr[6]; - - enum e1000_mac_type type; - - u32 collision_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - u32 mc_filter_type; - u32 tx_packet_delta; - u32 txcw; - - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; - u16 mta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ - #define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; - u16 rar_entry_count; - - u8 forced_speed_duplex; - - bool adaptive_ifs; - bool arc_subsystem_valid; - bool asf_firmware_present; - bool autoneg; - bool autoneg_failed; - bool get_link_status; - bool in_ifs_mode; - enum e1000_serdes_link_state serdes_link_state; - bool serdes_has_link; - bool tx_pkt_filtering; -}; - -struct e1000_phy_info { - struct e1000_phy_operations ops; - enum e1000_phy_type type; - - enum e1000_1000t_rx_status local_rx; - enum e1000_1000t_rx_status remote_rx; - enum e1000_ms_type ms_type; - enum e1000_ms_type original_ms_type; - enum e1000_rev_polarity cable_polarity; - enum e1000_smart_speed smart_speed; - - u32 addr; - u32 id; - u32 reset_delay_us; /* in usec */ - u32 revision; - - enum e1000_media_type media_type; - - u16 autoneg_advertised; - u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - - u8 mdix; - - bool disable_polarity_correction; - bool is_mdix; - bool polarity_correction; - bool reset_disable; - bool speed_downgraded; - bool autoneg_wait_to_complete; -}; - -struct e1000_nvm_info { - struct e1000_nvm_operations ops; - enum e1000_nvm_type type; - enum e1000_nvm_override override; - - u32 flash_bank_size; - u32 flash_base_addr; - - u16 word_size; - u16 delay_usec; - u16 address_bits; - u16 opcode_bits; - u16 page_size; -}; - -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_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* FC mode in effect */ - enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ -}; - -struct e1000_dev_spec_82571 { - bool laa_is_present; - u32 smb_counter; -}; - -struct e1000_dev_spec_80003es2lan { - bool mdic_wa_enable; -}; - -struct e1000_shadow_ram { - u16 value; - bool modified; -}; - -#define E1000_ICH8_SHADOW_RAM_WORDS 2048 - -struct e1000_dev_spec_ich8lan { - bool kmrn_lock_loss_workaround_enabled; - struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; - bool nvm_k1_enabled; -}; - -struct e1000_hw { - struct e1000_adapter *adapter; - - u8 __iomem *hw_addr; - u8 __iomem *flash_address; - - void *back; - unsigned long io_base; - - struct e1000_mac_info mac; - struct e1000_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; - struct e1000_host_mng_dhcp_cookie mng_cookie; - - union { - struct e1000_dev_spec_82571 _82571; - struct e1000_dev_spec_80003es2lan _80003es2lan; - struct e1000_dev_spec_ich8lan ich8lan; - } dev_spec; - - u16 device_id; - u16 subsystem_vendor_id; - u16 subsystem_device_id; - u16 vendor_id; - - u8 revision_id; -}; - -#include "e1000e_82571.h" -#include "e1000e_80003es2lan.h" -#include "e1000e_ich8lan.h" - -/* These functions must be implemented by drivers */ -s32 e1000e_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.c deleted file mode 100644 index 7b9a49b98..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.c +++ /dev/null @@ -1,3444 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * 82562G 10/100 Network Connection - * 82562G-2 10/100 Network Connection - * 82562GT 10/100 Network Connection - * 82562GT-2 10/100 Network Connection - * 82562V 10/100 Network Connection - * 82562V-2 10/100 Network Connection - * 82566DC-2 Gigabit Network Connection - * 82566DC Gigabit Network Connection - * 82566DM-2 Gigabit Network Connection - * 82566DM Gigabit Network Connection - * 82566MC Gigabit Network Connection - * 82566MM Gigabit Network Connection - * 82567LM Gigabit Network Connection - * 82567LF Gigabit Network Connection - * 82567V Gigabit Network Connection - * 82567LM-2 Gigabit Network Connection - * 82567LF-2 Gigabit Network Connection - * 82567V-2 Gigabit Network Connection - * 82567LF-3 Gigabit Network Connection - * 82567LM-3 Gigabit Network Connection - * 82567LM-4 Gigabit Network Connection - * 82577LM Gigabit Network Connection - * 82577LC Gigabit Network Connection - * 82578DM Gigabit Network Connection - * 82578DC Gigabit Network Connection - */ - -#include "e1000e.h" - -static s32 e1000e_init_phy_params_ich8lan(struct e1000_hw *hw); -static s32 e1000e_init_phy_params_pchlan(struct e1000_hw *hw); -static s32 e1000e_init_nvm_params_ich8lan(struct e1000_hw *hw); -static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw); -static s32 e1000e_acquire_swflag_ich8lan(struct e1000_hw *hw); -static void e1000e_release_swflag_ich8lan(struct e1000_hw *hw); -static s32 e1000e_acquire_nvm_ich8lan(struct e1000_hw *hw); -static void e1000e_release_nvm_ich8lan(struct e1000_hw *hw); -static bool e1000e_check_mng_mode_ich8lan(struct e1000_hw *hw); -static s32 e1000e_check_reset_block_ich8lan(struct e1000_hw *hw); -static s32 e1000e_phy_hw_reset_ich8lan(struct e1000_hw *hw); -static s32 e1000e_get_phy_info_ich8lan(struct e1000_hw *hw); -static s32 e1000e_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); -static s32 e1000e_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, - bool active); -static s32 e1000e_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, - bool active); -static s32 e1000e_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000e_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000e_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); -static s32 e1000e_update_nvm_checksum_ich8lan(struct e1000_hw *hw); -static s32 e1000e_valid_led_default_ich8lan(struct e1000_hw *hw, - u16 *data); -static s32 e1000e_id_led_init_pchlan(struct e1000_hw *hw); -static s32 e1000e_get_bus_info_ich8lan(struct e1000_hw *hw); -static s32 e1000e_reset_hw_ich8lan(struct e1000_hw *hw); -static s32 e1000e_init_hw_ich8lan(struct e1000_hw *hw); -static s32 e1000e_setup_link_ich8lan(struct e1000_hw *hw); -static s32 e1000e_setup_copper_link_ich8lan(struct e1000_hw *hw); -static s32 e1000e_get_link_up_info_ich8lan(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -static s32 e1000e_cleanup_led_ich8lan(struct e1000_hw *hw); -static s32 e1000e_led_on_ich8lan(struct e1000_hw *hw); -static s32 e1000e_led_off_ich8lan(struct e1000_hw *hw); -static s32 e1000e_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); -static s32 e1000e_setup_led_pchlan(struct e1000_hw *hw); -static s32 e1000e_cleanup_led_pchlan(struct e1000_hw *hw); -static s32 e1000e_led_on_pchlan(struct e1000_hw *hw); -static s32 e1000e_led_off_pchlan(struct e1000_hw *hw); -static void e1000e_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); -static s32 e1000e_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); -static s32 e1000e_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); -static s32 e1000e_flash_cycle_init_ich8lan(struct e1000_hw *hw); -static s32 e1000e_get_phy_info_ife_ich8lan(struct e1000_hw *hw); -static void e1000e_initialize_hw_bits_ich8lan(struct e1000_hw *hw); -static s32 e1000e_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); -static s32 e1000e_read_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 *data); -static s32 e1000e_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data); -static s32 e1000e_read_flash_word_ich8lan(struct e1000_hw *hw, - u32 offset, u16 *data); -static s32 e1000e_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte); -static s32 e1000e_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 data); -static s32 e1000e_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 data); -static s32 e1000e_get_cfg_done_ich8lan(struct e1000_hw *hw); -static void e1000e_power_down_phy_copper_ich8lan(struct e1000_hw *hw); -static s32 e1000e_check_for_copper_link_ich8lan(struct e1000_hw *hw); -static void e1000e_lan_init_done_ich8lan(struct e1000_hw *hw); -static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw); - -/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ -/* Offset 04h HSFSTS */ -union ich8_hws_flash_status { - struct ich8_hsfsts { - u16 flcdone :1; /* bit 0 Flash Cycle Done */ - u16 flcerr :1; /* bit 1 Flash Cycle Error */ - u16 dael :1; /* bit 2 Direct Access error Log */ - u16 berasesz :2; /* bit 4:3 Sector Erase Size */ - u16 flcinprog :1; /* bit 5 flash cycle in Progress */ - u16 reserved1 :2; /* bit 13:6 Reserved */ - u16 reserved2 :6; /* bit 13:6 Reserved */ - u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ - u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ - } hsf_status; - u16 regval; -}; - -/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ -/* Offset 06h FLCTL */ -union ich8_hws_flash_ctrl { - struct ich8_hsflctl { - u16 flcgo :1; /* 0 Flash Cycle Go */ - u16 flcycle :2; /* 2:1 Flash Cycle */ - u16 reserved :5; /* 7:3 Reserved */ - u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ - u16 flockdn :6; /* 15:10 Reserved */ - } hsf_ctrl; - u16 regval; -}; - -/* ICH Flash Region Access Permissions */ -union ich8_hws_flash_regacc { - struct ich8_flracc { - u32 grra :8; /* 0:7 GbE region Read Access */ - u32 grwa :8; /* 8:15 GbE region Write Access */ - u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ - u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ - } hsf_flregacc; - u16 regval; -}; - -/** - * e1000e_init_phy_params_pchlan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000e_init_phy_params_pchlan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.acquire = e1000e_acquire_swflag_ich8lan; - phy->ops.check_polarity = e1000e_check_polarity_ife; - phy->ops.check_reset_block = e1000e_check_reset_block_ich8lan; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_ife; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; -#endif - phy->ops.get_cfg_done = e1000e_get_cfg_done_ich8lan; - phy->ops.get_info = e1000e_get_phy_info_ich8lan; - phy->ops.read_reg = e1000e_read_phy_reg_hv; - phy->ops.read_reg_locked = e1000e_read_phy_reg_hv_locked; - phy->ops.release = e1000e_release_swflag_ich8lan; - phy->ops.reset = e1000e_phy_hw_reset_ich8lan; - phy->ops.set_d0_lplu_state = e1000e_set_lplu_state_pchlan; - phy->ops.set_d3_lplu_state = e1000e_set_lplu_state_pchlan; - phy->ops.write_reg = e1000e_write_phy_reg_hv; - phy->ops.write_reg_locked = e1000e_write_phy_reg_hv_locked; - phy->ops.power_up = e1000e_power_up_phy_copper; - phy->ops.power_down = e1000e_power_down_phy_copper_ich8lan; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - phy->id = e1000_phy_unknown; - e1000e_get_phy_id(hw); - phy->type = e1000e_get_phy_type_from_id(phy->id); - - if (phy->type == e1000_phy_82577) { - phy->ops.check_polarity = e1000e_check_polarity_82577; -#if 0 - phy->ops.force_speed_duplex = - e1000e_phy_force_speed_duplex_82577; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_82577; -#endif - phy->ops.get_info = e1000e_get_phy_info_82577; - phy->ops.commit = e1000e_phy_sw_reset; - } - - return ret_val; -} - -/** - * e1000e_init_phy_params_ich8lan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000e_init_phy_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 i = 0; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.acquire = e1000e_acquire_swflag_ich8lan; - phy->ops.check_polarity = e1000e_check_polarity_ife; - phy->ops.check_reset_block = e1000e_check_reset_block_ich8lan; -#if 0 - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_ife; -#endif -#if 0 - phy->ops.get_cable_length = e1000e_get_cable_length_igp_2; -#endif - phy->ops.get_cfg_done = e1000e_get_cfg_done_ich8lan; - phy->ops.get_info = e1000e_get_phy_info_ich8lan; - phy->ops.read_reg = e1000e_read_phy_reg_igp; - phy->ops.release = e1000e_release_swflag_ich8lan; - phy->ops.reset = e1000e_phy_hw_reset_ich8lan; - phy->ops.set_d0_lplu_state = e1000e_set_d0_lplu_state_ich8lan; - phy->ops.set_d3_lplu_state = e1000e_set_d3_lplu_state_ich8lan; - phy->ops.write_reg = e1000e_write_phy_reg_igp; - phy->ops.power_up = e1000e_power_up_phy_copper; - phy->ops.power_down = e1000e_power_down_phy_copper_ich8lan; - - /* - * We may need to do this twice - once for IGP and if that fails, - * we'll set BM func pointers and try again - */ - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - DBG("Cannot determine PHY addr. Erroring out\n"); - goto out; - } - } - - phy->id = 0; - while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) && - (i++ < 100)) { - msleep(1); - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - goto out; - } - - /* Verify phy id */ - switch (phy->id) { - case IGP03E1000_E_PHY_ID: - phy->type = e1000_phy_igp_3; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg_locked = e1000e_read_phy_reg_igp_locked; - phy->ops.write_reg_locked = e1000e_write_phy_reg_igp_locked; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy->type = e1000_phy_ife; - phy->autoneg_mask = E1000_ALL_NOT_GIG; - break; - case BME1000_E_PHY_ID: - phy->type = e1000_phy_bm; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.commit = e1000e_phy_sw_reset; - break; - default: - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_init_nvm_params_ich8lan - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific NVM parameters and function - * pointers. - **/ -static s32 e1000e_init_nvm_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 gfpreg, sector_base_addr, sector_end_addr; - s32 ret_val = E1000_SUCCESS; - u16 i; - - /* Can't read flash registers if the register set isn't mapped. */ - if (!hw->flash_address) { - e_dbg("ERROR: Flash registers not mapped\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - nvm->type = e1000_nvm_flash_sw; - - gfpreg = er32flash(ICH_FLASH_GFPREG); - - /* - * sector_X_addr is a "sector"-aligned address (4096 bytes) - * Add 1 to sector_end_addr since this sector is included in - * the overall size. - */ - sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; - sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; - - /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; - - /* - * find total size of the NVM, then cut in half since the total - * size represents two separate NVM banks. - */ - nvm->flash_bank_size = (sector_end_addr - sector_base_addr) - << FLASH_SECTOR_ADDR_SHIFT; - nvm->flash_bank_size /= 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - - nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; - - /* Clear shadow ram */ - for (i = 0; i < nvm->word_size; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - - /* Function Pointers */ - nvm->ops.acquire = e1000e_acquire_nvm_ich8lan; - nvm->ops.release = e1000e_release_nvm_ich8lan; - nvm->ops.read = e1000e_read_nvm_ich8lan; - nvm->ops.update = e1000e_update_nvm_checksum_ich8lan; - nvm->ops.valid_led_default = e1000e_valid_led_default_ich8lan; - nvm->ops.validate = e1000e_validate_nvm_checksum_ich8lan; - nvm->ops.write = e1000e_write_nvm_ich8lan; - -out: - return ret_val; -} - -/** - * e1000e_init_mac_params_ich8lan - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific MAC parameters and function - * pointers. - **/ -static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - /* Set media type function pointer */ - hw->phy.media_type = e1000_media_type_copper; - - /* Set mta register count */ - mac->mta_reg_count = 32; - /* Set rar entry count */ - mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; - if (mac->type == e1000_ich8lan) - mac->rar_entry_count--; - /* Set if part includes ASF firmware */ - mac->asf_firmware_present = true; - /* Set if manageability features are enabled. */ - mac->arc_subsystem_valid = true; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = e1000e_get_bus_info_ich8lan; - /* function id */ - mac->ops.set_lan_id = e1000e_set_lan_id_single_port; - /* reset */ - mac->ops.reset_hw = e1000e_reset_hw_ich8lan; - /* hw initialization */ - mac->ops.init_hw = e1000e_init_hw_ich8lan; - /* link setup */ - mac->ops.setup_link = e1000e_setup_link_ich8lan; - /* physical interface setup */ - mac->ops.setup_physical_interface = e1000e_setup_copper_link_ich8lan; - /* check for link */ - mac->ops.check_for_link = e1000e_check_for_copper_link_ich8lan; - /* check management mode */ - mac->ops.check_mng_mode = e1000e_check_mng_mode_ich8lan; - /* link info */ - mac->ops.get_link_up_info = e1000e_get_link_up_info_ich8lan; - /* multicast address update */ - mac->ops.update_mc_addr_list = e1000e_update_mc_addr_list_generic; - /* setting MTA */ - mac->ops.mta_set = e1000e_mta_set_generic; - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = e1000e_clear_hw_cntrs_ich8lan; - - /* LED operations */ - switch (mac->type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init; - /* blink LED */ - mac->ops.blink_led = e1000e_blink_led; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000e_cleanup_led_ich8lan; - /* turn on/off LED */ - mac->ops.led_on = e1000e_led_on_ich8lan; - mac->ops.led_off = e1000e_led_off_ich8lan; - break; - case e1000_pchlan: - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init_pchlan; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_pchlan; - /* cleanup LED */ - mac->ops.cleanup_led = e1000e_cleanup_led_pchlan; - /* turn on/off LED */ - mac->ops.led_on = e1000e_led_on_pchlan; - mac->ops.led_off = e1000e_led_off_pchlan; - break; - default: - break; - } - - /* Enable PCS Lock-loss workaround for ICH8 */ - if (mac->type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - - - return E1000_SUCCESS; -} - -/** - * e1000e_check_for_copper_link_ich8lan - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -static s32 e1000e_check_for_copper_link_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - /* - * We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000e_k1_gig_workaround_hv(hw, link); - if (ret_val) - goto out; - } - - if (!link) - goto out; /* No link detected */ - - mac->get_link_status = false; - - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1000e_link_stall_workaround_hv(hw); - if (ret_val) - goto out; - } - - /* - * Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* - * If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - e1000e_config_collision_dist(hw); - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) - e_dbg("Error configuring flow control\n"); - -out: - return ret_val; -} - -/** - * e1000e_init_function_pointers_ich8lan - Initialize ICH8 function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific function pointers for PHY, MAC, and NVM. - **/ -void e1000e_init_function_pointers_ich8lan(struct e1000_hw *hw) -{ - e1000e_init_mac_ops_generic(hw); - e1000e_init_nvm_ops_generic(hw); - hw->mac.ops.init_params = e1000e_init_mac_params_ich8lan; - hw->nvm.ops.init_params = e1000e_init_nvm_params_ich8lan; - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - hw->phy.ops.init_params = e1000e_init_phy_params_ich8lan; - break; - case e1000_pchlan: - hw->phy.ops.init_params = e1000e_init_phy_params_pchlan; - break; - default: - break; - } -} - -#if 0 -static DEFINE_MUTEX(nvm_mutex); -#endif - -/** - * e1000e_acquire_nvm_ich8lan - Acquire NVM mutex - * @hw: pointer to the HW structure - * - * Acquires the mutex for performing NVM operations. - **/ -static s32 e1000e_acquire_nvm_ich8lan(struct e1000_hw *hw __unused) -{ -#if 0 - mutex_lock(&nvm_mutex); -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_release_nvm_ich8lan - Release NVM mutex - * @hw: pointer to the HW structure - * - * Releases the mutex used while performing NVM operations. - **/ -static void e1000e_release_nvm_ich8lan(struct e1000_hw *hw __unused) -{ -#if 0 - mutex_unlock(&nvm_mutex); -#endif - return; -} - -#if 0 -static DEFINE_MUTEX(swflag_mutex); -#endif - -/** - * e1000e_acquire_swflag_ich8lan - Acquire software control flag - * @hw: pointer to the HW structure - * - * Acquires the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static s32 e1000e_acquire_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - -#if 0 - mutex_lock(&swflag_mutex); -#endif - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("SW/FW/HW has locked the resource for too long.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - timeout = SW_FLAG_TIMEOUT; - - extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("Failed to acquire the semaphore.\n"); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: -#if 0 - if (ret_val) - mutex_unlock(&swflag_mutex); -#endif - return ret_val; -} - -/** - * e1000e_release_swflag_ich8lan - Release software control flag - * @hw: pointer to the HW structure - * - * Releases the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static void e1000e_release_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - - extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - -#if 0 - mutex_unlock(&swflag_mutex); -#endif - return; -} - -/** - * e1000e_check_mng_mode_ich8lan - Checks management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has manageability enabled. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. - **/ -static bool e1000e_check_mng_mode_ich8lan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} -/** - * e1000e_check_reset_block_ich8lan - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Checks if firmware is blocking the reset of the PHY. - * This is a function pointer entry point only called by - * reset routines. - **/ -static s32 e1000e_check_reset_block_ich8lan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS - : E1000_BLK_PHY_RESET; -} - -/** - * e1000e_sw_lcd_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * - * SW should configure the LCD from the NVM extended configuration region - * as a workaround for certain parts. - **/ -static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val; - u16 word_addr, reg_data, reg_addr, phy_page = 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* - * Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) || - (hw->mac.type == e1000_pchlan)) { - /* Check if SW needs to configure the PHY */ - if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) || - (hw->device_id == E1000_DEV_ID_ICH8_IGP_M) || - (hw->mac.type == e1000_pchlan)) - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - else - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - goto out; - - /* Wait for basic configuration completes before proceeding */ - e1000e_lan_init_done_ich8lan(hw); - - /* - * Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - goto out; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - goto out; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - (hw->mac.type == e1000_pchlan)) { - /* - * HW configures the SMBus address and LEDs when the - * OEM and LCD Write Enable bits are set in the NVM. - * When both NVM bits are cleared, SW will configure - * them instead. - */ - data = er32(STRAP); - data &= E1000_STRAP_SMBUS_ADDRESS_MASK; - reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; - reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000e_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, - reg_data); - if (ret_val) - goto out; - - data = er32(LEDCTL); - ret_val = e1000e_write_phy_reg_hv_locked(hw, - HV_LED_CONFIG, - (u16)data); - if (ret_val) - goto out; - } - - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000e_read_nvm(hw, (word_addr + i * 2), 1, - ®_data); - if (ret_val) - goto out; - - ret_val = e1000e_read_nvm(hw, (word_addr + i * 2 + 1), - 1, ®_addr); - if (ret_val) - goto out; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } - - reg_addr &= PHY_REG_MASK; - reg_addr |= phy_page; - - ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr, - reg_data); - if (ret_val) - goto out; - } - } - -out: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_k1_gig_workaround_hv - K1 Si workaround - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * If K1 is enabled for 1Gbps, the MAC might stall when transitioning - * from a lower speed. This workaround disables K1 whenever link is at 1Gig - * If link is down, the function will restore the default K1 setting located - * in the NVM. - **/ -static s32 e1000e_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) -{ - s32 ret_val = E1000_SUCCESS; - u16 status_reg = 0; - bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; - - if (hw->mac.type != e1000_pchlan) - goto out; - - /* Wrap the whole flow with the sw flag */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ - if (link) { - if (hw->phy.type == e1000_phy_82578) { - ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK; - - if (status_reg == (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - k1_enable = false; - } - - if (hw->phy.type == e1000_phy_82577) { - ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_MASK; - - if (status_reg == (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_1000)) - k1_enable = false; - } - - /* Link stall fix for link up */ - ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), - 0x0100); - if (ret_val) - goto release; - - } else { - /* Link stall fix for link down */ - ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), - 0x4100); - if (ret_val) - goto release; - } - - ret_val = e1000e_configure_k1_ich8lan(hw, k1_enable); - -release: - hw->phy.ops.release(hw); -out: - return ret_val; -} - -/** - * e1000e_configure_k1_ich8lan - Configure K1 power state - * @hw: pointer to the HW structure - * @enable: K1 state to configure - * - * Configure the K1 power state based on the provided parameter. - * Assumes semaphore already acquired. - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - **/ -s32 e1000e_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) -{ - s32 ret_val = E1000_SUCCESS; - u32 ctrl_reg = 0; - u32 ctrl_ext = 0; - u32 reg = 0; - u16 kmrn_reg = 0; - - ret_val = e1000e_read_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - &kmrn_reg); - if (ret_val) - goto out; - - if (k1_enable) - kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; - else - kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; - - ret_val = e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg); - if (ret_val) - goto out; - - udelay(20); - ctrl_ext = er32(CTRL_EXT); - ctrl_reg = er32(CTRL); - - reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - reg |= E1000_CTRL_FRCSPD; - ew32(CTRL, reg); - - E1000_WRITE_REG(hw, - E1000_CTRL_EXT, - ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); - udelay(20); - ew32(CTRL, ctrl_reg); - ew32(CTRL_EXT, ctrl_ext); - udelay(20); - -out: - return ret_val; -} - -/** - * e1000e_oem_bits_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * @d0_state: boolean if entering d0 or d3 device state - * - * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are - * collectively called OEM bits. The OEM Write Enable bit and SW Config bit - * in NVM determines whether HW should configure LPLU and Gbe Disable. - **/ -s32 e1000e_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) -{ - s32 ret_val = 0; - u32 mac_reg; - u16 oem_reg; - - if (hw->mac.type != e1000_pchlan) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - mac_reg = er32(EXTCNF_CTRL); - if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto out; - - mac_reg = er32(FEXTNVM); - if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) - goto out; - - mac_reg = er32(PHY_CTRL); - - ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - goto out; - - oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); - - if (d0_state) { - if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } else { - if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } - /* Restart auto-neg to activate the bits */ - if (!e1000e_check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; - ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); - -out: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be - * done after every PHY reset. - **/ -static s32 e1000e_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->mac.type != e1000_pchlan) - goto out; - - if (((hw->phy.type == e1000_phy_82577) && - ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || - ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { - /* Disable generation of early preamble */ - ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431); - if (ret_val) - goto out; - - /* Preamble tuning for SSC */ - ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204); - if (ret_val) - goto out; - } - - if (hw->phy.type == e1000_phy_82578) { - /* - * Return registers to default by doing a soft reset then - * writing 0x3140 to the control register. - */ - if (hw->phy.revision < 2) { - e1000e_phy_sw_reset(hw); - ret_val = e1e_wphy(hw, PHY_CONTROL, - 0x3140); - } - } - - /* Select page 0 */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); - if (ret_val) - goto out; - hw->phy.ops.release(hw); - - /* - * Configure the K1 Si workaround during phy reset assuming there is - * link so that it disables K1 if link is in 1Gbps. - */ - ret_val = e1000e_k1_gig_workaround_hv(hw, true); - -out: - return ret_val; -} - -/** - * e1000e_lan_init_done_ich8lan - Check for PHY config completion - * @hw: pointer to the HW structure - * - * Check the appropriate indication the MAC has finished configuring the - * PHY after a software reset. - **/ -static void e1000e_lan_init_done_ich8lan(struct e1000_hw *hw) -{ - u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; - - /* Wait for basic configuration completes before proceeding */ - do { - data = er32(STATUS); - data &= E1000_STATUS_LAN_INIT_DONE; - udelay(100); - } while ((!data) && --loop); - - /* - * If basic configuration is incomplete before the above loop - * count reaches 0, loading the configuration from NVM will - * leave the PHY in a bad state possibly resulting in no link. - */ - if (loop == 0) - e_dbg("LAN_INIT_DONE not set, increase timeout\n"); - - /* Clear the Init Done bit for the next init event */ - data = er32(STATUS); - data &= ~E1000_STATUS_LAN_INIT_DONE; - ew32(STATUS, data); -} - -/** - * e1000e_phy_hw_reset_ich8lan - Performs a PHY reset - * @hw: pointer to the HW structure - * - * Resets the PHY - * This is a function pointer entry point called by drivers - * or other shared routines. - **/ -static s32 e1000e_phy_hw_reset_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 reg; - - ret_val = e1000e_phy_hw_reset_generic(hw); - if (ret_val) - goto out; - - /* Allow time for h/w to get to a quiescent state after reset */ - msleep(10); - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000e_hv_phy_workarounds_ich8lan(hw); - if (ret_val) - goto out; - } - - /* Dummy read to clear the phy wakeup bit after lcd reset */ - if (hw->mac.type == e1000_pchlan) - e1e_rphy(hw, BM_WUC, ®); - - /* Configure the LCD with the extended configuration region in NVM */ - ret_val = e1000e_sw_lcd_config_ich8lan(hw); - if (ret_val) - goto out; - - /* Configure the LCD with the OEM bits in NVM */ - if (hw->mac.type == e1000_pchlan) - ret_val = e1000e_oem_bits_config_ich8lan(hw, true); - -out: - return ret_val; -} - -/** - * e1000e_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info - * @hw: pointer to the HW structure - * - * Wrapper for calling the get_phy_info routines for the appropriate phy type. - **/ -static s32 e1000e_get_phy_info_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = -E1000_ERR_PHY_TYPE; - - switch (hw->phy.type) { - case e1000_phy_ife: - ret_val = e1000e_get_phy_info_ife_ich8lan(hw); - break; - case e1000_phy_igp_3: - case e1000_phy_bm: - case e1000_phy_82578: - case e1000_phy_82577: - ret_val = e1000e_get_phy_info_igp(hw); - break; - default: - break; - } - - return ret_val; -} - -/** - * e1000e_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states - * @hw: pointer to the HW structure - * - * Populates "phy" structure with various feature states. - * This function is only called by other family-specific - * routines. - **/ -static s32 e1000e_get_phy_info_ife_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); - if (ret_val) - goto out; - phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE) - ? false : true; - - if (phy->polarity_correction) { - ret_val = e1000e_check_polarity_ife(hw); - if (ret_val) - goto out; - } else { - /* Polarity is forced */ - phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - } - - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - goto out; - - phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false; - - /* The following parameters are undefined for 10/100 operation. */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - -out: - return ret_val; -} - -/** - * e1000e_set_lplu_state_pchlan - Set Low Power Link Up state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU state according to the active flag. For PCH, if OEM write - * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set - * the phy speed. This function will manually set the LPLU bit and restart - * auto-neg as hw would do. D3 and D0 LPLU will call the same function - * since it configures the same bit. - **/ -static s32 e1000e_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) -{ - s32 ret_val = E1000_SUCCESS; - u16 oem_reg; - - ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - goto out; - - if (active) - oem_reg |= HV_OEM_BITS_LPLU; - else - oem_reg &= ~HV_OEM_BITS_LPLU; - - oem_reg |= HV_OEM_BITS_RESTART_AN; - ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg); - -out: - return ret_val; -} - -/** - * e1000e_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000e_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = E1000_SUCCESS; - u16 data; - - if (phy->type == e1000_phy_ife) - goto out; - - phy_ctrl = er32(PHY_CTRL); - - if (active) { - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - goto out; - - /* - * Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else { - phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - goto out; - - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000e_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D3 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000e_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = E1000_SUCCESS; - u16 data; - - phy_ctrl = er32(PHY_CTRL); - - if (!active) { - phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - goto out; - - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - goto out; - - /* - * Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - } - -out: - return ret_val; -} - -/** - * e1000e_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 - * @hw: pointer to the HW structure - * @bank: pointer to the variable that returns the active bank - * - * Reads signature byte from the NVM using the flash access registers. - * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. - **/ -static s32 e1000e_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) -{ - u32 eecd; - struct e1000_nvm_info *nvm = &hw->nvm; - u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); - u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; - u8 sig_byte = 0; - s32 ret_val = E1000_SUCCESS; - - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - eecd = er32(EECD); - if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == - E1000_EECD_SEC1VAL_VALID_MASK) { - if (eecd & E1000_EECD_SEC1VAL) - *bank = 1; - else - *bank = 0; - - goto out; - } - e_dbg("Unable to determine valid NVM bank via EEC - " - "reading flash signature\n"); - /* fall-thru */ - default: - /* set bank to 0 in case flash read fails */ - *bank = 0; - - /* Check bank 0 */ - ret_val = e1000e_read_flash_byte_ich8lan(hw, act_offset, - &sig_byte); - if (ret_val) - goto out; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 0; - goto out; - } - - /* Check bank 1 */ - ret_val = e1000e_read_flash_byte_ich8lan(hw, act_offset + - bank1_offset, - &sig_byte); - if (ret_val) - goto out; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 1; - goto out; - } - - e_dbg("ERROR: No valid NVM bank present\n"); - ret_val = -E1000_ERR_NVM; - break; - } -out: - return ret_val; -} - -/** - * e1000e_read_nvm_ich8lan - Read word(s) from the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to read. - * @words: Size of data to read in words - * @data: Pointer to the word(s) to read at offset. - * - * Reads a word(s) from the NVM using the flash access registers. - **/ -static s32 e1000e_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 act_offset; - s32 ret_val = E1000_SUCCESS; - u32 bank = 0; - u16 i, word; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - nvm->ops.acquire(hw); - - ret_val = e1000e_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val != E1000_SUCCESS) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - act_offset = (bank) ? nvm->flash_bank_size : 0; - act_offset += offset; - - ret_val = E1000_SUCCESS; - for (i = 0; i < words; i++) { - if ((dev_spec->shadow_ram) && - (dev_spec->shadow_ram[offset+i].modified)) { - data[i] = dev_spec->shadow_ram[offset+i].value; - } else { - ret_val = e1000e_read_flash_word_ich8lan(hw, - act_offset + i, - &word); - if (ret_val) - break; - data[i] = word; - } - } - - nvm->ops.release(hw); - -out: - if (ret_val) - e_dbg("NVM read error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000e_flash_cycle_init_ich8lan - Initialize flash - * @hw: pointer to the HW structure - * - * This function does initial flash setup so that a new read/write/erase cycle - * can be started. - **/ -static s32 e1000e_flash_cycle_init_ich8lan(struct e1000_hw *hw) -{ - union ich8_hws_flash_status hsfsts; - s32 ret_val = -E1000_ERR_NVM; - s32 i = 0; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* Check if the flash descriptor is valid */ - if (hsfsts.hsf_status.fldesvalid == 0) { - e_dbg("Flash descriptor invalid. " - "SW Sequencing must be used."); - goto out; - } - - /* Clear FCERR and DAEL in hw status by writing 1 */ - hsfsts.hsf_status.flcerr = 1; - hsfsts.hsf_status.dael = 1; - - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - - /* - * Either we should have a hardware SPI cycle in progress - * bit to check against, in order to start a new cycle or - * FDONE bit should be changed in the hardware so that it - * is 1 after hardware reset, which can then be used as an - * indication whether a cycle is in progress or has been - * completed. - */ - - if (hsfsts.hsf_status.flcinprog == 0) { - /* - * There is no cycle running at present, - * so we can start a cycle. - * Begin by setting Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - ret_val = E1000_SUCCESS; - } else { - /* - * Otherwise poll for sometime so the current - * cycle has a chance to end before giving up. - */ - for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { - hsfsts.regval = er16flash( - ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcinprog == 0) { - ret_val = E1000_SUCCESS; - break; - } - udelay(1); - } - if (ret_val == E1000_SUCCESS) { - /* - * Successful in waiting for previous cycle to timeout, - * now set the Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - ew16flash(ICH_FLASH_HSFSTS, - hsfsts.regval); - } else { - e_dbg("Flash controller busy, cannot get access"); - } - } - -out: - return ret_val; -} - -/** - * e1000e_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) - * @hw: pointer to the HW structure - * @timeout: maximum time to wait for completion - * - * This function starts a flash cycle and waits for its completion. - **/ -static s32 e1000e_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) -{ - union ich8_hws_flash_ctrl hsflctl; - union ich8_hws_flash_status hsfsts; - s32 ret_val = -E1000_ERR_NVM; - u32 i = 0; - - /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcgo = 1; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - /* wait till FDONE bit is set to 1 */ - do { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcdone == 1) - break; - udelay(1); - } while (i++ < timeout); - - if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) - ret_val = E1000_SUCCESS; - - return ret_val; -} - -/** - * e1000e_read_flash_word_ich8lan - Read word from flash - * @hw: pointer to the HW structure - * @offset: offset to data location - * @data: pointer to the location for storing the data - * - * Reads the flash word at offset into data. Offset is converted - * to bytes before read. - **/ -static s32 e1000e_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - s32 ret_val; - - if (!data) { - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Must convert offset into bytes. */ - offset <<= 1; - - ret_val = e1000e_read_flash_data_ich8lan(hw, offset, 2, data); - -out: - return ret_val; -} - -/** - * e1000e_read_flash_byte_ich8lan - Read byte from flash - * @hw: pointer to the HW structure - * @offset: The offset of the byte to read. - * @data: Pointer to a byte to store the value read. - * - * Reads a single byte from the NVM using the flash access registers. - **/ -static s32 e1000e_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 *data) -{ - s32 ret_val = E1000_SUCCESS; - u16 word = 0; - - ret_val = e1000e_read_flash_data_ich8lan(hw, offset, 1, &word); - if (ret_val) - goto out; - - *data = (u8)word; - -out: - return ret_val; -} - -/** - * e1000e_read_flash_data_ich8lan - Read byte or word from NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte or word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: Pointer to the word to store the value read. - * - * Reads a byte or word from the NVM using the flash access registers. - **/ -static s32 e1000e_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val = -E1000_ERR_NVM; - u8 count = 0; - - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - goto out; - flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr; - - do { - udelay(1); - /* Steps */ - ret_val = e1000e_flash_cycle_init_ich8lan(hw); - if (ret_val != E1000_SUCCESS) - break; - - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = e1000e_flash_cycle_ich8lan(hw, - ICH_FLASH_READ_COMMAND_TIMEOUT); - - /* - * Check if FCERR is set to 1, if set to 1, clear it - * and try the whole sequence a few more times, else - * read in (shift in) the Flash Data0, the order is - * least significant byte first msb to lsb - */ - if (ret_val == E1000_SUCCESS) { - flash_data = er32flash(ICH_FLASH_FDATA0); - if (size == 1) - *data = (u8)(flash_data & 0x000000FF); - else if (size == 2) - *data = (u16)(flash_data & 0x0000FFFF); - break; - } else { - /* - * If we've gotten here, then things are probably - * completely hosed, but if the error condition is - * detected, it won't hurt to give it another try... - * ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash( - ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) { - /* Repeat for some time before giving up. */ - continue; - } else if (hsfsts.hsf_status.flcdone == 0) { - e_dbg("Timeout error - flash cycle " - "did not complete."); - break; - } - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - -out: - return ret_val; -} - -/** - * e1000e_write_nvm_ich8lan - Write word(s) to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to write. - * @words: Size of data to write in words - * @data: Pointer to the word(s) to write at offset. - * - * Writes a byte or word to the NVM using the flash access registers. - **/ -static s32 e1000e_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val = E1000_SUCCESS; - u16 i; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - nvm->ops.acquire(hw); - - for (i = 0; i < words; i++) { - dev_spec->shadow_ram[offset+i].modified = true; - dev_spec->shadow_ram[offset+i].value = data[i]; - } - - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_update_nvm_checksum_ich8lan - Update the checksum for NVM - * @hw: pointer to the HW structure - * - * The NVM checksum is updated by calling the generic update_nvm_checksum, - * which writes the checksum to the shadow ram. The changes in the shadow - * ram are then committed to the EEPROM by processing each bank at a time - * checking for the modified bit and writing only the pending changes. - * After a successful commit, the shadow ram is cleared and is ready for - * future writes. - **/ -static s32 e1000e_update_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 i, act_offset, new_bank_offset, old_bank_offset, bank; - s32 ret_val; - u16 data; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - goto out; - - if (nvm->type != e1000_nvm_flash_sw) - goto out; - - nvm->ops.acquire(hw); - - /* - * We're writing to the opposite bank so if we're on bank 1, - * write to bank 0 etc. We also need to erase the segment that - * is going to be written - */ - ret_val = e1000e_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val != E1000_SUCCESS) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - if (bank == 0) { - new_bank_offset = nvm->flash_bank_size; - old_bank_offset = 0; - ret_val = e1000e_erase_flash_bank_ich8lan(hw, 1); - if (ret_val) { - nvm->ops.release(hw); - goto out; - } - } else { - old_bank_offset = nvm->flash_bank_size; - new_bank_offset = 0; - ret_val = e1000e_erase_flash_bank_ich8lan(hw, 0); - if (ret_val) { - nvm->ops.release(hw); - goto out; - } - } - - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - /* - * Determine whether to write the value stored - * in the other NVM bank or a modified value stored - * in the shadow RAM - */ - if (dev_spec->shadow_ram[i].modified) { - data = dev_spec->shadow_ram[i].value; - } else { - ret_val = e1000e_read_flash_word_ich8lan(hw, i + - old_bank_offset, - &data); - if (ret_val) - break; - } - - /* - * If the word is 0x13, then make sure the signature bits - * (15:14) are 11b until the commit has completed. - * This will allow us to write 10b which indicates the - * signature is valid. We want to do this after the write - * has completed so that we don't mark the segment valid - * while the write is still in progress - */ - if (i == E1000_ICH_NVM_SIG_WORD) - data |= E1000_ICH_NVM_SIG_MASK; - - /* Convert offset to bytes. */ - act_offset = (i + new_bank_offset) << 1; - - udelay(100); - /* Write the bytes to the new bank. */ - ret_val = e1000e_retry_write_flash_byte_ich8lan(hw, - act_offset, - (u8)data); - if (ret_val) - break; - - udelay(100); - ret_val = e1000e_retry_write_flash_byte_ich8lan(hw, - act_offset + 1, - (u8)(data >> 8)); - if (ret_val) - break; - } - - /* - * Don't bother writing the segment valid bits if sector - * programming failed. - */ - if (ret_val) { - e_dbg("Flash commit failed.\n"); - nvm->ops.release(hw); - goto out; - } - - /* - * Finally validate the new segment by setting bit 15:14 - * to 10b in word 0x13 , this can be done without an - * erase as well since these bits are 11 to start with - * and we need to change bit 14 to 0b - */ - act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; - ret_val = e1000e_read_flash_word_ich8lan(hw, act_offset, &data); - if (ret_val) { - nvm->ops.release(hw); - goto out; - } - - data &= 0xBFFF; - ret_val = e1000e_retry_write_flash_byte_ich8lan(hw, - act_offset * 2 + 1, - (u8)(data >> 8)); - if (ret_val) { - nvm->ops.release(hw); - goto out; - } - - /* - * And invalidate the previously valid segment by setting - * its signature word (0x13) high_byte to 0b. This can be - * done without an erase because flash erase sets all bits - * to 1's. We can write 1's to 0's without an erase - */ - act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; - ret_val = e1000e_retry_write_flash_byte_ich8lan(hw, act_offset, 0); - if (ret_val) { - nvm->ops.release(hw); - goto out; - } - - /* Great! Everything worked, we can now clear the cached entries. */ - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - - nvm->ops.release(hw); - - /* - * Reload the EEPROM, or else modifications will not appear - * until after the next adapter reset. - */ - nvm->ops.reload(hw); - msleep(10); - -out: - if (ret_val) - e_dbg("NVM update error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000e_validate_nvm_checksum_ich8lan - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. - * If the bit is 0, that the EEPROM had been modified, but the checksum was not - * calculated, in which case we need to calculate the checksum and set bit 6. - **/ -static s32 e1000e_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 data; - - /* - * Read 0x19 and check bit 6. If this bit is 0, the checksum - * needs to be fixed. This bit is an indication that the NVM - * was prepared by OEM software and did not calculate the - * checksum...a likely scenario. - */ - ret_val = e1000e_read_nvm(hw, 0x19, 1, &data); - if (ret_val) - goto out; - - if ((data & 0x40) == 0) { - data |= 0x40; - ret_val = e1000e_write_nvm(hw, 0x19, 1, &data); - if (ret_val) - goto out; - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - goto out; - } - - ret_val = e1000e_validate_nvm_checksum_generic(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_flash_data_ich8lan - Writes bytes to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte/word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: The byte(s) to write to the NVM. - * - * Writes one/two bytes to the NVM using the flash access registers. - **/ -static s32 e1000e_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val = -E1000_ERR_NVM; - u8 count = 0; - - if (size < 1 || size > 2 || data > size * 0xff || - offset > ICH_FLASH_LINEAR_ADDR_MASK) - goto out; - - flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr; - - do { - udelay(1); - /* Steps */ - ret_val = e1000e_flash_cycle_init_ich8lan(hw); - if (ret_val != E1000_SUCCESS) - break; - - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - if (size == 1) - flash_data = (u32)data & 0x00FF; - else - flash_data = (u32)data; - - ew32flash(ICH_FLASH_FDATA0, flash_data); - - /* - * check if FCERR is set to 1 , if set to 1, clear it - * and try the whole sequence a few more times else done - */ - ret_val = e1000e_flash_cycle_ich8lan(hw, - ICH_FLASH_WRITE_COMMAND_TIMEOUT); - if (ret_val == E1000_SUCCESS) - break; - - /* - * If we're here, then things are most likely - * completely hosed, but if the error condition - * is detected, it won't hurt to give it another - * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) { - /* Repeat for some time before giving up. */ - continue; - } else if (hsfsts.hsf_status.flcdone == 0) { - e_dbg("Timeout error - flash cycle " - "did not complete."); - break; - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - -out: - return ret_val; -} - -/** - * e1000e_write_flash_byte_ich8lan - Write a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The index of the byte to read. - * @data: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - **/ -static s32 e1000e_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 data) -{ - u16 word = (u16)data; - - return e1000e_write_flash_data_ich8lan(hw, offset, 1, word); -} - -/** - * e1000e_retry_write_flash_byte_ich8lan - Writes a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The offset of the byte to write. - * @byte: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - * Goes through a retry algorithm before giving up. - **/ -static s32 e1000e_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte) -{ - s32 ret_val; - u16 program_retries; - - ret_val = e1000e_write_flash_byte_ich8lan(hw, offset, byte); - if (ret_val == E1000_SUCCESS) - goto out; - - for (program_retries = 0; program_retries < 100; program_retries++) { - e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset); - udelay(100); - ret_val = e1000e_write_flash_byte_ich8lan(hw, offset, byte); - if (ret_val == E1000_SUCCESS) - break; - } - if (program_retries == 100) { - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM - * @hw: pointer to the HW structure - * @bank: 0 for first bank, 1 for second bank, etc. - * - * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. - * bank N is 4096 * N + flash_reg_addr. - **/ -static s32 e1000e_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - /* bank size is in 16bit words - adjust to bytes */ - u32 flash_bank_size = nvm->flash_bank_size * 2; - s32 ret_val = E1000_SUCCESS; - s32 count = 0; - s32 j, iteration, sector_size; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* - * Determine HW Sector size: Read BERASE bits of hw flash status - * register - * 00: The Hw sector is 256 bytes, hence we need to erase 16 - * consecutive sectors. The start index for the nth Hw sector - * can be calculated as = bank * 4096 + n * 256 - * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. - * The start index for the nth Hw sector can be calculated - * as = bank * 4096 - * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 - * (ich9 only, otherwise error condition) - * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 - */ - switch (hsfsts.hsf_status.berasesz) { - case 0: - /* Hw sector size 256 */ - sector_size = ICH_FLASH_SEG_SIZE_256; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; - break; - case 1: - sector_size = ICH_FLASH_SEG_SIZE_4K; - iteration = 1; - break; - case 2: - sector_size = ICH_FLASH_SEG_SIZE_8K; - iteration = 1; - break; - case 3: - sector_size = ICH_FLASH_SEG_SIZE_64K; - iteration = 1; - break; - default: - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Start with the base address, then add the sector offset. */ - flash_linear_addr = hw->nvm.flash_base_addr; - flash_linear_addr += (bank) ? flash_bank_size : 0; - - for (j = 0; j < iteration ; j++) { - do { - /* Steps */ - ret_val = e1000e_flash_cycle_init_ich8lan(hw); - if (ret_val) - goto out; - - /* - * Write a value 11 (block Erase) in Flash - * Cycle field in hw flash control - */ - hsflctl.regval = er16flash( - ICH_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - ew16flash(ICH_FLASH_HSFCTL, - hsflctl.regval); - - /* - * Write the last 24 bits of an index within the - * block into Flash Linear address field in Flash - * Address. - */ - flash_linear_addr += (j * sector_size); - ew32flash(ICH_FLASH_FADDR, - flash_linear_addr); - - ret_val = e1000e_flash_cycle_ich8lan(hw, - ICH_FLASH_ERASE_COMMAND_TIMEOUT); - if (ret_val == E1000_SUCCESS) - break; - - /* - * Check if FCERR is set to 1. If 1, - * clear it and try the whole sequence - * a few more times else Done - */ - hsfsts.regval = er16flash( - ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) - /* repeat for some time before giving up */ - continue; - else if (hsfsts.hsf_status.flcdone == 0) - goto out; - } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); - } - -out: - return ret_val; -} - -/** - * e1000e_valid_led_default_ich8lan - Set the default LED settings - * @hw: pointer to the HW structure - * @data: Pointer to the LED settings - * - * Reads the LED default settings from the NVM to data. If the NVM LED - * settings is all 0's or F's, set the LED default to a valid LED default - * setting. - **/ -static s32 e1000e_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000e_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - if (*data == ID_LED_RESERVED_0000 || - *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT_ICH8LAN; - -out: - return ret_val; -} - -/** - * e1000e_id_led_init_pchlan - store LED configurations - * @hw: pointer to the HW structure - * - * PCH does not control LEDs via the LEDCTL register, rather it uses - * the PHY LED configuration register. - * - * PCH also does not have an "always on" or "always off" mode which - * complicates the ID feature. Instead of using the "on" mode to indicate - * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()), - * use "link_up" mode. The LEDs will still ID on request if there is no - * link based on logic in e1000e_led_[on|off]_pchlan(). - **/ -static s32 e1000e_id_led_init_pchlan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; - const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; - u16 data, i, temp, shift; - - /* Get default ID LED modes */ - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - goto out; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; - shift = (i * 5); - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_on << shift); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_on << shift); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - } - -out: - return ret_val; -} - -/** - * e1000e_get_bus_info_ich8lan - Get/Set the bus type and width - * @hw: pointer to the HW structure - * - * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability - * register, so the the bus width is hard coded. - **/ -static s32 e1000e_get_bus_info_ich8lan(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - s32 ret_val; - - ret_val = e1000e_get_bus_info_pcie(hw); - - /* - * ICH devices are "PCI Express"-ish. They have - * a configuration space, but do not contain - * PCI Express Capability registers, so bus width - * must be hardcoded. - */ - if (bus->width == e1000_bus_width_unknown) - bus->width = e1000_bus_width_pcie_x1; - - return ret_val; -} - -/** - * e1000e_reset_hw_ich8lan - Reset the hardware - * @hw: pointer to the HW structure - * - * Does a full reset of the hardware which includes a reset of the PHY and - * MAC. - **/ -static s32 e1000e_reset_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 reg; - u32 ctrl, kab; - s32 ret_val; - - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* - * Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC - * with the global reset. - */ - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - msleep(10); - - /* Workaround for ICH8 bit corruption issue in FIFO memory */ - if (hw->mac.type == e1000_ich8lan) { - /* Set Tx and Rx buffer allocation to 8k apiece. */ - ew32(PBA, E1000_PBA_8K); - /* Set Packet Buffer Size to 16k. */ - ew32(PBS, E1000_PBS_16K); - } - - if (hw->mac.type == e1000_pchlan) { - /* Save the NVM K1 bit setting*/ - ret_val = e1000e_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); - if (ret_val) - return ret_val; - - if (reg & E1000_NVM_K1_ENABLE) - dev_spec->nvm_k1_enabled = true; - else - dev_spec->nvm_k1_enabled = false; - } - - ctrl = er32(CTRL); - - if (!e1000e_check_reset_block(hw) && !hw->phy.reset_disable) { - /* Clear PHY Reset Asserted bit */ - if (hw->mac.type >= e1000_pchlan) { - u32 status = er32(STATUS); - ew32(STATUS, status & - ~E1000_STATUS_PHYRA); - } - - /* - * PHY HW reset requires MAC CORE reset at the same - * time to make sure the interface between MAC and the - * external PHY is reset. - */ - ctrl |= E1000_CTRL_PHY_RST; - } - ret_val = e1000e_acquire_swflag_ich8lan(hw); - e_dbg("Issuing a global reset to ich8lan\n"); - ew32(CTRL, (ctrl | E1000_CTRL_RST)); - msleep(20); - - if (!ret_val) - e1000e_release_swflag_ich8lan(hw); - - if (ctrl & E1000_CTRL_PHY_RST) - ret_val = hw->phy.ops.get_cfg_done(hw); - - if (hw->mac.type >= e1000_ich10lan) { - e1000e_lan_init_done_ich8lan(hw); - } else { - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) { - /* - * When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - e_dbg("Auto Read Done did not complete\n"); - } - } - /* Dummy read to clear the phy wakeup bit after lcd reset */ - if (hw->mac.type == e1000_pchlan) - e1e_rphy(hw, BM_WUC, ®); - - ret_val = e1000e_sw_lcd_config_ich8lan(hw); - if (ret_val) - goto out; - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000e_oem_bits_config_ich8lan(hw, true); - if (ret_val) - goto out; - } - /* - * For PCH, this write will make sure that any noise - * will be detected as a CRC error and be dropped rather than show up - * as a bad packet to the DMA engine. - */ - if (hw->mac.type == e1000_pchlan) - ew32(CRC_OFFSET, 0x65656565); - - ew32(IMC, 0xffffffff); - er32(ICR); - - kab = er32(KABGTXD); - kab |= E1000_KABGTXD_BGSQLBIAS; - ew32(KABGTXD, kab); - - if (hw->mac.type == e1000_pchlan) - ret_val = e1000e_hv_phy_workarounds_ich8lan(hw); - -out: - return ret_val; -} - -/** - * e1000e_init_hw_ich8lan - Initialize the hardware - * @hw: pointer to the HW structure - * - * Prepares the hardware for transmit and receive by doing the following: - * - initialize hardware bits - * - initialize LED identification - * - setup receive address registers - * - setup flow control - * - setup transmit descriptors - * - clear statistics - **/ -static s32 e1000e_init_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl_ext, txdctl, snoop; - s32 ret_val; - u16 i; - - e1000e_initialize_hw_bits_ich8lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) - /* This is not fatal and we should not stop init due to this */ - e_dbg("Error initializing identification LED\n"); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* - * The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Reading the BM_WUC register will clear the host wakeup bit. - * Reset the phy after disabling host wakeup to reset the Rx buffer. - */ - if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_WUC, &i); - ret_val = e1000e_phy_hw_reset_ich8lan(hw); - if (ret_val) - return ret_val; - } - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy for both queues */ - txdctl = er32(TXDCTL(0)); - txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH; - ew32(TXDCTL(0), txdctl); - txdctl = er32(TXDCTL(1)); - txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH; - ew32(TXDCTL(1), txdctl); - - /* - * ICH8 has opposite polarity of no_snoop bits. - * By default, we should use snoop behavior. - */ - if (mac->type == e1000_ich8lan) - snoop = PCIE_ICH8_SNOOP_ALL; - else - snoop = (u32)~(PCIE_NO_SNOOP_ALL); - e1000e_set_pcie_no_snoop(hw, snoop); - - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - ew32(CTRL_EXT, ctrl_ext); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000e_clear_hw_cntrs_ich8lan(hw); - - return ret_val; -} -/** - * e1000e_initialize_hw_bits_ich8lan - Initialize required hardware bits - * @hw: pointer to the HW structure - * - * Sets/Clears required hardware bits necessary for correctly setting up the - * hardware for transmit and receive. - **/ -static void e1000e_initialize_hw_bits_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Extended Device Control */ - reg = er32(CTRL_EXT); - reg |= (1 << 22); - /* Enable PHY low-power state when MAC is at D3 w/o WoL */ - if (hw->mac.type >= e1000_pchlan) - reg |= E1000_CTRL_EXT_PHYPDEN; - ew32(CTRL_EXT, reg); - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - if (hw->mac.type == e1000_ich8lan) - reg |= (1 << 28) | (1 << 29); - reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - reg |= (1 << 24) | (1 << 26) | (1 << 30); - ew32(TARC(1), reg); - - /* Device Status */ - if (hw->mac.type == e1000_ich8lan) { - reg = er32(STATUS); - reg &= ~(1 << 31); - ew32(STATUS, reg); - } - - return; -} - -/** - * e1000e_setup_link_ich8lan - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000e_setup_link_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (e1000e_check_reset_block(hw)) - goto out; - - /* - * ICH parts do not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - if (hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); - - /* Continue to configure the copper link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - goto out; - - ew32(FCTTV, hw->fc.pause_time); - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82577)) { - ret_val = e1e_wphy(hw, - PHY_REG(BM_PORT_CTRL_PAGE, 27), - hw->fc.pause_time); - if (ret_val) - goto out; - } - - ret_val = e1000e_set_fc_watermarks(hw); - -out: - return ret_val; -} - -/** - * e1000e_setup_copper_link_ich8lan - Configure MAC/PHY interface - * @hw: pointer to the HW structure - * - * Configures the kumeran interface to the PHY to wait the appropriate time - * when polling the PHY, then call the generic setup_copper_link to finish - * configuring the copper link. - **/ -static s32 e1000e_setup_copper_link_ich8lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* - * Set the mac to wait the maximum time between each iteration - * and increase the max iterations when polling the phy; - * this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_TIMEOUTS, - 0xFFFF); - if (ret_val) - goto out; - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_INBAND_PARAM, - ®_data); - if (ret_val) - goto out; - reg_data |= 0x3F; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_INBAND_PARAM, - reg_data); - if (ret_val) - goto out; - - switch (hw->phy.type) { - case e1000_phy_igp_3: - ret_val = e1000e_copper_link_setup_igp(hw); - if (ret_val) - goto out; - break; - case e1000_phy_bm: - case e1000_phy_82578: - ret_val = e1000e_copper_link_setup_m88(hw); - if (ret_val) - goto out; - break; - case e1000_phy_82577: - ret_val = e1000e_copper_link_setup_82577(hw); - if (ret_val) - goto out; - break; - case e1000_phy_ife: - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, - ®_data); - if (ret_val) - goto out; - - reg_data &= ~IFE_PMC_AUTO_MDIX; - - switch (hw->phy.mdix) { - case 1: - reg_data &= ~IFE_PMC_FORCE_MDIX; - break; - case 2: - reg_data |= IFE_PMC_FORCE_MDIX; - break; - case 0: - default: - reg_data |= IFE_PMC_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, - reg_data); - if (ret_val) - goto out; - break; - default: - break; - } - ret_val = e1000e_setup_copper_link(hw); - -out: - return ret_val; -} - -/** - * e1000e_get_link_up_info_ich8lan - Get current link speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to store current link speed - * @duplex: pointer to store the current link duplex - * - * Calls the generic get_speed_and_duplex to retrieve the current link - * information and then calls the Kumeran lock loss workaround for links at - * gigabit speeds. - **/ -static s32 e1000e_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); - if (ret_val) - goto out; - - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3) && - (*speed == SPEED_1000)) { - ret_val = e1000e_kmrn_lock_loss_workaround_ich8lan(hw); - } - -out: - return ret_val; -} - -/** - * e1000e_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround - * @hw: pointer to the HW structure - * - * Work-around for 82566 Kumeran PCS lock loss: - * On link status change (i.e. PCI reset, speed change) and link is up and - * speed is gigabit- - * 0) if workaround is optionally disabled do nothing - * 1) wait 1ms for Kumeran link to come up - * 2) check Kumeran Diagnostic register PCS lock loss bit - * 3) if not set the link is locked (all is good), otherwise... - * 4) reset the PHY - * 5) repeat up to 10 times - * Note: this is only called for IGP3 copper when speed is 1gb. - **/ -static s32 e1000e_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 phy_ctrl; - s32 ret_val = E1000_SUCCESS; - u16 i, data; - bool link; - - if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) - goto out; - - /* - * Make sure link is up before proceeding. If not just return. - * Attempting this while link is negotiating fouled up link - * stability - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (!link) { - ret_val = E1000_SUCCESS; - goto out; - } - - for (i = 0; i < 10; i++) { - /* read once to clear */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - goto out; - /* and again to get new status */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - goto out; - - /* check for PCS lock */ - if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Issue PHY reset */ - e1000e_phy_hw_reset(hw); - mdelay(5); - } - /* Disable GigE link negotiation */ - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, phy_ctrl); - - /* - * Call gig speed drop workaround on Gig disable before accessing - * any PHY registers - */ - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* unable to acquire PCS lock */ - ret_val = -E1000_ERR_PHY; - -out: - return ret_val; -} - -/** - * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state - * @hw: pointer to the HW structure - * @state: boolean value used to set the current Kumeran workaround state - * - * If ICH8, set the current Kumeran workaround state (enabled - true - * /disabled - false). - **/ -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - - if (hw->mac.type != e1000_ich8lan) { - e_dbg("Workaround applies to ICH8 only.\n"); - return; - } - - dev_spec->kmrn_lock_loss_workaround_enabled = state; - - return; -} - -/** - * e1000e_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 - * @hw: pointer to the HW structure - * - * Workaround for 82566 power-down on D3 entry: - * 1) disable gigabit link - * 2) write VR power-down enable - * 3) read it back - * Continue if successful, else issue LCD reset and repeat - **/ -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - u16 data; - u8 retry = 0; - - if (hw->phy.type != e1000_phy_igp_3) - goto out; - - /* Try the workaround twice (if needed) */ - do { - /* Disable link */ - reg = er32(PHY_CTRL); - reg |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, reg); - - /* - * Call gig speed drop workaround on Gig disable before - * accessing any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* Write VR power-down enable */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - e1e_wphy(hw, IGP3_VR_CTRL, - data | IGP3_VR_CTRL_MODE_SHUTDOWN); - - /* Read it back and test */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) - break; - - /* Issue PHY reset and repeat at most one more time */ - reg = er32(CTRL); - ew32(CTRL, reg | E1000_CTRL_PHY_RST); - retry++; - } while (retry); - -out: - return; -} - -/** - * e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working - * @hw: pointer to the HW structure - * - * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), - * LPLU, Gig disable, MDIC PHY reset): - * 1) Set Kumeran Near-end loopback - * 2) Clear Kumeran Near-end loopback - * Should only be called for ICH8[m] devices with IGP_3 Phy. - **/ -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 reg_data; - - if ((hw->mac.type != e1000_ich8lan) || - (hw->phy.type != e1000_phy_igp_3)) - goto out; - - ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, - ®_data); - if (ret_val) - goto out; - reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_DIAG_OFFSET, - reg_data); - if (ret_val) - goto out; - reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_DIAG_OFFSET, - reg_data); -out: - return; -} - -/** - * e1000e_disable_gig_wol_ich8lan - disable gig during WoL - * @hw: pointer to the HW structure - * - * During S0 to Sx transition, it is possible the link remains at gig - * instead of negotiating to a lower speed. Before going to Sx, set - * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation - * to a lower speed. - * - * Should only be called for applicable parts. - **/ -void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) -{ - u32 phy_ctrl; - - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - case e1000_pchlan: - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_GBE_DISABLE; - ew32(PHY_CTRL, phy_ctrl); - - if (hw->mac.type == e1000_pchlan) - e1000e_phy_hw_reset_ich8lan(hw); - default: - break; - } - - return; -} - -/** - * e1000e_cleanup_led_ich8lan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000e_cleanup_led_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.type == e1000_phy_ife) - ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - 0); - else - ew32(LEDCTL, hw->mac.ledctl_default); - - return ret_val; -} - -/** - * e1000e_led_on_ich8lan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000e_led_on_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.type == e1000_phy_ife) - ret_val = e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); - else - ew32(LEDCTL, hw->mac.ledctl_mode2); - - return ret_val; -} - -/** - * e1000e_led_off_ich8lan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000e_led_off_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.type == e1000_phy_ife) - ret_val = e1e_wphy(hw, - IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); - else - ew32(LEDCTL, hw->mac.ledctl_mode1); - - return ret_val; -} - -/** - * e1000e_setup_led_pchlan - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use. - **/ -static s32 e1000e_setup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, - (u16)hw->mac.ledctl_mode1); -} - -/** - * e1000e_cleanup_led_pchlan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000e_cleanup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, - (u16)hw->mac.ledctl_default); -} - -/** - * e1000e_led_on_pchlan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000e_led_on_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode2; - u32 i, led; - - /* - * If no link, then turn LED on by setting the invert bit - * for each LED that's mode is "link_up" in ledctl_mode2. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000e_led_off_pchlan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000e_led_off_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode1; - u32 i, led; - - /* - * If no link, then turn LED off by clearing the invert bit - * for each LED that's mode is "link_up" in ledctl_mode1. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000e_get_cfg_done_ich8lan - Read config done bit - * @hw: pointer to the HW structure - * - * Read the management control register for the config done bit for - * completion status. NOTE: silicon which is EEPROM-less will fail trying - * to read the config done bit, so an error is *ONLY* logged and returns - * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon - * would not be able to be reset or change link. - **/ -static s32 e1000e_get_cfg_done_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u32 bank = 0; - - if (hw->mac.type >= e1000_pchlan) { - u32 status = er32(STATUS); - - if (status & E1000_STATUS_PHYRA) { - ew32(STATUS, status & - ~E1000_STATUS_PHYRA); - } else - e_dbg("PHY Reset Asserted not set - needs delay\n"); - } - - e1000e_get_cfg_done(hw); - - /* If EEPROM is not marked present, init the IGP 3 PHY manually */ - if ((hw->mac.type != e1000_ich10lan) && - (hw->mac.type != e1000_pchlan)) { - if (((er32(EECD) & E1000_EECD_PRES) == 0) && - (hw->phy.type == e1000_phy_igp_3)) { - e1000e_phy_init_script_igp3(hw); - } - } else { - if (e1000e_valid_nvm_bank_detect_ich8lan(hw, &bank)) { - /* Maybe we should do a basic PHY config */ - e_dbg("EEPROM not present\n"); - ret_val = -E1000_ERR_CONFIG; - } - } - - return ret_val; -} - -/** - * e1000e_power_down_phy_copper_ich8lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000e_power_down_phy_copper_ich8lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - e1000e_check_reset_block(hw))) - e1000e_power_down_phy_copper(hw); - - return; -} - -/** - * e1000e_clear_hw_cntrs_ich8lan - Clear statistical counters - * @hw: pointer to the HW structure - * - * Clears hardware counters specific to the silicon family and calls - * clear_hw_cntrs_generic to clear all general purpose counters. - **/ -static void e1000e_clear_hw_cntrs_ich8lan(struct e1000_hw *hw __unused) -{ -#if 0 - u16 phy_data; - - e1000e_clear_hw_cntrs_base(hw); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - /* Clear PHY statistics registers */ - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82577)) { - e1e_rphy(hw, HV_SCC_UPPER, &phy_data); - e1e_rphy(hw, HV_SCC_LOWER, &phy_data); - e1e_rphy(hw, HV_ECOL_UPPER, &phy_data); - e1e_rphy(hw, HV_ECOL_LOWER, &phy_data); - e1e_rphy(hw, HV_MCC_UPPER, &phy_data); - e1e_rphy(hw, HV_MCC_LOWER, &phy_data); - e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data); - e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data); - e1e_rphy(hw, HV_COLC_UPPER, &phy_data); - e1e_rphy(hw, HV_COLC_LOWER, &phy_data); - e1e_rphy(hw, HV_DC_UPPER, &phy_data); - e1e_rphy(hw, HV_DC_LOWER, &phy_data); - e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data); - e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data); - } -#endif -} - -static struct pci_device_id e1000e_ich8lan_nics[] = { - PCI_ROM(0x8086, 0x104C, "E1000_DEV_ID_ICH8_IFE", "E1000_DEV_ID_ICH8_IFE", board_ich8lan), - PCI_ROM(0x8086, 0x10C5, "E1000_DEV_ID_ICH8_IFE_G", "E1000_DEV_ID_ICH8_IFE_G", board_ich8lan), - PCI_ROM(0x8086, 0x10C4, "E1000_DEV_ID_ICH8_IFE_GT", "E1000_DEV_ID_ICH8_IFE_GT", board_ich8lan), - PCI_ROM(0x8086, 0x104A, "E1000_DEV_ID_ICH8_IGP_AMT", "E1000_DEV_ID_ICH8_IGP_AMT", board_ich8lan), - PCI_ROM(0x8086, 0x104B, "E1000_DEV_ID_ICH8_IGP_C", "E1000_DEV_ID_ICH8_IGP_C", board_ich8lan), - PCI_ROM(0x8086, 0x104D, "E1000_DEV_ID_ICH8_IGP_M", "E1000_DEV_ID_ICH8_IGP_M", board_ich8lan), - PCI_ROM(0x8086, 0x1049, "E1000_DEV_ID_ICH8_IGP_M_AMT", "E1000_DEV_ID_ICH8_IGP_M_AMT", board_ich8lan), - PCI_ROM(0x8086, 0x1501, "E1000_DEV_ID_ICH8_82567V_3", "E1000_DEV_ID_ICH8_82567V_3", board_ich8lan), - PCI_ROM(0x8086, 0x10C0, "E1000_DEV_ID_ICH9_IFE", "E1000_DEV_ID_ICH9_IFE", board_ich9lan), - PCI_ROM(0x8086, 0x10C2, "E1000_DEV_ID_ICH9_IFE_G", "E1000_DEV_ID_ICH9_IFE_G", board_ich9lan), - PCI_ROM(0x8086, 0x10C3, "E1000_DEV_ID_ICH9_IFE_GT", "E1000_DEV_ID_ICH9_IFE_GT", board_ich9lan), - PCI_ROM(0x8086, 0x10BD, "E1000_DEV_ID_ICH9_IGP_AMT", "E1000_DEV_ID_ICH9_IGP_AMT", board_ich9lan), - PCI_ROM(0x8086, 0x294C, "E1000_DEV_ID_ICH9_IGP_C", "E1000_DEV_ID_ICH9_IGP_C", board_ich9lan), - PCI_ROM(0x8086, 0x10E5, "E1000_DEV_ID_ICH9_BM", "E1000_DEV_ID_ICH9_BM", board_ich9lan), - PCI_ROM(0x8086, 0x10BF, "E1000_DEV_ID_ICH9_IGP_M", "E1000_DEV_ID_ICH9_IGP_M", board_ich9lan), - PCI_ROM(0x8086, 0x10F5, "E1000_DEV_ID_ICH9_IGP_M_AMT", "E1000_DEV_ID_ICH9_IGP_M_AMT", board_ich9lan), - PCI_ROM(0x8086, 0x10CB, "E1000_DEV_ID_ICH9_IGP_M_V", "E1000_DEV_ID_ICH9_IGP_M_V", board_ich9lan), - PCI_ROM(0x8086, 0x10CC, "E1000_DEV_ID_ICH10_R_BM_LM", "E1000_DEV_ID_ICH10_R_BM_LM", board_ich9lan), - PCI_ROM(0x8086, 0x10CD, "E1000_DEV_ID_ICH10_R_BM_LF", "E1000_DEV_ID_ICH10_R_BM_LF", board_ich9lan), - PCI_ROM(0x8086, 0x10CE, "E1000_DEV_ID_ICH10_R_BM_V", "E1000_DEV_ID_ICH10_R_BM_V", board_ich9lan), - PCI_ROM(0x8086, 0x10DE, "E1000_DEV_ID_ICH10_D_BM_LM", "E1000_DEV_ID_ICH10_D_BM_LM", board_ich10lan), - PCI_ROM(0x8086, 0x10DF, "E1000_DEV_ID_ICH10_D_BM_LF", "E1000_DEV_ID_ICH10_D_BM_LF", board_ich10lan), - PCI_ROM(0x8086, 0x10EA, "E1000_DEV_ID_PCH_M_HV_LM", "E1000_DEV_ID_PCH_M_HV_LM", board_pchlan), - PCI_ROM(0x8086, 0x10EB, "E1000_DEV_ID_PCH_M_HV_LC", "E1000_DEV_ID_PCH_M_HV_LC", board_pchlan), - PCI_ROM(0x8086, 0x10EF, "E1000_DEV_ID_PCH_D_HV_DM", "E1000_DEV_ID_PCH_D_HV_DM", board_pchlan), - PCI_ROM(0x8086, 0x10F0, "E1000_DEV_ID_PCH_D_HV_DC", "E1000_DEV_ID_PCH_D_HV_DC", board_pchlan), -}; - -struct pci_driver e1000e_ich8lan_driver __pci_driver = { - .ids = e1000e_ich8lan_nics, - .id_count = (sizeof (e1000e_ich8lan_nics) / sizeof (e1000e_ich8lan_nics[0])), - .probe = e1000e_probe, - .remove = e1000e_remove, -}; diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.h deleted file mode 100644 index af3447829..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_ich8lan.h +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_ICH8LAN_H_ -#define _E1000E_ICH8LAN_H_ - -#define ICH_FLASH_GFPREG 0x0000 -#define ICH_FLASH_HSFSTS 0x0004 -#define ICH_FLASH_HSFCTL 0x0006 -#define ICH_FLASH_FADDR 0x0008 -#define ICH_FLASH_FDATA0 0x0010 - -/* Requires up to 10 seconds when MNG might be accessing part. */ -#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF -#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 - -#define ICH_CYCLE_READ 0 -#define ICH_CYCLE_WRITE 2 -#define ICH_CYCLE_ERASE 3 - -#define FLASH_GFPREG_BASE_MASK 0x1FFF -#define FLASH_SECTOR_ADDR_SHIFT 12 - -#define ICH_FLASH_SEG_SIZE_256 256 -#define ICH_FLASH_SEG_SIZE_4K 4096 -#define ICH_FLASH_SEG_SIZE_8K 8192 -#define ICH_FLASH_SEG_SIZE_64K 65536 -#define ICH_FLASH_SECTOR_SIZE 4096 - -#define ICH_FLASH_REG_MAPSIZE 0x00A0 - -#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ -#define E1000_ICH_FWSM_DISSW 0x10000000 /* FW Disables SW Writes */ -/* FW established a valid mode */ -#define E1000_ICH_FWSM_FW_VALID 0x00008000 - -#define E1000_ICH_MNG_IAMT_MODE 0x2 - -#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_OFF1_ON2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_ICH_NVM_SIG_WORD 0x13 -#define E1000_ICH_NVM_SIG_MASK 0xC000 -#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 -#define E1000_ICH_NVM_SIG_VALUE 0x80 - -#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 - -#define E1000_FEXTNVM_SW_CONFIG 1 -#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */ - -#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL - -#define E1000_ICH_RAR_ENTRIES 7 - -#define PHY_PAGE_SHIFT 5 -#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ - ((reg) & MAX_PHY_REG_ADDRESS)) -#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ -#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ -#define IGP3_CAPABILITY PHY_REG(776, 19) /* Capability */ -#define IGP3_PM_CTRL PHY_REG(769, 20) /* Power Management Control */ - -#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 -#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 -#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 -#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020 - -/* PHY Wakeup Registers and defines */ -#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) -#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) -#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) -#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) -#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) -#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) -#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) -#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) -#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) - -#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ -#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ -#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ -#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ -#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ -#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ -#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ - -#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ -#define HV_MUX_DATA_CTRL PHY_REG(776, 16) -#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 -#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 -#define HV_SCC_UPPER PHY_REG(778, 16) /* Single Collision Count */ -#define HV_SCC_LOWER PHY_REG(778, 17) -#define HV_ECOL_UPPER PHY_REG(778, 18) /* Excessive Collision Count */ -#define HV_ECOL_LOWER PHY_REG(778, 19) -#define HV_MCC_UPPER PHY_REG(778, 20) /* Multiple Collision Count */ -#define HV_MCC_LOWER PHY_REG(778, 21) -#define HV_LATECOL_UPPER PHY_REG(778, 23) /* Late Collision Count */ -#define HV_LATECOL_LOWER PHY_REG(778, 24) -#define HV_COLC_UPPER PHY_REG(778, 25) /* Collision Count */ -#define HV_COLC_LOWER PHY_REG(778, 26) -#define HV_DC_UPPER PHY_REG(778, 27) /* Defer Count */ -#define HV_DC_LOWER PHY_REG(778, 28) -#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ -#define HV_TNCRS_LOWER PHY_REG(778, 30) - -#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ - -#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ -#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ - -/* SMBus Address Phy Register */ -#define HV_SMB_ADDR PHY_REG(768, 26) -#define HV_SMB_ADDR_PEC_EN 0x0200 -#define HV_SMB_ADDR_VALID 0x0080 - -/* Strapping Option Register - RO */ -#define E1000_STRAP 0x0000C -#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 -#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 - -/* OEM Bits Phy Register */ -#define HV_OEM_BITS PHY_REG(768, 25) -#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ -#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ -#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ - -#define LCD_CFG_PHY_ADDR_BIT 0x0020 /* Phy address bit from LCD Config word */ - -#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */ - -/* - * Additional interrupts need to be handled for ICH family: - * DSW = The FW changed the status of the DISSW bit in FWSM - * PHYINT = The LAN connected device generates an interrupt - * EPRST = Manageability reset event - */ -#define IMS_ICH_ENABLE_MASK (\ - E1000_IMS_DSW | \ - E1000_IMS_PHYINT | \ - E1000_IMS_EPRST) - -/* Additional interrupt register bit definitions */ -#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */ -#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ -#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ - -/* Security Processing bit Indication */ -#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000 -#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000 -#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000 -#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000 -#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000 - - -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state); -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); -s32 e1000e_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); -s32 e1000e_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_config); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.c deleted file mode 100644 index d96b279f7..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.c +++ /dev/null @@ -1,1883 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000e.h" - -static u32 e1000e_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); -static s32 e1000e_set_default_fc_generic(struct e1000_hw *hw); -static s32 e1000e_commit_fc_settings_generic(struct e1000_hw *hw); -static s32 e1000e_poll_fiber_serdes_link_generic(struct e1000_hw *hw); -static s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw); -static void e1000e_set_lan_id_multi_port_pcie(struct e1000_hw *hw); - -/** - * e1000e_init_mac_ops_generic - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void e1000e_init_mac_ops_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - /* General Setup */ - mac->ops.set_lan_id = e1000e_set_lan_id_multi_port_pcie; - mac->ops.read_mac_addr = e1000e_read_mac_addr_generic; - mac->ops.config_collision_dist = e1000e_config_collision_dist; - /* LINK */ - mac->ops.wait_autoneg = e1000e_wait_autoneg; - /* Management */ -#if 0 - mac->ops.mng_host_if_write = e1000e_mng_host_if_write_generic; - mac->ops.mng_write_cmd_header = e1000e_mng_write_cmd_header_generic; - mac->ops.mng_enable_host_if = e1000e_mng_enable_host_if_generic; -#endif - /* VLAN, MC, etc. */ - mac->ops.rar_set = e1000e_rar_set; - mac->ops.validate_mdi_setting = e1000e_validate_mdi_setting_generic; -} - -/** - * e1000e_get_bus_info_pcie - Get PCIe bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCIe), and PCIe function. - **/ -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - - s32 ret_val; - u16 pcie_link_status; - - bus->type = e1000_bus_type_pci_express; - bus->speed = e1000_bus_speed_2500; - - ret_val = e1000e_read_pcie_cap_reg(hw, - PCIE_LINK_STATUS, - &pcie_link_status); - if (ret_val) - bus->width = e1000_bus_width_unknown; - else - bus->width = (enum e1000_bus_width)((pcie_link_status & - PCIE_LINK_WIDTH_MASK) >> - PCIE_LINK_WIDTH_SHIFT); - - mac->ops.set_lan_id(hw); - - return E1000_SUCCESS; -} - -/** - * e1000e_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices - * - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading memory-mapped registers - * and swaps the port value if requested. - **/ -static void e1000e_set_lan_id_multi_port_pcie(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u32 reg; - - /* - * The status register reports the correct function number - * for the device regardless of function swap state. - */ - reg = er32(STATUS); - bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; -} - -/** - * e1000e_set_lan_id_single_port - Set LAN id for a single port device - * @hw: pointer to the HW structure - * - * Sets the LAN function id to zero for a single port device. - **/ -void e1000e_set_lan_id_single_port(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - - bus->func = 0; -} - -/** - * e1000e_clear_vfta_generic - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -void e1000e_clear_vfta_generic(struct e1000_hw *hw) -{ - u32 offset; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); - e1e_flush(); - } -} - -/** - * e1000e_write_vfta_generic - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: register offset in VLAN filter table - * @value: register value written to VLAN filter table - * - * Writes value at the given offset in the register array which stores - * the VLAN filter table. - **/ -void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) -{ - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - e1e_flush(); -} - -/** - * e1000e_init_rx_addrs - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setups the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ADDR_LEN] = {0}; - - /* Setup the receive address */ - e_dbg("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - e_dbg("Clearing RAR[1-%u]\n", rar_count-1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - -/** - * e1000e_check_alt_mac_addr_generic - Check for alternate MAC addr - * @hw: pointer to the HW structure - * - * Checks the nvm for an alternate MAC address. An alternate MAC address - * can be setup by pre-boot software and must be treated like a permanent - * address and must override the actual permanent MAC address. If an - * alternate MAC address is found it is programmed into RAR0, replacing - * the permanent address that was installed into RAR0 by the Si on reset. - * This function will return SUCCESS unless it encounters an error while - * reading the EEPROM. - **/ -s32 e1000e_check_alt_mac_addr_generic(struct e1000_hw *hw) -{ - u32 i; - s32 ret_val = E1000_SUCCESS; - u16 offset, nvm_alt_mac_addr_offset, nvm_data; - u8 alt_mac_addr[ETH_ADDR_LEN]; - - ret_val = e1000e_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - if (nvm_alt_mac_addr_offset == 0xFFFF) { - /* There is no Alternate MAC Address */ - goto out; - } - - if (hw->bus.func == E1000_FUNC_1) - nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; - for (i = 0; i < ETH_ADDR_LEN; i += 2) { - offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = e1000e_read_nvm(hw, offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - alt_mac_addr[i] = (u8)(nvm_data & 0xFF); - alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); - } - - /* if multicast bit is set, the alternate address will not be used */ - if (alt_mac_addr[0] & 0x01) { - e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); - goto out; - } - - /* - * We have a valid alternate MAC address, and we want to treat it the - * same as the normal permanent MAC address stored by the HW into the - * RAR. Do this by mapping this address into RAR0. - */ - hw->mac.ops.rar_set(hw, alt_mac_addr, 0); - -out: - return ret_val; -} - -/** - * e1000e_rar_set - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* - * HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | - ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - /* - * Some bridges will combine consecutive 32-bit writes into - * a single burst write, which will malfunction on some parts. - * The flushes avoid this. - */ - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); -} - -/** - * e1000e_mta_set_generic - Set multicast filter table address - * @hw: pointer to the HW structure - * @hash_value: determines the MTA register and bit to set - * - * The multicast table address is a register array of 32-bit registers. - * The hash_value is used to determine what register the bit is in, the - * current value is read, the new bit is OR'd in and the new value is - * written back into the register. - **/ -void e1000e_mta_set_generic(struct e1000_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg, mta; - - /* - * The MTA is a register array of 32-bit registers. It is - * treated like an array of (32*mta_reg_count) bits. We want to - * set bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The (hw->mac.mta_reg_count - 1) serves as a - * mask to bits 31:5 of the hash value which gives us the - * register we're modifying. The hash bit within that register - * is determined by the lower 5 bits of the hash value. - */ - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); - - mta |= (1 << hash_bit); - - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); - e1e_flush(); -} - -/** - * e1000e_update_mc_addr_list_generic - 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 entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32) i < mc_addr_count; i++) { - hash_value = e1000e_hash_mc_addr_generic(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ADDR_LEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - e1e_flush(); -} - -/** - * e1000e_hash_mc_addr_generic - 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 - * e1000e_mta_set_generic() - **/ -static u32 e1000e_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value, hash_mask; - u8 bit_shift = 0; - - /* Register count multiplied by bits per register */ - hash_mask = (hw->mac.mta_reg_count * 32) - 1; - - /* - * For a mc_filter_type of 0, 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++; - - /* - * The portion of the address that is used for the hash table - * is determined by the mc_filter_type setting. - * The algorithm is such that there is a total of 8 bits of shifting. - * The bit_shift for a mc_filter_type of 0 represents the number of - * left-shifts where the MSB of mc_addr[5] would still fall within - * the hash_mask. Case 0 does this exactly. Since there are a total - * of 8 bits of shifting, then mc_addr[4] will shift right the - * remaining number of bits. Thus 8 - bit_shift. The rest of the - * cases are a variation of this algorithm...essentially raising the - * number of bits to shift mc_addr[5] left, while still keeping the - * 8-bit shifting total. - * - * For example, given the following Destination MAC Address and an - * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), - * we can see that the bit_shift for case 0 is 4. These are the hash - * values resulting from each mc_filter_type... - * [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - * - * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 - * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 - * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 - * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 - */ - switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; - } - - hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16) mc_addr[5]) << bit_shift))); - - return hash_value; -} - -/** - * e1000e_clear_hw_cntrs_base - Clear base hardware counters - * @hw: pointer to the HW structure - * - * Clears the base hardware counters by reading the counter registers. - **/ -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw __unused) -{ -#if 0 - er32(CRCERRS); - er32(SYMERRS); - er32(MPC); - er32(SCC); - er32(ECOL); - er32(MCC); - er32(LATECOL); - er32(COLC); - er32(DC); - er32(SEC); - er32(RLEC); - er32(XONRXC); - er32(XONTXC); - er32(XOFFRXC); - er32(XOFFTXC); - er32(FCRUC); - er32(GPRC); - er32(BPRC); - er32(MPRC); - er32(GPTC); - er32(GORCL); - er32(GORCH); - er32(GOTCL); - er32(GOTCH); - er32(RNBC); - er32(RUC); - er32(RFC); - er32(ROC); - er32(RJC); - er32(TORL); - er32(TORH); - er32(TOTL); - er32(TOTH); - er32(TPR); - er32(TPT); - er32(MPTC); - er32(BPTC); -#endif -} - -/** - * e1000e_check_for_copper_link - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -s32 e1000e_check_for_copper_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - /* - * We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) - goto out; /* No link detected */ - - mac->get_link_status = false; - - /* - * Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* - * If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - e1000e_config_collision_dist(hw); - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) - e_dbg("Error configuring flow control\n"); - -out: - return ret_val; -} - -/** - * e1000e_check_for_fiber_link - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - -out: - return ret_val; -} - -/** - * e1000e_check_for_serdes_link - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* - * If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - forced.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & er32(TXCW)) { - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg " - "completed sucessfully.\n"); - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - no sync.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - autoneg failed\n"); - } - } - -out: - return ret_val; -} - -/** - * e1000e_setup_link - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -s32 e1000e_setup_link(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - /* - * In the case of the phy reset being blocked, we already have a link. - * We do not need to set it up again. - */ - if (hw->phy.ops.check_reset_block) - if (e1000e_check_reset_block(hw)) - goto out; - - /* - * If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = e1000e_set_default_fc_generic(hw); - if (ret_val) - goto out; - } - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); - - /* Call the necessary media_type subroutine to configure the link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - goto out; - - /* - * Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - e_dbg("Initializing the Flow Control address, type and timer regs\n"); - ew32(FCT, FLOW_CONTROL_TYPE); - ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); - ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); - - ew32(FCTTV, hw->fc.pause_time); - - ret_val = e1000e_set_fc_watermarks(hw); - -out: - return ret_val; -} - -/** - * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. - **/ -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - e1000e_config_collision_dist(hw); - - ret_val = e1000e_commit_fc_settings_generic(hw); - if (ret_val) - goto out; - - /* - * Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - e_dbg("Auto-negotiation enabled\n"); - - ew32(CTRL, ctrl); - e1e_flush(); - msleep(1); - - /* - * For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. - */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (er32(CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000e_poll_fiber_serdes_link_generic(hw); - } else { - e_dbg("No signal detected\n"); - } - -out: - return ret_val; -} - -/** - * e1000e_config_collision_dist - 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 e1000e_config_collision_dist(struct e1000_hw *hw) -{ - u32 tctl; - - tctl = er32(TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - ew32(TCTL, tctl); - e1e_flush(); -} - -/** - * e1000e_poll_fiber_serdes_link_generic - Poll for link up - * @hw: pointer to the HW structure - * - * Polls for link up by reading the status register, if link fails to come - * up with auto-negotiation, then the link is forced if a signal is detected. - **/ -static s32 e1000e_poll_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 i, status; - s32 ret_val = E1000_SUCCESS; - - /* - * If we have a signal (the cable is plugged in, or assumed true for - * serdes media) then poll for a "Link-Up" indication in the Device - * Status Register. Time-out if a link isn't seen in 500 milliseconds - * seconds (Auto-negotiation should complete in less than 500 - * milliseconds even if the other end is doing it in SW). - */ - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - msleep(10); - status = er32(STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == FIBER_LINK_UP_LIMIT) { - e_dbg("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = 1; - /* - * AutoNeg failed to achieve a link, so we'll call - * mac->check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = hw->mac.ops.check_for_link(hw); - if (ret_val) { - e_dbg("Error while checking for link\n"); - goto out; - } - mac->autoneg_failed = 0; - } else { - mac->autoneg_failed = 0; - e_dbg("Valid Link Found\n"); - } - -out: - return ret_val; -} - -/** - * e1000e_commit_fc_settings_generic - Configure flow control - * @hw: pointer to the HW structure - * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. - **/ -static s32 e1000e_commit_fc_settings_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - s32 ret_val = E1000_SUCCESS; - - /* - * Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric RX - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - - ew32(TXCW, txcw); - mac->txcw = txcw; - -out: - return ret_val; -} - -/** - * e1000e_set_fc_watermarks - Set flow control high/low watermarks - * @hw: pointer to the HW structure - * - * Sets the flow control high/low threshold (watermark) registers. If - * flow control XON frame transmission is enabled, then set XON frame - * transmission as well. - **/ -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u32 fcrtl = 0, fcrth = 0; - - /* - * Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames is not enabled, then these - * registers will be set to 0. - */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - fcrtl = hw->fc.low_water; - if (hw->fc.send_xon) - fcrtl |= E1000_FCRTL_XONE; - - fcrth = hw->fc.high_water; - } - ew32(FCRTL, fcrtl); - ew32(FCRTH, fcrth); - - return ret_val; -} - -/** - * e1000e_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -static s32 e1000e_set_default_fc_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 nvm_data; - - /* - * Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - ret_val = e1000e_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); - - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == - NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - -out: - return ret_val; -} - -/** - * e1000e_force_mac_fc - Force the MAC's flow control settings - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the - * device control register to reflect the adapter settings. TFCE and RFCE - * need to be explicitly set by software when a copper PHY is used because - * autonegotiation is managed by the PHY rather than the MAC. Software must - * also configure these bits when link is forced on a fiber connection. - **/ -s32 e1000e_force_mac_fc(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - - /* - * Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and Tx flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); - - switch (hw->fc.current_mode) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ew32(CTRL, ctrl); - -out: - return ret_val; -} - -/** - * e1000e_config_fc_after_link_up - Configures flow control after link - * @hw: pointer to the HW structure - * - * Checks the status of auto-negotiation after link up to ensure that the - * speed and duplex were not forced. If the link needed to be forced, then - * flow control needs to be forced also. If auto-negotiation is enabled - * and did not fail, then we configure flow control based on our link - * partner. - **/ -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; - u16 speed, duplex; - - /* - * Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) - ret_val = e1000e_force_mac_fc(hw); - } else { - if (hw->phy.media_type == e1000_media_type_copper) - ret_val = e1000e_force_mac_fc(hw); - } - - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - goto out; - } - - /* - * Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* - * Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - - if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { - e_dbg("Copper PHY and Auto Neg " - "has not completed.\n"); - goto out; - } - - /* - * The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (Address 4) and the Auto_Negotiation Base - * Page Ability Register (Address 5) to determine how - * flow control was negotiated. - */ - ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg); - if (ret_val) - goto out; - ret_val = e1e_rphy(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg); - if (ret_val) - goto out; - - /* - * Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | E1000_fc_full - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\r\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = " - "RX PAUSE frames only.\r\n"); - } - } - /* - * For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = TX PAUSE frames only.\r\n"); - } - /* - * For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = RX PAUSE frames only.\r\n"); - } else { - /* - * Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\r\n"); - } - - /* - * Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - e_dbg("Error getting link speed and duplex\n"); - goto out; - } - - if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; - - /* - * Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000e_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Read the status register for the current speed/duplex and store the current - * speed and duplex for copper connections. - **/ -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - u32 status; - - status = er32(STATUS); - if (status & E1000_STATUS_SPEED_1000) { - *speed = SPEED_1000; - e_dbg("1000 Mbs, "); - } else if (status & E1000_STATUS_SPEED_100) { - *speed = SPEED_100; - e_dbg("100 Mbs, "); - } else { - *speed = SPEED_10; - e_dbg("10 Mbs, "); - } - - if (status & E1000_STATUS_FD) { - *duplex = FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } else { - *duplex = HALF_DUPLEX; - e_dbg("Half Duplex\n"); - } - - return E1000_SUCCESS; -} - -/** - * e1000e_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Sets the speed and duplex to gigabit full duplex (the only possible option) - * for fiber/serdes links. - **/ -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw __unused, - u16 *speed, u16 *duplex) -{ - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - - return E1000_SUCCESS; -} - -/** - * e1000e_get_hw_semaphore - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - s32 ret_val = E1000_SUCCESS; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - udelay(50); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - udelay(50); - } - - if (i == timeout) { - /* Release semaphores */ - e1000e_put_hw_semaphore(hw); - e_dbg("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_put_hw_semaphore - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void e1000e_put_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} -/** - * e1000e_get_auto_rd_done - Check for auto read completion - * @hw: pointer to the HW structure - * - * Check EEPROM for Auto Read done bit. - **/ -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) -{ - s32 i = 0; - s32 ret_val = E1000_SUCCESS; - - while (i < AUTO_READ_DONE_TIMEOUT) { - if (er32(EECD) & E1000_EECD_AUTO_RD) - break; - msleep(1); - i++; - } - - if (i == AUTO_READ_DONE_TIMEOUT) { - e_dbg("Auto read by HW from NVM has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_valid_led_default - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000e_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - -out: - return ret_val; -} - -/** - * e1000e_id_led_init - - * @hw: pointer to the HW structure - * - **/ -s32 e1000e_id_led_init(struct e1000_hw *hw __unused) -{ -#if 0 - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 data, i, temp; - const u16 led_mask = 0x0F; - - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - goto out; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - -out: - return ret_val; -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_setup_led_generic - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -s32 e1000e_setup_led_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ledctl; - s32 ret_val = E1000_SUCCESS; - - if (hw->mac.ops.setup_led != e1000e_setup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - if (hw->phy.media_type == e1000_media_type_fiber) { - ledctl = er32(LEDCTL); - hw->mac.ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - ew32(LEDCTL, ledctl); - } else if (hw->phy.media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->mac.ledctl_mode1); - } - -out: - return ret_val; -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_cleanup_led_generic - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw __unused) -{ -#if 0 - s32 ret_val = E1000_SUCCESS; - - if (hw->mac.ops.cleanup_led != e1000e_cleanup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ew32(LEDCTL, hw->mac.ledctl_default); - -out: - return ret_val; -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_blink_led - Blink LED - * @hw: pointer to the HW structure - * - * Blink the LEDs which are set to be on. - **/ -s32 e1000e_blink_led(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ledctl_blink = 0; - u32 i; - - if (hw->phy.media_type == e1000_media_type_fiber) { - /* always blink LED0 for PCI-E fiber */ - ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); - } else { - /* - * set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); - } - - ew32(LEDCTL, ledctl_blink); -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_led_on_generic - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -s32 e1000e_led_on_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode2); - break; - default: - break; - } -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_led_off_generic - Turn LED off - * @hw: pointer to the HW structure - * - * Turn LED off. - **/ -s32 e1000e_led_off_generic(struct e1000_hw *hw __unused) -{ -#if 0 - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode1); - break; - default: - break; - } -#endif - return E1000_SUCCESS; -} - -/** - * e1000e_set_pcie_no_snoop - Set PCI-express capabilities - * @hw: pointer to the HW structure - * @no_snoop: bitmap of snoop events - * - * Set the PCI-express register to snoop for events enabled in 'no_snoop'. - **/ -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) -{ - u32 gcr; - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - if (no_snoop) { - gcr = er32(GCR); - gcr &= ~(PCIE_NO_SNOOP_ALL); - gcr |= no_snoop; - ew32(GCR, gcr); - } -out: - return; -} - -/** - * e1000e_disable_pcie_master - Disables PCI-express master access - * @hw: pointer to the HW structure - * - * Returns 0 (E1000_SUCCESS) if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused - * the master requests to be disabled. - * - * Disables PCI-Express master access and verifies there are no pending - * requests. - **/ -s32 e1000e_disable_pcie_master(struct e1000_hw *hw) -{ - u32 ctrl; - s32 timeout = MASTER_DISABLE_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; - ew32(CTRL, ctrl); - - while (timeout) { - if (!(er32(STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE)) - break; - udelay(100); - timeout--; - } - - if (!timeout) { - e_dbg("Master requests are pending.\n"); - ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void e1000e_reset_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - goto out; - } - - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - ew32(AIT, 0); -out: - return; -} - -/** - * e1000e_update_adaptive - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void e1000e_update_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - goto out; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - ew32(AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - ew32(AIT, 0); - } - } -out: - return; -} - -/** - * e1000e_validate_mdi_setting_generic - Verify MDI/MDIx settings - * @hw: pointer to the HW structure - * - * Verify that when not using auto-negotiation that MDI/MDIx is correctly - * set, which is forced to MDI mode only. - **/ -static s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { - e_dbg("Invalid MDI setting detected\n"); - hw->phy.mdix = 1; - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: - return ret_val; -} diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.h deleted file mode 100644 index 5b8a42517..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_mac.h +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_MAC_H_ -#define _E1000E_MAC_H_ - -/* - * Functions that should not be called directly from drivers but can be used - * by other files in this 'shared code' - */ -void e1000e_init_mac_ops_generic(struct e1000_hw *hw); -s32 e1000e_blink_led(struct e1000_hw *hw); -s32 e1000e_check_for_copper_link(struct e1000_hw *hw); -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); -s32 e1000e_disable_pcie_master(struct e1000_hw *hw); -s32 e1000e_force_mac_fc(struct e1000_hw *hw); -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); -void e1000e_set_lan_id_single_port(struct e1000_hw *hw); -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -s32 e1000e_id_led_init(struct e1000_hw *hw); -s32 e1000e_led_on_generic(struct e1000_hw *hw); -s32 e1000e_led_off_generic(struct e1000_hw *hw); -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); -s32 e1000e_setup_led_generic(struct e1000_hw *hw); -s32 e1000e_setup_link(struct e1000_hw *hw); - -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); -void e1000e_clear_vfta_generic(struct e1000_hw *hw); -void e1000e_config_collision_dist(struct e1000_hw *hw); -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); -void e1000e_mta_set_generic(struct e1000_hw *hw, u32 hash_value); -void e1000e_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); -void e1000e_put_hw_semaphore(struct e1000_hw *hw); -void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); -s32 e1000e_check_alt_mac_addr_generic(struct e1000_hw *hw); -void e1000e_reset_adaptive(struct e1000_hw *hw); -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); -void e1000e_update_adaptive(struct e1000_hw *hw); -void e1000e_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_main.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_main.c deleted file mode 100644 index e5cb2490a..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_main.c +++ /dev/null @@ -1,1265 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. - - Portions Copyright(c) 2010 Marty Connor - Portions Copyright(c) 2010 Entity Cyber, Inc. - Portions Copyright(c) 2010 Northrop Grumman 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000e.h" - -static s32 e1000e_get_variants_82571(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - static int global_quad_port_a; /* global port a indication */ - struct pci_device *pdev = adapter->pdev; - u16 eeprom_data = 0; - int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; - - /* tag quad port adapters first, it's used below */ - switch (pdev->device) { - case E1000_DEV_ID_82571EB_QUAD_COPPER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: - case E1000_DEV_ID_82571PT_QUAD_COPPER: - adapter->flags |= FLAG_IS_QUAD_PORT; - /* mark the first port */ - if (global_quad_port_a == 0) - adapter->flags |= FLAG_IS_QUAD_PORT_A; - /* Reset for multiple quad port adapters */ - global_quad_port_a++; - if (global_quad_port_a == 4) - global_quad_port_a = 0; - break; - default: - break; - } - - switch (adapter->hw.mac.type) { - case e1000_82571: - /* these dual ports don't have WoL on port B at all */ - if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) || - (pdev->device == E1000_DEV_ID_82571EB_SERDES) || - (pdev->device == E1000_DEV_ID_82571EB_COPPER)) && - (is_port_b)) - adapter->flags &= ~FLAG_HAS_WOL; - /* quad ports only support WoL on port A */ - if (adapter->flags & FLAG_IS_QUAD_PORT && - (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) - adapter->flags &= ~FLAG_HAS_WOL; - /* Does not support WoL on any port */ - if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) - adapter->flags &= ~FLAG_HAS_WOL; - break; - - case e1000_82573: - if (pdev->device == E1000_DEV_ID_82573L) { - if (e1000e_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1, - &eeprom_data) < 0) - break; - if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) { - adapter->flags |= FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = DEFAULT_JUMBO; - } - } - break; - - default: - break; - } - - return 0; -} - -static struct e1000_info e1000_82571_info = { - .mac = e1000_82571, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_RESET_OVERWRITES_LAA /* errata */ - | FLAG_TARC_SPEED_MODE_BIT /* errata */ - | FLAG_APME_CHECK_PORT_B, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_82571, - .get_variants = e1000e_get_variants_82571, -}; - -static struct e1000_info e1000_82572_info = { - .mac = e1000_82572, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_TARC_SPEED_MODE_BIT, /* errata */ - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_82571, - .get_variants = e1000e_get_variants_82571, -}; - -static struct e1000_info e1000_82573_info = { - .mac = e1000_82573, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_ERT - | FLAG_HAS_SWSM_ON_LOAD, - .pba = 20, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, - .init_ops = e1000e_init_function_pointers_82571, - .get_variants = e1000e_get_variants_82571, -}; - -static struct e1000_info e1000_82574_info = { - .mac = e1000_82574, - .flags = FLAG_HAS_HW_VLAN_FILTER -#ifdef CONFIG_E1000E_MSIX - | FLAG_HAS_MSIX -#endif - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_CTRLEXT_ON_LOAD, - .pba = 20, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_82571, - .get_variants = e1000e_get_variants_82571, -}; - -static struct e1000_info e1000_82583_info = { - .mac = e1000_82583, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_CTRLEXT_ON_LOAD, - .pba = 20, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, - .init_ops = e1000e_init_function_pointers_82571, - .get_variants = e1000e_get_variants_82571, -}; - -static struct e1000_info e1000_es2_info = { - .mac = e1000_80003es2lan, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_RX_NEEDS_RESTART /* errata */ - | FLAG_TARC_SET_BIT_ZERO /* errata */ - | FLAG_APME_CHECK_PORT_B - | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ - | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_80003es2lan, - .get_variants = NULL, -}; - -static s32 e1000e_get_variants_ich8lan(struct e1000_adapter *adapter) -{ - if (adapter->hw.phy.type == e1000_phy_ife) { - adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN; - } - - if ((adapter->hw.mac.type == e1000_ich8lan) && - (adapter->hw.phy.type == e1000_phy_igp_3)) - adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; - - return 0; -} - -static struct e1000_info e1000_ich8_info = { - .mac = e1000_ich8lan, - .flags = FLAG_HAS_WOL - | FLAG_IS_ICH - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 8, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, - .init_ops = e1000e_init_function_pointers_ich8lan, - .get_variants = e1000e_get_variants_ich8lan, -}; - -static struct e1000_info e1000_ich9_info = { - .mac = e1000_ich9lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_ERT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 10, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_ich8lan, - .get_variants = e1000e_get_variants_ich8lan, -}; - -static struct e1000_info e1000_ich10_info = { - .mac = e1000_ich10lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_ERT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 10, - .max_hw_frame_size = DEFAULT_JUMBO, - .init_ops = e1000e_init_function_pointers_ich8lan, - .get_variants = e1000e_get_variants_ich8lan, -}; - -static struct e1000_info e1000_pch_info = { - .mac = e1000_pchlan, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_RX_CSUM_ENABLED - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ - | FLAG_APME_IN_WUC, - .pba = 26, - .max_hw_frame_size = 4096, - .init_ops = e1000e_init_function_pointers_ich8lan, - .get_variants = e1000e_get_variants_ich8lan, -}; - -static const struct e1000_info *e1000_info_tbl[] = { - [board_82571] = &e1000_82571_info, - [board_82572] = &e1000_82572_info, - [board_82573] = &e1000_82573_info, - [board_82574] = &e1000_82574_info, - [board_82583] = &e1000_82583_info, - [board_80003es2lan] = &e1000_es2_info, - [board_ich8lan] = &e1000_ich8_info, - [board_ich9lan] = &e1000_ich9_info, - [board_ich10lan] = &e1000_ich10_info, - [board_pchlan] = &e1000_pch_info, -}; - -/* Low-level support routines */ - -s32 e1000e_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) -{ - u16 cap_offset; - - cap_offset = pci_find_capability(hw->adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_read_config_word(hw->adapter->pdev, cap_offset + reg, value); - - return E1000_SUCCESS; -} - -/** - * e1000e_irq_disable - Mask off interrupt generation on the NIC - **/ -static void e1000e_irq_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMC, ~0); - e1e_flush(); -} - -/** - * e1000e_irq_enable - Enable default interrupt generation settings - **/ -static void e1000e_irq_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMS, IMS_ENABLE_MASK); - e1e_flush(); -} - -/** - * e1000_get_hw_control - get control of the h/w from f/w - * @adapter: address of board private structure - * - * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that - * the driver is loaded. For AMT version (only with 82573) - * of the f/w this means that the network i/f is open. - **/ -static void e1000e_get_hw_control(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - u32 swsm; - - /* Let firmware know the driver has taken over */ - if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); - } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { - ctrl_ext = er32(CTRL_EXT); - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); - } -} - -/** - * e1000e_power_up_phy - restore link in case the phy was powered down - * @adapter: address of board private structure - * - * The phy may be powered down to save power and turn off link when the - * driver is unloaded and wake on lan is not enabled (among others) - * *** this routine MUST be followed by a call to e1000e_reset *** - **/ -void e1000e_power_up_phy(struct e1000_adapter *adapter) -{ - if (adapter->hw.phy.ops.power_up) - adapter->hw.phy.ops.power_up(&adapter->hw); - - adapter->hw.mac.ops.setup_link(&adapter->hw); -} - -/** - * e1000_power_down_phy - Power down the PHY - * - * Power down the PHY so no link is implied when interface is down. - * The PHY cannot be powered down if management or WoL is active. - */ -void e1000e_power_down_phy(struct e1000_adapter *adapter) -{ - /* WoL is enabled */ - if (adapter->wol) - return; - - if (adapter->hw.phy.ops.power_down) - adapter->hw.phy.ops.power_down(&adapter->hw); -} - -/** - * e1000e_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 e1000e_reset(struct e1000_adapter *adapter) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_fc_info *fc = &adapter->hw.fc; - u32 pba = adapter->pba; - struct e1000_hw *hw = &adapter->hw; - - /* Reset Packet Buffer Allocation to default */ - ew32(PBA, pba); - - hw->fc.requested_mode = e1000_fc_none; - fc->current_mode = fc->requested_mode; - - /* Allow time for pending master requests to run */ - mac->ops.reset_hw(hw); - - /* - * For parts with AMT enabled, let the firmware know - * that the network interface is in control - */ - if (adapter->flags & FLAG_HAS_AMT) - e1000e_get_hw_control(adapter); - - ew32(WUC, 0); - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) - e1e_wphy(&adapter->hw, BM_WUC, 0); - - if (mac->ops.init_hw(hw)) - DBG("Hardware Error\n"); - - /* additional part of the flow-control workaround above */ - if (hw->mac.type == e1000_pchlan) - ew32(FCRTV_PCH, 0x1000); - - e1000e_reset_adaptive(hw); - - e1000e_get_phy_info(hw); - - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && - !(adapter->flags & FLAG_SMART_POWER_DOWN)) { - u16 phy_data = 0; - /* - * speed up time to link by disabling smart power down, ignore - * the return value of this function because there is nothing - * different we would do if it failed - */ - e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - phy_data &= ~IGP02E1000_PM_SPD; - e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); - } -} - -static int e1000e_sw_init(struct e1000_adapter *adapter) -{ - s32 rc; - - /* Set various function pointers */ - adapter->ei->init_ops(&adapter->hw); - - rc = adapter->hw.mac.ops.init_params(&adapter->hw); - if (rc) - return rc; - - rc = adapter->hw.nvm.ops.init_params(&adapter->hw); - if (rc) - return rc; - - rc = adapter->hw.phy.ops.init_params(&adapter->hw); - if (rc) - return rc; - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000e_irq_disable(adapter); - - return E1000_SUCCESS; -} - -/* TX support routines */ - -/** - * e1000_setup_tx_resources - allocate Tx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000e_setup_tx_resources ( struct e1000_adapter *adapter ) -{ - DBGP ( "e1000_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; -} - -/** - * e1000_process_tx_packets - process transmitted packets - * - * @v netdev network interface device structure - **/ -static void e1000e_process_tx_packets ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t tx_status; - struct e1000_tx_desc *tx_curr_desc; - - /* Check status of transmitted packets - */ - DBG ( "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->upper.data; - - 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 ); - - if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | - E1000_TXD_STAT_TU ) ) { - netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL ); - DBG ( "Error transmitting packet, tx_status: %#08x\n", - tx_status ); - } else { - 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; - } -} - -static void e1000e_free_tx_resources ( struct e1000_adapter *adapter ) -{ - DBGP ( "e1000_free_tx_resources\n" ); - - free_dma ( adapter->tx_base, adapter->tx_ring_size ); -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000e_configure_tx ( struct e1000_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - u32 tctl, tipg, tarc; - u32 ipgr1, ipgr2; - - DBGP ( "e1000_configure_tx\n" ); - - /* disable transmits while setting up the descriptors */ - tctl = E1000_READ_REG ( hw, E1000_TCTL ); - E1000_WRITE_REG ( hw, E1000_TCTL, tctl & ~E1000_TCTL_EN ); - e1e_flush(); - mdelay(10); - - E1000_WRITE_REG ( hw, E1000_TDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDBAL(0), virt_to_bus ( adapter->tx_base ) ); - E1000_WRITE_REG ( hw, E1000_TDLEN(0), adapter->tx_ring_size ); - - DBG ( "E1000_TDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_TDBAL(0) ) ); - DBG ( "E1000_TDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_TDLEN(0) ) ); - - /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG ( hw, E1000_TDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDT(0), 0 ); - - adapter->tx_head = 0; - adapter->tx_tail = 0; - adapter->tx_fill_ctr = 0; - - /* Set the default values for the Tx Inter Packet Gap timer */ - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; /* 8 */ - ipgr1 = DEFAULT_82543_TIPG_IPGR1; /* 8 */ - ipgr2 = DEFAULT_82543_TIPG_IPGR2; /* 6 */ - - if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN) - ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /* 7 */ - - tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; - ew32(TIPG, tipg); - - /* Program the Transmit Control Register */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { - tarc = er32(TARC(0)); - /* - * set the speed mode bit, we'll clear it if we're not at - * gigabit link later - */ -#define SPEED_MODE_BIT (1 << 21) - tarc |= SPEED_MODE_BIT; - ew32(TARC(0), tarc); - } - - /* errata: program both queues to unweighted RR */ - if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { - tarc = er32(TARC(0)); - tarc |= 1; - ew32(TARC(0), tarc); - tarc = er32(TARC(1)); - tarc |= 1; - ew32(TARC(1), tarc); - } - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* enable Report Status bit */ - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - /* - * enable transmits in the hardware, need to do this - * after setting TARC(0) - */ - tctl |= E1000_TCTL_EN; - ew32(TCTL, tctl); - e1e_flush(); - - e1000e_config_collision_dist(hw); -} - -/* RX support routines */ - -static void e1000e_free_rx_resources ( struct e1000_adapter *adapter ) -{ - int i; - - DBGP ( "e1000_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] ); - } -} - -/** - * e1000_refill_rx_ring - allocate Rx io_buffers - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000e_refill_rx_ring ( struct e1000_adapter *adapter ) -{ - int i, rx_curr; - int rc = 0; - struct e1000_rx_desc *rx_curr_desc; - struct e1000_hw *hw = &adapter->hw; - struct io_buffer *iob; - - DBGP ("e1000_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->status & 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; - - if ( ! iob ) { - DBG ( "alloc_iob failed\n" ); - rc = -ENOMEM; - break; - } else { - rx_curr_desc->buffer_addr = virt_to_bus ( iob->data ); - - E1000_WRITE_REG ( hw, E1000_RDT(0), rx_curr ); - } - } - return rc; -} - -/** - * e1000_setup_rx_resources - allocate Rx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int e1000e_setup_rx_resources ( struct e1000_adapter *adapter ) -{ - int i, rc = 0; - - DBGP ( "e1000_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++ ) { - /* let e1000_refill_rx_ring() io_buffer allocations */ - adapter->rx_iobuf[i] = NULL; - } - - /* allocate io_buffers */ - rc = e1000e_refill_rx_ring ( adapter ); - if ( rc < 0 ) - e1000e_free_rx_resources ( adapter ); - - return rc; -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000e_configure_rx ( struct e1000_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; - - DBGP ( "e1000_configure_rx\n" ); - - /* disable receives while setting up the descriptors */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - e1e_flush(); - mdelay(10); - - adapter->rx_curr = 0; - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring */ - - E1000_WRITE_REG ( hw, E1000_RDBAL(0), virt_to_bus ( adapter->rx_base ) ); - E1000_WRITE_REG ( hw, E1000_RDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDLEN(0), adapter->rx_ring_size ); - - E1000_WRITE_REG ( hw, E1000_RDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDT(0), NUM_RX_DESC - 1 ); - - /* Enable Receives */ - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_MPE; - E1000_WRITE_REG ( hw, E1000_RCTL, rctl ); - e1e_flush(); - - DBG ( "E1000_RDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_RDBAL(0) ) ); - DBG ( "E1000_RDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_RDLEN(0) ) ); - DBG ( "E1000_RCTL: %#08x\n", E1000_READ_REG ( hw, E1000_RCTL ) ); -} - -/** - * e1000_process_rx_packets - process received packets - * - * @v netdev network interface device structure - **/ -static void e1000e_process_rx_packets ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t rx_status; - uint32_t rx_len; - uint32_t rx_err; - struct e1000_rx_desc *rx_curr_desc; - - /* 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->status; - - DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status ); - - if ( ! ( rx_status & E1000_RXD_STAT_DD ) ) - break; - - if ( adapter->rx_iobuf[i] == NULL ) - break; - - DBG ( "E1000_RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RCTL ) ); - - rx_len = rx_curr_desc->length; - - DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n", - i, rx_status, rx_len ); - - rx_err = rx_curr_desc->errors; - - iob_put ( adapter->rx_iobuf[i], rx_len ); - - if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) { - - netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL ); - DBG ( "e1000_poll: 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; - } -} - -/** Functions that implement the iPXE driver API **/ - -/** - * e1000_close - Disables a network interface - * - * @v netdev network interface device structure - * - **/ -static void e1000e_close ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; - - DBGP ( "e1000_close\n" ); - - /* Disable and acknowledge interrupts */ - e1000e_irq_disable ( adapter ); - E1000_READ_REG ( hw, E1000_ICR ); - - /* disable receives */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - e1e_flush(); - - e1000e_reset ( adapter ); - - e1000e_free_tx_resources ( adapter ); - e1000e_free_rx_resources ( adapter ); -} - -/** - * e1000_transmit - Transmit a packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * - * @ret rc Returns 0 on success, negative on failure - */ -static int e1000e_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) -{ - struct e1000_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t tx_curr = adapter->tx_tail; - struct e1000_tx_desc *tx_curr_desc; - - DBGP ("e1000_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->buffer_addr = virt_to_bus ( iobuf->data ); - tx_curr_desc->upper.data = 0; - tx_curr_desc->lower.data = adapter->txd_cmd | iob_len ( iobuf ); - - 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 - */ - E1000_WRITE_REG ( hw, E1000_TDT(0), adapter->tx_tail ); - e1e_flush(); - - return 0; -} - -/** - * e1000_poll - Poll for received packets - * - * @v netdev Network device - */ -static void e1000e_poll ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - - uint32_t icr; - - DBGP ( "e1000_poll\n" ); - - /* Acknowledge interrupts */ - icr = E1000_READ_REG ( hw, E1000_ICR ); - if ( ! icr ) - return; - - DBG ( "e1000_poll: intr_status = %#08x\n", icr ); - - e1000e_process_tx_packets ( netdev ); - - e1000e_process_rx_packets ( netdev ); - - e1000e_refill_rx_ring(adapter); -} - -/** - * e1000_irq - enable or Disable interrupts - * - * @v adapter e1000 adapter - * @v action requested interrupt action - **/ -static void e1000e_irq ( struct net_device *netdev, int enable ) -{ - struct e1000_adapter *adapter = netdev_priv ( netdev ); - - DBGP ( "e1000_irq\n" ); - - if ( enable ) { - e1000e_irq_enable ( adapter ); - } else { - e1000e_irq_disable ( adapter ); - } -} - -static struct net_device_operations e1000e_operations; - -/** - * e1000_probe - Initial configuration of e1000 NIC - * - * @v pci PCI device - * @v id PCI IDs - * - * @ret rc Return status code - **/ -int e1000e_probe ( struct pci_device *pdev ) -{ - int i, err; - struct net_device *netdev; - struct e1000_adapter *adapter; - unsigned long mmio_start, mmio_len; - unsigned long flash_start, flash_len; - struct e1000_hw *hw; - const struct e1000_info *ei = e1000_info_tbl[pdev->id->driver_data]; - - DBGP ( "e1000_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 e1000_adapter ) ); - if ( ! netdev ) { - DBG ( "err_alloc_etherdev\n" ); - goto err_alloc_etherdev; - } - - /* Associate e1000-specific network operations operations with - * generic network device layer */ - netdev_init ( netdev, &e1000e_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->device_id = pdev->device; - - adapter->irqno = pdev->irq; - adapter->netdev = netdev; - adapter->hw.back = adapter; - - adapter->ei = ei; - adapter->pba = ei->pba; - adapter->flags = ei->flags; - adapter->flags2 = ei->flags2; - - adapter->hw.adapter = adapter; - adapter->hw.mac.type = ei->mac; - 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; - } - - /* Flash BAR mapping depends on mac_type */ - if ( ( adapter->flags & FLAG_HAS_FLASH) && ( pdev->ioaddr ) ) { - flash_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_1 ); - flash_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_1 ); - adapter->hw.flash_address = ioremap ( flash_start, flash_len ); - if ( ! adapter->hw.flash_address ) { - DBG ( "err_flashmap\n" ); - goto err_flashmap; - } - } - - /* setup adapter struct */ - err = e1000e_sw_init ( adapter ); - if (err) { - DBG ( "err_sw_init\n" ); - goto err_sw_init; - } - - if (ei->get_variants) { - err = ei->get_variants(adapter); - if (err) { - DBG ( "err_hw_initr\n" ); - goto err_hw_init; - } - } - - /* Copper options */ - if (adapter->hw.phy.media_type == e1000_media_type_copper) { - adapter->hw.phy.mdix = AUTO_ALL_MODES; - adapter->hw.phy.disable_polarity_correction = 0; - adapter->hw.phy.ms_type = e1000_ms_hw_default; - } - - DBG ( "adapter->hw.mac.type: %#08x\n", adapter->hw.mac.type ); - - /* Force auto-negotiation */ - adapter->hw.mac.autoneg = 1; - adapter->fc_autoneg = 1; - adapter->hw.phy.autoneg_wait_to_complete = true; - adapter->hw.mac.adaptive_ifs = true; - adapter->hw.fc.requested_mode = e1000_fc_default; - adapter->hw.fc.current_mode = e1000_fc_default; - - /* - * before reading the NVM, reset the controller to - * put the device in a known good starting state - */ - adapter->hw.mac.ops.reset_hw(&adapter->hw); - - /* - * systems with ASPM and others may see the checksum fail on the first - * attempt. Let's give it a few tries - */ - for (i = 0;; i++) { - if (e1000e_validate_nvm_checksum(&adapter->hw) >= 0) - break; - if (i == 2) { - DBG("The NVM Checksum Is Not Valid\n"); - err = -EIO; - goto err_eeprom; - } - } - - /* copy the MAC address out of the EEPROM */ - if ( e1000e_read_mac_addr ( &adapter->hw ) ) - DBG ( "EEPROM Read Error\n" ); - - memcpy ( netdev->hw_addr, adapter->hw.mac.perm_addr, ETH_ALEN ); - - /* reset the hardware with the new settings */ - e1000e_reset ( adapter ); - - if ( ( err = register_netdev ( netdev ) ) != 0) { - DBG ( "err_register\n" ); - goto err_register; - } - - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); - - for (i = 0; i < 6; i++) - DBG ("%02x%s", netdev->ll_addr[i], i == 5 ? "\n" : ":"); - - DBG ( "e1000e_probe succeeded!\n" ); - - /* No errors, return success */ - return 0; - -/* Error return paths */ -err_register: -err_hw_init: -err_eeprom: -err_flashmap: - if (!e1000e_check_reset_block(&adapter->hw)) - e1000e_phy_hw_reset(&adapter->hw); - if (adapter->hw.flash_address) - iounmap(adapter->hw.flash_address); -err_sw_init: - iounmap ( adapter->hw.hw_addr ); -err_ioremap: - netdev_put ( netdev ); -err_alloc_etherdev: - return err; -} - -/** - * e1000e_remove - Device Removal Routine - * - * @v pdev PCI device information struct - * - **/ -void e1000e_remove ( struct pci_device *pdev ) -{ - struct net_device *netdev = pci_get_drvdata ( pdev ); - struct e1000_adapter *adapter = netdev_priv ( netdev ); - - DBGP ( "e1000e_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 ); - e1000e_reset ( adapter ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** - * e1000e_open - Called when a network interface is made active - * - * @v netdev network interface device structure - * @ret rc Return status code, 0 on success, negative value on failure - * - **/ -static int e1000e_open ( struct net_device *netdev ) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int err; - - DBGP ( "e1000e_open\n" ); - - /* allocate transmit descriptors */ - err = e1000e_setup_tx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up TX resources!\n" ); - goto err_setup_tx; - } - - /* allocate receive descriptors */ - err = e1000e_setup_rx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up RX resources!\n" ); - goto err_setup_rx; - } - - e1000e_configure_tx ( adapter ); - - e1000e_configure_rx ( adapter ); - - DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) ); - - return 0; - -err_setup_rx: - DBG ( "err_setup_rx\n" ); - e1000e_free_tx_resources ( adapter ); -err_setup_tx: - DBG ( "err_setup_tx\n" ); - e1000e_reset ( adapter ); - - return err; -} - -/** e1000e net device operations */ -static struct net_device_operations e1000e_operations = { - .open = e1000e_open, - .close = e1000e_close, - .transmit = e1000e_transmit, - .poll = e1000e_poll, - .irq = e1000e_irq, -}; diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.c deleted file mode 100644 index e0935362e..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.c +++ /dev/null @@ -1,372 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#if 0 - -#include "e1000e.h" - -static u8 e1000e_calculate_checksum(u8 *buffer, u32 length); - -/** - * e1000e_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000e_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - if (!buffer) - return 0; - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8) (0 - sum); -} - -/** - * e1000e_mng_enable_host_if_generic - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -s32 e1000e_mng_enable_host_if_generic(struct e1000_hw *hw) -{ - u32 hicr; - s32 ret_val = E1000_SUCCESS; - u8 i; - - /* Check that the host interface is enabled. */ - hicr = er32(HICR); - if ((hicr & E1000_HICR_EN) == 0) { - e_dbg("E1000_HOST_EN bit disabled.\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = er32(HICR); - if (!(hicr & E1000_HICR_C)) - break; - mdelay(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - e_dbg("Previous command timeout failed .\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_check_mng_mode_generic - Generic check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000e_enable_tx_pkt_filtering - Enable packet filtering on TX - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - bool tx_filter = true; - - /* No manageability, no filtering */ - if (!hw->mac.ops.check_mng_mode(hw)) { - tx_filter = false; - goto out; - } - - /* - * If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val != E1000_SUCCESS) { - tx_filter = false; - goto out; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) { - *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, - E1000_HOST_IF, - offset + i); - } - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000e_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if (hdr_csum != csum) - goto out; - if (hdr->signature != E1000_IAMT_SIGNATURE) - goto out; - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - tx_filter = false; - -out: - hw->mac.tx_pkt_filtering = tx_filter; - return tx_filter; -} - -/** - * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, - u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val) - goto out; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - goto out; - - /* Write the manageability command header */ - ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); - if (ret_val) - goto out; - - /* Tell the ARC a new command is pending. */ - hicr = er32(HICR); - ew32(HICR, hicr | E1000_HICR_C); - -out: - return ret_val; -} - -/** - * e1000e_mng_write_cmd_header_generic - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -s32 e1000e_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000e_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, - *((u32 *) hdr + i)); - e1e_flush(); - } - - return E1000_SUCCESS; -} - -/** - * e1000e_mng_host_if_write_generic - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -s32 e1000e_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - s32 ret_val = E1000_SUCCESS; - u16 remaining, i, j, prev_bytes; - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { - ret_val = -E1000_ERR_PARAM; - goto out; - } - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* - * The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, - data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); - } - -out: - return ret_val; -} - -/** - * e1000e_enable_mng_pass_thru - Enable processing of ARP's - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to allow ARPs to be processed by the host. - **/ -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - bool ret_val = false; - - if (!hw->mac.asf_firmware_present) - goto out; - - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - goto out; - - if (hw->mac.arc_subsystem_valid) { - fwsm = er32(FWSM); - factps = er32(FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { - ret_val = true; - goto out; - } - } else { - if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - ret_val = true; - goto out; - } - } - -out: - return ret_val; -} - -#endif - diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.h deleted file mode 100644 index f136aee84..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_manage.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_MANAGE_H_ -#define _E1000E_MANAGE_H_ - -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw); -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); -s32 e1000e_mng_enable_host_if_generic(struct e1000_hw *hw); -s32 e1000e_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum); -s32 e1000e_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr); -#if 0 -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, - u8 *buffer, u16 length); -#endif -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); - -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -#define E1000_FWSM_MODE_MASK 0xE -#define E1000_FWSM_MODE_SHIFT 1 - -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 - -#define E1000_VFTA_ENTRY_SHIFT 5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ -#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ -#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ - -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 -#define E1000_HICR_SV 0x04 /* Status Validity */ -#define E1000_HICR_FW_RESET_ENABLE 0x40 -#define E1000_HICR_FW_RESET 0x80 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.c deleted file mode 100644 index f49d421f5..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.c +++ /dev/null @@ -1,596 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000e.h" - -static void e1000e_stop_nvm(struct e1000_hw *hw); -static void e1000e_reload_nvm(struct e1000_hw *hw); - -/** - * e1000e_init_nvm_ops_generic - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void e1000e_init_nvm_ops_generic(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - /* Initialize function pointers */ - nvm->ops.reload = e1000e_reload_nvm; -} - -/** - * e1000e_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void e1000e_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000e_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void e1000e_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000e_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000e_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u32 mask; - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - e1e_flush(); - - udelay(nvm->delay_usec); - - e1000e_raise_eec_clk(hw, &eecd); - e1000e_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000e_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 e1000e_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - eecd = er32(EECD); - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - e1000e_raise_eec_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000e_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - s32 ret_val = -E1000_ERR_NVM; - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = er32(EERD); - else - reg = er32(EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) { - ret_val = E1000_SUCCESS; - break; - } - - udelay(5); - } - - return ret_val; -} - -/** - * e1000e_acquire_nvm - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 e1000e_acquire_nvm(struct e1000_hw *hw) -{ - u32 eecd = er32(EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - s32 ret_val = E1000_SUCCESS; - - ew32(EECD, eecd | E1000_EECD_REQ); - eecd = er32(EECD); - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - udelay(5); - eecd = er32(EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire NVM grant\n"); - ret_val = -E1000_ERR_NVM; - } - - return ret_val; -} - -/** - * e1000e_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void e1000e_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - } -} - -/** - * e1000e_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -static void e1000e_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - eecd = er32(EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - e1000e_lower_eec_clk(hw, &eecd); - } -} - -/** - * e1000e_release_nvm - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void e1000e_release_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - e1000e_stop_nvm(hw); - - eecd = er32(EECD); - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); -} - -/** - * e1000e_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 e1000e_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - s32 ret_val = E1000_SUCCESS; - u16 timeout = 0; - u8 spi_stat_reg; - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - udelay(1); - timeout = NVM_MAX_RETRY_SPI; - - /* - * Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - e1000e_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)e1000e_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - udelay(5); - e1000e_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - e_dbg("SPI NVM Status error\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - } - -out: - return ret_val; -} - -/** - * e1000e_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = E1000_SUCCESS; - - /* - * A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - for (i = 0; i < words; i++) { - eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - ew32(EERD, eerd); - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) - break; - - data[i] = (er32(EERD) >> - E1000_NVM_RW_REG_DATA); - } - -out: - return ret_val; -} - -/** - * e1000e_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 widx = 0; - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = e1000e_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - e1000e_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - e1000e_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - e1000e_standby_nvm(hw); - - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000e_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - e1000e_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000e_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - e1000e_standby_nvm(hw); - break; - } - } - } - - msleep(10); -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_read_pba_num - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num) -{ - s32 ret_val; - u16 nvm_data; - - ret_val = e1000e_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - *pba_num = (u32)(nvm_data << 16); - - ret_val = e1000e_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - *pba_num |= nvm_data; - -out: - return ret_val; -} - -/** - * e1000e_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 e1000e_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = er32(RAH(0)); - rar_low = er32(RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); - - for (i = 0; i < ETH_ADDR_LEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return E1000_SUCCESS; -} - -/** - * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = e1000e_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - checksum += nvm_data; - } - - if (checksum != (u16) NVM_SUM) { - e_dbg("NVM Checksum Invalid\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = e1000e_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error while updating checksum.\n"); - goto out; - } - checksum += nvm_data; - } - checksum = (u16) NVM_SUM - checksum; - ret_val = e1000e_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) - e_dbg("NVM Write Error while updating checksum.\n"); - -out: - return ret_val; -} - -/** - * e1000e_reload_nvm - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -static void e1000e_reload_nvm(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - udelay(10); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} - diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.h deleted file mode 100644 index 1a8e0f3fc..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_nvm.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_NVM_H_ -#define _E1000E_NVM_H_ - -void e1000e_init_nvm_ops_generic(struct e1000_hw *hw); -s32 e1000e_acquire_nvm(struct e1000_hw *hw); - -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -s32 e1000e_read_mac_addr_generic(struct e1000_hw *hw); -s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); -s32 e1000e_write_nvm_eewr(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); -void e1000e_release_nvm(struct e1000_hw *hw); - -#define E1000_STM_OPCODE 0xDB00 - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.c b/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.c deleted file mode 100644 index 337be7371..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.c +++ /dev/null @@ -1,3323 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "e1000e.h" - -static s32 e1000e_copper_link_autoneg(struct e1000_hw *hw); -static s32 e1000e_phy_setup_autoneg(struct e1000_hw *hw); -static u32 e1000e_get_phy_addr_for_bm_page(u32 page, u32 reg); -static s32 e1000e_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read); -static u32 e1000e_get_phy_addr_for_hv_page(u32 page); -static s32 e1000e_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read); -#if 0 -/* Cable length tables */ -static const u16 e1000_m88_cable_length_table[] = - { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_m88_cable_length_table) / \ - sizeof(e1000_m88_cable_length_table[0])) - -static const u16 e1000_igp_2_cable_length_table[] = - { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, - 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, - 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, - 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, - 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, - 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, - 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, - 104, 109, 114, 118, 121, 124}; -#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_igp_2_cable_length_table) / \ - sizeof(e1000_igp_2_cable_length_table[0])) -#endif - -/** - * e1000e_check_reset_block_generic - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Read the PHY management control register and check whether a PHY reset - * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise - * return E1000_BLK_PHY_RESET (12). - **/ -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) -{ - u32 manc; - - manc = er32(MANC); - - return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? - E1000_BLK_PHY_RESET : E1000_SUCCESS; -} - -/** - * e1000e_get_phy_id - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -s32 e1000e_get_phy_id(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_id; - u16 retry_count = 0; - - if (!(phy->ops.read_reg)) - goto out; - - while (retry_count < 2) { - ret_val = e1e_rphy(hw, PHY_ID1, &phy_id); - if (ret_val) - goto out; - - phy->id = (u32)(phy_id << 16); - udelay(20); - ret_val = e1e_rphy(hw, PHY_ID2, &phy_id); - if (ret_val) - goto out; - - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - - if (phy->id != 0 && phy->id != PHY_REVISION_MASK) - goto out; - - /* - * If the PHY ID is still unknown, we may have an 82577 - * without link. We will try again after setting Slow MDIC - * mode. No harm in trying again in this case since the PHY - * ID is unknown at this point anyway. - */ - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - ret_val = e1000e_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - phy->ops.release(hw); - - retry_count++; - } -out: - /* Revert to MDIO fast mode, if applicable */ - if (retry_count) { - ret_val = phy->ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1000e_set_mdio_slow_mode_hv(hw, false); - phy->ops.release(hw); - } - - return ret_val; -} - -/** - * e1000e_phy_reset_dsp - Reset PHY DSP - * @hw: pointer to the HW structure - * - * Reset the digital signal processor. - **/ -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (!(hw->phy.ops.write_reg)) - goto out; - - ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); - if (ret_val) - goto out; - - ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0); - -out: - return ret_val; -} - -/** - * e1000e_read_phy_reg_mdic - Read MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the MDI control register in the PHY at offset and stores the - * information read to data. - **/ -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - ew32(MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Read did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - *data = (u16) mdic; - -out: - return ret_val; -} - -/** - * e1000e_write_phy_reg_mdic - Write MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write to register at offset - * - * Writes data to MDI control register in the PHY at offset. - **/ -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = (((u32)data) | - (offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - ew32(MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Write did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_read_phy_reg_m88 - Read m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val = E1000_SUCCESS; - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_phy_reg_m88 - Write m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val = E1000_SUCCESS; - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * __e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - s32 ret_val = E1000_SUCCESS; - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) - goto release; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - if (!locked) - hw->phy.ops.release(hw); -out: - return ret_val; -} - -/** - * e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores the - * retrieved information in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_read_phy_reg_igp_locked - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, true); -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - s32 ret_val = E1000_SUCCESS; - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) - goto release; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_write_phy_reg_igp_locked - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, true); -} - -/** - * __e1000e_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then reads the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release any acquired semaphores before exiting. - **/ -static s32 __e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset using the - * kumeran interface. The information retrieved is stored in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_read_kmrn_reg_locked - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the kumeran interface. The - * information retrieved is stored in data. - * Assumes semaphore already acquired. - **/ -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_kmrn_reg(hw, offset, data, true); -} - -/** - * __e1000e_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then write the data to PHY register - * at the offset using the kumeran interface. Release any acquired semaphores - * before exiting. - **/ -static s32 __e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - - udelay(2); - - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * e1000e_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to the PHY register at the offset - * using the kumeran interface. Release the acquired semaphore before exiting. - **/ -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_write_kmrn_reg_locked - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Write the data to PHY register at the offset using the kumeran interface. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_kmrn_reg(hw, offset, data, true); -} - -/** - * e1000e_copper_link_setup_82577 - Setup 82577 PHY for copper link - * @hw: pointer to the HW structure - * - * Sets up Carrier-sense on Transmit and downshift values. - **/ -s32 e1000e_copper_link_setup_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); - if (ret_val) - goto out; - - phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; - - /* Enable downshift */ - phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; - - ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data); - -out: - return ret_val; -} - -/** - * e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock - * and downshift values are set also. - **/ -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - /* For BM PHY this bit is downshift enable */ - if (phy->type != e1000_phy_bm) - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* - * Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* - * Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - - /* Enable downshift on BM (disabled by default) */ - if (phy->type == e1000_phy_bm) - phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; - - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - if ((phy->type == e1000_phy_m88) && - (phy->revision < E1000_REVISION_4) && - (phy->id != BME1000_E_PHY_ID_R2)) { - /* - * Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((phy->revision == E1000_REVISION_2) && - (phy->id == M88E1111_I_PHY_ID)) { - /* 82573L PHY - set the downshift counter to 5x. */ - phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - } - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - goto out; - } - - if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { - /* Set PHY page 0, register 29 to 0x0003 */ - ret_val = e1e_wphy(hw, 29, 0x0003); - if (ret_val) - goto out; - - /* Set PHY page 0, register 30 to 0x0000 */ - ret_val = e1e_wphy(hw, 30, 0x0000); - if (ret_val) - goto out; - } - - /* Commit the changes. */ - ret_val = e1000e_commit_phy(hw); - if (ret_val) { - e_dbg("Error committing the PHY changes\n"); - goto out; - } - - if (phy->type == e1000_phy_82578) { - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - goto out; - - /* 82578 PHY - set the downshift count to 1x. */ - phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; - phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_copper_link_setup_igp - Setup igp PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for - * igp PHY's. - **/ -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = e1000e_phy_hw_reset(hw); - if (ret_val) { - e_dbg("Error resetting the PHY.\n"); - goto out; - } - - /* - * Wait 100ms for MAC to configure PHY from NVM settings, to avoid - * timeout issues when LFS is enabled. - */ - msleep(100); - - /* - * The NVM settings will configure LPLU in D3 for - * non-IGP1 PHYs. - */ - if (phy->type == e1000_phy_igp) { - /* disable lplu d3 during driver init */ - ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D3\n"); - goto out; - } - } - - /* disable lplu d0 during driver init */ - if (hw->phy.ops.set_d0_lplu_state) { - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D0\n"); - goto out; - } - } - /* Configure mdi-mdix settings */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (phy->mdix) { - case 1: - data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, data); - if (ret_val) - goto out; - - /* set auto-master slave resolution settings */ - if (hw->mac.autoneg) { - /* - * when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - - /* Set auto Master/Slave resolution process */ - ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - data &= ~CR_1000T_MS_ENABLE; - ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - - ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - /* load defaults for future use */ - phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? - ((data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : - e1000_ms_auto; - - switch (phy->ms_type) { - case e1000_ms_force_master: - data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - data |= CR_1000T_MS_ENABLE; - data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_copper_link_autoneg - Setup/Enable autoneg for copper link - * @hw: pointer to the HW structure - * - * Performs initial bounds checking on autoneg advertisement parameter, then - * configure to advertise the full capability. Setup the PHY to autoneg - * and restart the negotiation process between the link partner. If - * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. - **/ -static s32 e1000e_copper_link_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_ctrl; - - /* - * Perform some bounds checking on the autoneg advertisement - * parameter. - */ - phy->autoneg_advertised &= phy->autoneg_mask; - - /* - * If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (phy->autoneg_advertised == 0) - phy->autoneg_advertised = phy->autoneg_mask; - - e_dbg("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000e_phy_setup_autoneg(hw); - if (ret_val) { - e_dbg("Error Setting up Auto-Negotiation\n"); - goto out; - } - e_dbg("Restarting Auto-Neg\n"); - - /* - * Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - /* - * Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (phy->autoneg_wait_to_complete) { - ret_val = hw->mac.ops.wait_autoneg(hw); - if (ret_val) { - e_dbg("Error while waiting for " - "autoneg to complete\n"); - goto out; - } - } - - hw->mac.get_link_status = true; - -out: - return ret_val; -} - -/** - * e1000e_phy_setup_autoneg - Configure PHY for auto-negotiation - * @hw: pointer to the HW structure - * - * Reads the MII auto-neg advertisement register and/or the 1000T control - * register and if the PHY is already setup for auto-negotiation, then - * return successful. Otherwise, setup advertisement and flow control to - * the appropriate values for the wanted auto-negotiation. - **/ -static s32 e1000e_phy_setup_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg = 0; - - phy->autoneg_advertised &= phy->autoneg_mask; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if (ret_val) - goto out; - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1e_rphy(hw, PHY_1000T_CTRL, - &mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - - /* - * Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* - * 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 &= ~(NWAY_AR_100TX_FD_CAPS | - NWAY_AR_100TX_HD_CAPS | - NWAY_AR_10T_FD_CAPS | - NWAY_AR_10T_HD_CAPS); - mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); - - e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_HALF) { - e_dbg("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_FULL) { - e_dbg("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_HALF) { - e_dbg("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_FULL) { - e_dbg("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) - e_dbg("Advertise 1000mb Half duplex request denied!\n"); - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { - e_dbg("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* - * Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- - * negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* - * Flow control (Rx & Tx) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled, and Tx Flow control is - * disabled, by a software over-ride. - * - * Since there really isn't a way to advertise that we are - * capable of Rx Pause ONLY, we will advertise that we - * support both symmetric and asymmetric Rx PAUSE. Later - * (in e1000e_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = e1e_wphy(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if (ret_val) - goto out; - - e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = e1e_wphy(hw, - PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_setup_copper_link - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -s32 e1000e_setup_copper_link(struct e1000_hw *hw) -{ - s32 ret_val; - bool link; - - if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = e1000e_copper_link_autoneg(hw); - if (ret_val) - goto out; - } else { -#if 0 - /* - * PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - e_dbg("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - e_dbg("Error Forcing Speed and Duplex\n"); - goto out; - } -#endif - } - - /* - * Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000e_phy_has_link_generic(hw, - COPPER_LINK_UP_LIMIT, - 10, - &link); - if (ret_val) - goto out; - - if (link) { - e_dbg("Valid link established!!!\n"); - e1000e_config_collision_dist(hw); - ret_val = e1000e_config_fc_after_link_up(hw); - } else { - e_dbg("Unable to establish link!!!\n"); - } - -out: - return ret_val; -} - -#if 0 -/** - * e1000e_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* - * Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - goto out; - - e_dbg("IGP PSCR: %X\n", phy_data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} -#endif - -#if 0 -/** - * e1000e_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Resets the PHY to commit the - * changes. If time expires while waiting for link up, we reset the DSP. - * After reset, TX_CLK and CRS on Tx must be set. Return successful upon - * successful completion, else return corresponding error code. - **/ -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - e_dbg("M88E1000 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* Reset the phy to commit changes. */ - ret_val = e1000e_commit_phy(hw); - if (ret_val) - goto out; - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - - if (!link) { - /* - * We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1e_wphy(hw, - M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - goto out; - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - goto out; - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - } - - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - /* - * Resetting the phy means we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock from - * the reset value of 2.5MHz. - */ - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - /* - * In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - -out: - return ret_val; -} -#endif - -#if 0 -/** - * e1000e_phy_force_speed_duplex_ife - Force PHY speed & duplex - * @hw: pointer to the HW structure - * - * Forces the speed and duplex settings of the PHY. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -s32 e1000e_phy_force_speed_duplex_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - if (phy->type != e1000_phy_ife) { - ret_val = e1000e_phy_force_speed_duplex_igp(hw); - goto out; - } - - ret_val = e1e_rphy(hw, PHY_CONTROL, &data); - if (ret_val) - goto out; - - e1000e_phy_force_speed_duplex_setup(hw, &data); - - ret_val = e1e_wphy(hw, PHY_CONTROL, data); - if (ret_val) - goto out; - - /* Disable MDI-X support for 10/100 */ - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - goto out; - - data &= ~IFE_PMC_AUTO_MDIX; - data &= ~IFE_PMC_FORCE_MDIX; - - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); - if (ret_val) - goto out; - - e_dbg("IFE PMC: %X\n", data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} -#endif - -#if 0 -/** - * e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex - * @hw: pointer to the HW structure - * @phy_ctrl: pointer to current value of PHY_CONTROL - * - * Forces speed and duplex on the PHY by doing the following: disable flow - * control, force speed/duplex on the MAC, disable auto speed detection, - * disable auto-negotiation, configure duplex, configure speed, configure - * the collision distance, write configuration to CTRL register. The - * caller must write to the PHY_CONTROL register for these settings to - * take affect. - **/ -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - - /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; - - /* Force speed/duplex on the mac */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~E1000_CTRL_SPD_SEL; - - /* Disable Auto Speed Detection */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Disable autoneg on the phy */ - *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; - - /* Forcing Full or Half Duplex? */ - if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { - ctrl &= ~E1000_CTRL_FD; - *phy_ctrl &= ~MII_CR_FULL_DUPLEX; - e_dbg("Half Duplex\n"); - } else { - ctrl |= E1000_CTRL_FD; - *phy_ctrl |= MII_CR_FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } - - /* Forcing 10mb or 100mb? */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { - ctrl |= E1000_CTRL_SPD_100; - *phy_ctrl |= MII_CR_SPEED_100; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - e_dbg("Forcing 100mb\n"); - } else { - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl |= MII_CR_SPEED_10; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - e_dbg("Forcing 10mb\n"); - } - - e1000e_config_collision_dist(hw); - - ew32(CTRL, ctrl); -} -#endif - -/** - * e1000e_set_d3_lplu_state - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 data; - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - goto out; - - if (!active) { - data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - } - -out: - return ret_val; -} - -/** - * e1000e_check_downshift - Checks whether a downshift in speed occurred - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns 1 - * - * A downshift is detected by querying the PHY link health. - **/ -s32 e1000e_check_downshift(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - switch (phy->type) { - case e1000_phy_m88: - case e1000_phy_gg82563: - case e1000_phy_bm: - case e1000_phy_82578: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; - break; - case e1000_phy_igp_2: - case e1000_phy_igp: - case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; - break; - default: - /* speed downshift not supported */ - phy->speed_downgraded = false; - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = (phy_data & mask) ? true : false; - -out: - return ret_val; -} - -/** - * e1000e_check_polarity_m88 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000e_check_polarity_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data); - - if (!ret_val) - phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * e1000e_check_polarity_igp - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY port status register, and the - * current speed (since there is no polarity at 100Mbps). - **/ -s32 e1000e_check_polarity_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data, offset, mask; - - /* - * Polarity is determined based on the speed of - * our connection. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; - } else { - /* - * This really only applies to 10Mbps since - * there is no polarity for 100Mbps (always 0). - */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; - } - - ret_val = e1e_rphy(hw, offset, &data); - - if (!ret_val) - phy->cable_polarity = (data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - -out: - return ret_val; -} - -/** - * e1000e_check_polarity_ife - Check cable polarity for IFE PHY - * @hw: pointer to the HW structure - * - * Polarity is determined on the polarity reversal feature being enabled. - **/ -s32 e1000e_check_polarity_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - /* - * Polarity is determined based on the reversal feature being enabled. - */ - if (phy->polarity_correction) { - offset = IFE_PHY_EXTENDED_STATUS_CONTROL; - mask = IFE_PESC_POLARITY_REVERSED; - } else { - offset = IFE_PHY_SPECIAL_CONTROL; - mask = IFE_PSC_FORCE_POLARITY; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->cable_polarity = (phy_data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * e1000e_wait_autoneg - Wait for auto-neg completion - * @hw: pointer to the HW structure - * - * Waits for auto-negotiation to complete or for the auto-negotiation time - * limit to expire, which ever happens first. - **/ -s32 e1000e_wait_autoneg(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ - for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_AUTONEG_COMPLETE) - break; - msleep(100); - } - - /* - * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation - * has completed. - */ - return ret_val; -} - -/** - * e1000e_phy_has_link_generic - Polls PHY for link - * @hw: pointer to the HW structure - * @iterations: number of times to poll for link - * @usec_interval: delay between polling attempts - * @success: pointer to whether polling was successful or not - * - * Polls the PHY status register for link, 'iterations' number of times. - **/ -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - for (i = 0; i < iterations; i++) { - /* - * Some PHYs require the PHY_STATUS register to be read - * twice due to the link bit being sticky. No harm doing - * it across the board. - */ - ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); - if (ret_val) { - /* - * If the first read fails, another entity may have - * ownership of the resources, wait and try again to - * see if they have relinquished the resources yet. - */ - udelay(usec_interval); - } - ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_LINK_STATUS) - break; - if (usec_interval >= 1000) - mdelay(usec_interval/1000); - else - udelay(usec_interval); - } - - *success = (i < iterations) ? true : false; - - return ret_val; -} - -#if 0 -/** - * e1000e_get_cable_length_m88 - Determine cable length for m88 PHY - * @hw: pointer to the HW structure - * - * Reads the PHY specific status register to retrieve the cable length - * information. The cable length is determined by averaging the minimum and - * maximum values to get the "average" cable length. The m88 PHY has four - * possible cable length values, which are: - * Register Value Cable Length - * 0 < 50 meters - * 1 50 - 80 meters - * 2 80 - 110 meters - * 3 110 - 140 meters - * 4 > 140 meters - **/ -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT; - if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} - -/** - * e1000e_get_cable_length_igp_2 - Determine cable length for igp2 PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_data, i, agc_value = 0; - u16 cur_agc_index, max_agc_index = 0; - u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = - {IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D}; - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1e_rphy(hw, agc_reg_array[i], &phy_data); - if (ret_val) - goto out; - - /* - * Getting bits 15:9, which represent the combination of - * coarse and fine gain values. The result is a number - * that can be put into the lookup table to obtain the - * approximate cable length. - */ - cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK; - - /* Array index bound check. */ - if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || - (cur_agc_index == 0)) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - /* Remove min & max AGC values from calculation. */ - if (e1000_igp_2_cable_length_table[min_agc_index] > - e1000_igp_2_cable_length_table[cur_agc_index]) - min_agc_index = cur_agc_index; - if (e1000_igp_2_cable_length_table[max_agc_index] < - e1000_igp_2_cable_length_table[cur_agc_index]) - max_agc_index = cur_agc_index; - - agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; - } - - agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + - e1000_igp_2_cable_length_table[max_agc_index]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* Calculate cable length with the error range of +/- 10 meters. */ - phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0; - phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} -#endif - -/** - * e1000e_get_phy_info_m88 - Retrieve PHY information - * @hw: pointer to the HW structure - * - * Valid for only copper links. Read the PHY status register (sticky read) - * to verify that link is up. Read the PHY special control register to - * determine the polarity and 10base-T extended distance. Read the PHY - * special status register to determine MDI/MDIx and current speed. If - * speed is 1000, then determine cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - if (phy->media_type != e1000_media_type_copper) { - e_dbg("Phy info is only valid for copper media\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? true : false; - - ret_val = e1000e_check_polarity_m88(hw); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { -#if 0 - ret_val = e1000e_get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; -#if 0 - ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; -#endif - } else { - /* Set values to "undefined" */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } -out: - return ret_val; -} - -/** - * e1000e_get_phy_info_igp - Retrieve igp PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - phy->polarity_correction = true; - - ret_val = e1000e_check_polarity_igp(hw); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { -#if 0 - ret_val = phy->ops.get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; -#if 0 - ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data); - if (ret_val) - goto out; - - phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; -#endif - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } -out: - return ret_val; -} - -/** - * e1000e_phy_sw_reset - PHY software reset - * @hw: pointer to the HW structure - * - * Does a software reset of the PHY by reading the PHY control register and - * setting/write the control register reset bit to the PHY. - **/ -s32 e1000e_phy_sw_reset(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 phy_ctrl; - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= MII_CR_RESET; - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - udelay(1); - -out: - return ret_val; -} - -/** - * e1000e_phy_hw_reset_generic - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u32 ctrl; - - ret_val = e1000e_check_reset_block(hw); - if (ret_val) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); - e1e_flush(); - - udelay(phy->reset_delay_us); - - ew32(CTRL, ctrl); - e1e_flush(); - - udelay(150); - - phy->ops.release(hw); - - ret_val = phy->ops.get_cfg_done(hw); - -out: - return ret_val; -} - -/** - * e1000e_get_cfg_done - Generic configuration done - * @hw: pointer to the HW structure - * - * Generic function to wait 10 milli-seconds for configuration to complete - * and return success. - **/ -s32 e1000e_get_cfg_done(struct e1000_hw *hw __unused) -{ - mdelay(10); - - return E1000_SUCCESS; -} - -/** - * e1000e_phy_init_script_igp3 - Inits the IGP3 PHY - * @hw: pointer to the HW structure - * - * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. - **/ -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) -{ - e_dbg("Running IGP 3 PHY init script\n"); - - /* PHY init IGP 3 */ - /* Enable rise/fall, 10-mode work in class-A */ - e1e_wphy(hw, 0x2F5B, 0x9018); - /* Remove all caps from Replica path filter */ - e1e_wphy(hw, 0x2F52, 0x0000); - /* Bias trimming for ADC, AFE and Driver (Default) */ - e1e_wphy(hw, 0x2FB1, 0x8B24); - /* Increase Hybrid poly bias */ - e1e_wphy(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Gig mode */ - e1e_wphy(hw, 0x2010, 0x10B0); - /* Disable trimming (TTT) */ - e1e_wphy(hw, 0x2011, 0x0000); - /* Poly DC correction to 94.6% + 2% for all channels */ - e1e_wphy(hw, 0x20DD, 0x249A); - /* ABS DC correction to 95.9% */ - e1e_wphy(hw, 0x20DE, 0x00D3); - /* BG temp curve trim */ - e1e_wphy(hw, 0x28B4, 0x04CE); - /* Increasing ADC OPAMP stage 1 currents to max */ - e1e_wphy(hw, 0x2F70, 0x29E4); - /* Force 1000 ( required for enabling PHY regs configuration) */ - e1e_wphy(hw, 0x0000, 0x0140); - /* Set upd_freq to 6 */ - e1e_wphy(hw, 0x1F30, 0x1606); - /* Disable NPDFE */ - e1e_wphy(hw, 0x1F31, 0xB814); - /* Disable adaptive fixed FFE (Default) */ - e1e_wphy(hw, 0x1F35, 0x002A); - /* Enable FFE hysteresis */ - e1e_wphy(hw, 0x1F3E, 0x0067); - /* Fixed FFE for short cable lengths */ - e1e_wphy(hw, 0x1F54, 0x0065); - /* Fixed FFE for medium cable lengths */ - e1e_wphy(hw, 0x1F55, 0x002A); - /* Fixed FFE for long cable lengths */ - e1e_wphy(hw, 0x1F56, 0x002A); - /* Enable Adaptive Clip Threshold */ - e1e_wphy(hw, 0x1F72, 0x3FB0); - /* AHT reset limit to 1 */ - e1e_wphy(hw, 0x1F76, 0xC0FF); - /* Set AHT master delay to 127 msec */ - e1e_wphy(hw, 0x1F77, 0x1DEC); - /* Set scan bits for AHT */ - e1e_wphy(hw, 0x1F78, 0xF9EF); - /* Set AHT Preset bits */ - e1e_wphy(hw, 0x1F79, 0x0210); - /* Change integ_factor of channel A to 3 */ - e1e_wphy(hw, 0x1895, 0x0003); - /* Change prop_factor of channels BCD to 8 */ - e1e_wphy(hw, 0x1796, 0x0008); - /* Change cg_icount + enable integbp for channels BCD */ - e1e_wphy(hw, 0x1798, 0xD008); - /* - * Change cg_icount + enable integbp + change prop_factor_master - * to 8 for channel A - */ - e1e_wphy(hw, 0x1898, 0xD918); - /* Disable AHT in Slave mode on channel A */ - e1e_wphy(hw, 0x187A, 0x0800); - /* - * Enable LPLU and disable AN to 1000 in non-D0a states, - * Enable SPD+B2B - */ - e1e_wphy(hw, 0x0019, 0x008D); - /* Enable restart AN on an1000_dis change */ - e1e_wphy(hw, 0x001B, 0x2080); - /* Enable wh_fifo read clock in 10/100 modes */ - e1e_wphy(hw, 0x0014, 0x0045); - /* Restart AN, Speed selection is 1000 */ - e1e_wphy(hw, 0x0000, 0x1340); - - return E1000_SUCCESS; -} - -/** - * e1000e_get_phy_type_from_id - Get PHY type from id - * @phy_id: phy_id read from the phy - * - * Returns the phy type from the id. - **/ -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) -{ - enum e1000_phy_type phy_type = e1000_phy_unknown; - - switch (phy_id) { - case M88E1000_I_PHY_ID: - case M88E1000_E_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1011_I_PHY_ID: - phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ - phy_type = e1000_phy_igp_2; - break; - case GG82563_E_PHY_ID: - phy_type = e1000_phy_gg82563; - break; - case IGP03E1000_E_PHY_ID: - phy_type = e1000_phy_igp_3; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy_type = e1000_phy_ife; - break; - case BME1000_E_PHY_ID: - case BME1000_E_PHY_ID_R2: - phy_type = e1000_phy_bm; - break; - case I82578_E_PHY_ID: - phy_type = e1000_phy_82578; - break; - case I82577_E_PHY_ID: - phy_type = e1000_phy_82577; - break; - default: - phy_type = e1000_phy_unknown; - break; - } - return phy_type; -} - -/** - * e1000e_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * addresses. It tests each by reading the PHY ID registers and - * checking for a match. - **/ -s32 e1000e_determine_phy_address(struct e1000_hw *hw) -{ - s32 ret_val = -E1000_ERR_PHY_TYPE; - u32 phy_addr = 0; - u32 i; - enum e1000_phy_type phy_type = e1000_phy_unknown; - - hw->phy.id = phy_type; - - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - i = 0; - - do { - e1000e_get_phy_id(hw); - phy_type = e1000e_get_phy_type_from_id(hw->phy.id); - - /* - * If phy_type is valid, break - we found our - * PHY address - */ - if (phy_type != e1000_phy_unknown) { - ret_val = E1000_SUCCESS; - goto out; - } - msleep(1); - i++; - } while (i < 10); - } - -out: - return ret_val; -} - -/** - * e1000e_get_phy_addr_for_bm_page - Retrieve PHY page address - * @page: page to access - * - * Returns the phy address for the page requested. - **/ -static u32 e1000e_get_phy_addr_for_bm_page(u32 page, u32 reg) -{ - u32 phy_addr = 2; - - if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000e_write_phy_reg_bm - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u32 page_select = 0; - u32 page = offset >> IGP_PAGE_SHIFT; - u32 page_shift = 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, &data, - false); - goto out; - } - - hw->phy.addr = e1000e_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* - * Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto out; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -out: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u32 page_select = 0; - u32 page = offset >> IGP_PAGE_SHIFT; - u32 page_shift = 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, data, - true); - goto out; - } - - hw->phy.addr = e1000e_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* - * Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto out; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -out: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm2 - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, data, - true); - goto out; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto out; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -out: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_write_phy_reg_bm2 - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, &data, - false); - goto out; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto out; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -out: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_access_phy_wakeup_reg_bm - Read BM PHY wakeup register - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to read or write - * @read: determines if operation is read or write - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. Note that procedure to read the wakeup - * registers are different. It works as such: - * 1) Set page 769, register 17, bit 2 = 1 - * 2) Set page to 800 for host (801 if we were manageability) - * 3) Write the address using the address opcode (0x11) - * 4) Read or write the data using the data opcode (0x12) - * 5) Restore 769_17.2 to its original value - * - * Assumes semaphore already acquired. - **/ -static s32 e1000e_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read) -{ - s32 ret_val; - u16 reg = BM_PHY_REG_NUM(offset); - u16 phy_reg = 0; - - /* Gig must be disabled for MDIO accesses to page 800 */ - if ((hw->mac.type == e1000_pchlan) && - (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) - e_dbg("Attempting to access page 800 while gig enabled.\n"); - - /* All operations in this function are phy address 1 */ - hw->phy.addr = 1; - - /* Set page 769 */ - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); - - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); - if (ret_val) { - e_dbg("Could not read PHY page 769\n"); - goto out; - } - - /* First clear bit 4 to avoid a power state change */ - phy_reg &= ~(BM_WUC_HOST_WU_BIT); - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - e_dbg("Could not clear PHY page 769 bit 4\n"); - goto out; - } - - /* Write bit 2 = 1, and clear bit 4 to 769_17 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, - phy_reg | BM_WUC_ENABLE_BIT); - if (ret_val) { - e_dbg("Could not write PHY page 769 bit 2\n"); - goto out; - } - - /* Select page 800 */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_PAGE << IGP_PAGE_SHIFT)); - - /* Write the page 800 offset value using opcode 0x11 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); - if (ret_val) { - e_dbg("Could not write address opcode to page 800\n"); - goto out; - } - - if (read) { - /* Read the page 800 value using opcode 0x12 */ - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - data); - } else { - /* Write the page 800 value using opcode 0x12 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - *data); - } - - if (ret_val) { - e_dbg("Could not access data value from page 800\n"); - goto out; - } - - /* - * Restore 769_17.2 to its original value - * Set page 769 - */ - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); - - /* Clear 769_17.2 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - e_dbg("Could not clear PHY page 769 bit 2\n"); - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_power_up_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000e_power_up_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, PHY_CONTROL, &mii_reg); - mii_reg &= ~MII_CR_POWER_DOWN; - e1e_wphy(hw, PHY_CONTROL, mii_reg); -} - -/** - * e1000e_power_down_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000e_power_down_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, PHY_CONTROL, &mii_reg); - mii_reg |= MII_CR_POWER_DOWN; - e1e_wphy(hw, PHY_CONTROL, mii_reg); - msleep(1); -} - -/** - * e1000e_set_mdio_slow_mode_hv - Set slow MDIO access mode - * @hw: pointer to the HW structure - * @slow: true for slow mode, false for normal mode - * - * Assumes semaphore already acquired. - **/ -s32 e1000e_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) -{ - s32 ret_val = E1000_SUCCESS; - u16 data = 0; - - /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) - goto out; - - ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, - (0x2180 | (slow << 10))); - if (ret_val) - goto out; - - /* dummy read when reverting to fast mode - throw away result */ - if (!slow) - ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); - -out: - return ret_val; -} - -/** - * __e1000e_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphore before exiting. - **/ -static s32 __e1000e_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000e_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, - data, true); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000e_access_phy_debug_regs_hv(hw, offset, - data, true); - goto out; - } - - hw->phy.addr = e1000e_get_phy_addr_for_hv_page(page); - - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - u32 phy_addr = hw->phy.addr; - - hw->phy.addr = 1; - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, - data); -out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000e_set_mdio_slow_mode_hv(hw, false); - - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores - * the retrieved information in data. Release the acquired semaphore - * before exiting. - **/ -s32 e1000e_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_hv(hw, offset, data, false); -} - -/** - * e1000e_read_phy_reg_hv_locked - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000e_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_hv(hw, offset, data, true); -} - -/** - * __e1000e_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000e_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000e_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000e_access_phy_wakeup_reg_bm(hw, offset, - &data, false); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000e_access_phy_debug_regs_hv(hw, offset, - &data, false); - goto out; - } - - hw->phy.addr = e1000e_get_phy_addr_for_hv_page(page); - - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - /* - * Workaround MDIO accesses being disabled after entering IEEE Power - * Down (whenever bit 11 of the PHY Control register is set) - */ - if ((hw->phy.type == e1000_phy_82578) && - (hw->phy.revision >= 1) && - (hw->phy.addr == 2) && - ((MAX_PHY_REG_ADDRESS & reg) == 0) && - (data & (1 << 11))) { - u16 data2 = 0x7EFF; - ret_val = e1000e_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, - &data2, false); - if (ret_val) - goto out; - } - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - u32 phy_addr = hw->phy.addr; - - hw->phy.addr = 1; - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (page << IGP_PAGE_SHIFT)); - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, - data); - -out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000e_set_mdio_slow_mode_hv(hw, false); - - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register at the offset. - * Release the acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_hv(hw, offset, data, false); -} - -/** - * e1000e_write_phy_reg_hv_locked - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. Assumes semaphore - * already acquired. - **/ -s32 e1000e_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_hv(hw, offset, data, true); -} - -/** - * e1000e_get_phy_addr_for_hv_page - Get PHY adrress based on page - * @page: page to be accessed - **/ -static u32 e1000e_get_phy_addr_for_hv_page(u32 page) -{ - u32 phy_addr = 2; - - if (page >= HV_INTC_FC_PAGE_START) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000e_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to be read or written - * @read: determines if operation is read or written - * - * Reads the PHY register at offset and stores the retreived information - * in data. Assumes semaphore already acquired. Note that the procedure - * to read these regs uses the address port and data port to read/write. - **/ -static s32 e1000e_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read) -{ - s32 ret_val; - u32 addr_reg = 0; - u32 data_reg = 0; - - /* This takes care of the difference with desktop vs mobile phy */ - addr_reg = (hw->phy.type == e1000_phy_82578) ? - I82578_ADDR_REG : I82577_ADDR_REG; - data_reg = addr_reg + 1; - - /* All operations in this function are phy address 2 */ - hw->phy.addr = 2; - - /* masking with 0x3F to remove the page from offset */ - ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); - if (ret_val) { - e_dbg("Could not write PHY the HV address register\n"); - goto out; - } - - /* Read or write the data value next */ - if (read) - ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data); - else - ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); - - if (ret_val) { - e_dbg("Could not read data value from HV data register\n"); - goto out; - } - -out: - return ret_val; -} - -/** - * e1000e_link_stall_workaround_hv - Si workaround - * @hw: pointer to the HW structure - * - * This function works around a Si bug where the link partner can get - * a link up indication before the PHY does. If small packets are sent - * by the link partner they can be placed in the packet buffer without - * being properly accounted for by the PHY and will stall preventing - * further packets from being received. The workaround is to clear the - * packet buffer after the PHY detects link up. - **/ -s32 e1000e_link_stall_workaround_hv(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 data; - - if (hw->phy.type != e1000_phy_82578) - goto out; - - /* Do not apply workaround if in PHY loopback bit 14 set */ - e1e_rphy(hw, PHY_CONTROL, &data); - if (data & PHY_CONTROL_LB) - goto out; - - /* check if link is up and at 1Gbps */ - ret_val = e1e_rphy(hw, BM_CS_STATUS, &data); - if (ret_val) - goto out; - - data &= BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK; - - if (data != (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - goto out; - - msleep(200); - - /* flush the packets in the fifo buffer */ - ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, - HV_MUX_DATA_CTRL_GEN_TO_MAC | - HV_MUX_DATA_CTRL_FORCE_SPEED); - if (ret_val) - goto out; - - ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, - HV_MUX_DATA_CTRL_GEN_TO_MAC); - -out: - return ret_val; -} - -/** - * e1000e_check_polarity_82577 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000e_check_polarity_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - - if (!ret_val) - phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -#if 0 -/** - * e1000e_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 e1000e_phy_force_speed_duplex_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* - * Clear Auto-Crossover to force MDI manually. 82577 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX; - phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX; - - ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); - if (ret_val) - goto out; - - e_dbg("I82577_PHY_CTRL_2: %X\n", phy_data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on 82577 phy\n"); - - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} -#endif - -/** - * e1000e_get_phy_info_82577 - Retrieve I82577 PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - phy->polarity_correction = true; - - ret_val = e1000e_check_polarity_82577(hw); - if (ret_val) - goto out; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - if (ret_val) - goto out; - - phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; - - if ((data & I82577_PHY_STATUS2_SPEED_MASK) == - I82577_PHY_STATUS2_SPEED_1000MBPS) { -#if 0 - ret_val = e1000e_get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; -#if 0 - ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data); - if (ret_val) - goto out; - - phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; -#endif - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } -out: - return ret_val; -} - -#if 0 -/** - * e1000e_get_cable_length_82577 - Determine cable length for 82577 PHY - * @hw: pointer to the HW structure - * - * Reads the diagnostic status register and verifies result is valid before - * placing it in the phy_cable_length field. - **/ -s32 e1000e_get_cable_length_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, length; - - ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data); - if (ret_val) - goto out; - - length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> - I82577_DSTATUS_CABLE_LENGTH_SHIFT; - - if (length == E1000_CABLE_LENGTH_UNDEFINED) - ret_val = -E1000_ERR_PHY; - - phy->cable_length = length; - -out: - return ret_val; -} -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.h deleted file mode 100644 index 9081050fe..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_phy.h +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_PHY_H_ -#define _E1000E_PHY_H_ - -void e1000e_init_phy_ops_generic(struct e1000_hw *hw); -s32 e1000e_check_downshift(struct e1000_hw *hw); -s32 e1000e_check_polarity_m88(struct e1000_hw *hw); -s32 e1000e_check_polarity_igp(struct e1000_hw *hw); -s32 e1000e_check_polarity_ife(struct e1000_hw *hw); -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); -#if 0 -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_ife(struct e1000_hw *hw); -#endif -#if 0 -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); -#endif -s32 e1000e_get_cfg_done(struct e1000_hw *hw); -s32 e1000e_get_phy_id(struct e1000_hw *hw); -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); -s32 e1000e_phy_sw_reset(struct e1000_hw *hw); -#if 0 -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -#endif -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); -s32 e1000e_setup_copper_link(struct e1000_hw *hw); -s32 e1000e_wait_autoneg(struct e1000_hw *hw); -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw); -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); -s32 e1000e_determine_phy_address(struct e1000_hw *hw); -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); -void e1000e_power_up_phy_copper(struct e1000_hw *hw); -void e1000e_power_down_phy_copper(struct e1000_hw *hw); -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); -s32 e1000e_link_stall_workaround_hv(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_82577(struct e1000_hw *hw); -s32 e1000e_check_polarity_82577(struct e1000_hw *hw); -s32 e1000e_get_phy_info_82577(struct e1000_hw *hw); -#if 0 -s32 e1000e_phy_force_speed_duplex_82577(struct e1000_hw *hw); -#endif -#if 0 -s32 e1000e_get_cable_length_82577(struct e1000_hw *hw); -#endif - -#define E1000_MAX_PHY_ADDR 4 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -#define IGP_PAGE_SHIFT 5 -#define PHY_REG_MASK 0x1F - -/* BM/HV Specific Registers */ -#define BM_PORT_CTRL_PAGE 769 -#define BM_PCIE_PAGE 770 -#define BM_WUC_PAGE 800 -#define BM_WUC_ADDRESS_OPCODE 0x11 -#define BM_WUC_DATA_OPCODE 0x12 -#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE -#define BM_WUC_ENABLE_REG 17 -#define BM_WUC_ENABLE_BIT (1 << 2) -#define BM_WUC_HOST_WU_BIT (1 << 4) - -#define PHY_UPPER_SHIFT 21 -#define BM_PHY_REG(page, reg) \ - (((reg) & MAX_PHY_REG_ADDRESS) |\ - (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ - (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) -#define BM_PHY_REG_PAGE(offset) \ - ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) -#define BM_PHY_REG_NUM(offset) \ - ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ - (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ - ~MAX_PHY_REG_ADDRESS))) - -#define HV_INTC_FC_PAGE_START 768 -#define I82578_ADDR_REG 29 -#define I82577_ADDR_REG 16 -#define I82577_CFG_REG 22 -#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) -#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ -#define I82577_CTRL_REG 23 - -/* 82577 specific PHY registers */ -#define I82577_PHY_CTRL_2 18 -#define I82577_PHY_LBK_CTRL 19 -#define I82577_PHY_STATUS_2 26 -#define I82577_PHY_DIAG_STATUS 31 - -/* I82577 PHY Status 2 */ -#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 -#define I82577_PHY_STATUS2_MDIX 0x0800 -#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 -#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 -#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100 - -/* I82577 PHY Control 2 */ -#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 -#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 - -/* I82577 PHY Diagnostics Status */ -#define I82577_DSTATUS_CABLE_LENGTH 0x03FC -#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 - -/* BM PHY Copper Specific Control 1 */ -#define BM_CS_CTRL1 16 -#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ - -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - -/* 82577 Mobile Phy Status Register */ -#define HV_M_STATUS 26 -#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 -#define HV_M_STATUS_SPEED_MASK 0x0300 -#define HV_M_STATUS_SPEED_1000 0x0200 -#define HV_M_STATUS_LINK_UP 0x0040 - -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ - -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 - -/* Enable flexible speed on link-up */ -#define IGP01E1000_GMII_FLEX_SPD 0x0010 -#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ - -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 - -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 - -#define IGP02E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F -#define IGP02E1000_AGC_RANGE 15 - -#define IGP03E1000_PHY_MISC_CTRL 0x1B -#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ - -#define E1000_CABLE_LENGTH_UNDEFINED 0xFF - -#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KMRNCTRLSTA_REN 0x00200000 -#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ -#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ -#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ -#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 -#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ - -/* IFE PHY Extended Status Control */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 - -/* IFE PHY Special Control */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -#define IFE_PSC_FORCE_POLARITY 0x0020 -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 - -/* IFE PHY Special Control and LED Control */ -#define IFE_PSCL_PROBE_MODE 0x0020 -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -/* IFE PHY MDIX Control */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ - -#endif diff --git a/roms/ipxe/src/drivers/net/e1000e/e1000e_regs.h b/roms/ipxe/src/drivers/net/e1000e/e1000e_regs.h deleted file mode 100644 index 064d92c9a..000000000 --- a/roms/ipxe/src/drivers/net/e1000e/e1000e_regs.h +++ /dev/null @@ -1,340 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2009 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _E1000E_REGS_H_ -#define _E1000E_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_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ -#define E1000_SVCR 0x000F0 -#define E1000_SVT 0x000F4 -#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_PBA_ECC 0x01100 /* PBA ECC Register */ -#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_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_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ - (0x0C014 + ((_n) * 0x40))) -#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) -#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_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \ - (0x0C030 + ((_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_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ - (0x0E014 + ((_n) * 0x40))) -#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) -#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_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ - (0x0E038 + ((_n) * 0x40))) -#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ - (0x0E03C + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) -#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_CRC_OFFSET 0x05F50 /* CRC Offset register */ - -#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 */ -#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ -#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ - -#endif diff --git a/roms/ipxe/src/drivers/net/eepro100.c b/roms/ipxe/src/drivers/net/eepro100.c index 85840cdfa..ede0a1a4b 100644 --- a/roms/ipxe/src/drivers/net/eepro100.c +++ b/roms/ipxe/src/drivers/net/eepro100.c @@ -25,7 +25,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * * date version by what @@ -909,7 +910,7 @@ static void ifec_refill_rx_ring ( struct net_device *netdev ) * Initial allocation & initialization of the rx ring. * * @v netdev Device of rx ring. - * @ret rc Non-zero if error occured + * @ret rc Non-zero if error occurred */ static int ifec_rx_setup ( struct net_device *netdev ) { @@ -1141,6 +1142,7 @@ PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent 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 diff --git a/roms/ipxe/src/drivers/net/efi/snpnet.c b/roms/ipxe/src/drivers/net/efi/snpnet.c index b725d407f..977908151 100644 --- a/roms/ipxe/src/drivers/net/efi/snpnet.c +++ b/roms/ipxe/src/drivers/net/efi/snpnet.c @@ -57,28 +57,25 @@ static int snpnet_transmit ( struct net_device *netdev, 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 ); - return EFIRC_TO_RC ( efirc ); -} - -/** - * Find a I/O buffer on the list of outstanding Tx buffers and complete it. - * - * @v snpnetdev SNP network device - * @v txbuf Buffer address - */ -static void snpnet_complete ( struct net_device *netdev, void *txbuf ) { - struct io_buffer *tmp; - struct io_buffer *iobuf; - - list_for_each_entry_safe ( iobuf, tmp, &netdev->tx_queue, list ) { - if ( iobuf->data == txbuf ) { - netdev_tx_complete ( netdev, iobuf ); + 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; } /** @@ -92,22 +89,6 @@ static void snpnet_poll ( struct net_device *netdev ) { EFI_STATUS efirc; struct io_buffer *iobuf = NULL; UINTN len; - void *txbuf; - - /* Process Tx completions */ - while ( 1 ) { - efirc = snp->GetStatus ( snp, NULL, &txbuf ); - if ( efirc ) { - DBGC ( snp, "SNP %p could not get status %s\n", snp, - efi_strerror ( efirc ) ); - break; - } - - if ( txbuf == NULL ) - break; - - snpnet_complete ( netdev, txbuf ); - } /* Process received packets */ while ( 1 ) { diff --git a/roms/ipxe/src/drivers/net/epic100.c b/roms/ipxe/src/drivers/net/epic100.c index 5211317ff..8e31a3bfa 100644 --- a/roms/ipxe/src/drivers/net/epic100.c +++ b/roms/ipxe/src/drivers/net/epic100.c @@ -10,7 +10,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include "nic.h" -#include #include "epic100.h" /* Condensed operations for readability */ @@ -251,7 +250,7 @@ epic100_open(void) outl(tmp, txcon); - /* Give adress of RX and TX ring to the chip */ + /* Give address of RX and TX ring to the chip */ outl(virt_to_le32desc(&rx_ring), prcdar); outl(virt_to_le32desc(&tx_ring), ptcdar); @@ -366,7 +365,7 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type, * Arguments: none * * returns: 1 if a packet was received. - * 0 if no pacet was received. + * 0 if no packet was received. * side effects: * returns the packet in the array nic->packet. * returns the length of the packet in nic->packetlen. @@ -377,7 +376,7 @@ epic100_poll(struct nic *nic, int retrieve) { int entry; int retcode; - int status; + unsigned long status; entry = cur_rx % RX_RING_SIZE; if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN) @@ -402,7 +401,7 @@ epic100_poll(struct nic *nic, int retrieve) retcode = 0; } else { /* Omit the four octet CRC from the length. */ - nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4; + nic->packetlen = (status >> 16) - 4; memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen); retcode = 1; } diff --git a/roms/ipxe/src/drivers/net/epic100.h b/roms/ipxe/src/drivers/net/epic100.h index f290b1037..806c4bdab 100644 --- a/roms/ipxe/src/drivers/net/epic100.h +++ b/roms/ipxe/src/drivers/net/epic100.h @@ -64,7 +64,7 @@ enum epic100_registers { #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_PARITY_ERR (0x00001000) /* PCI address 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 */ diff --git a/roms/ipxe/src/drivers/net/etherfabric.c b/roms/ipxe/src/drivers/net/etherfabric.c index 15e7d4c13..6036d3216 100644 --- a/roms/ipxe/src/drivers/net/etherfabric.c +++ b/roms/ipxe/src/drivers/net/etherfabric.c @@ -20,11 +20,11 @@ FILE_LICENCE ( GPL_ANY ); #include #include +#include #include #include #include #include -#include #include #include #include @@ -93,7 +93,6 @@ static int falcon_mdio_read ( struct efab_nic *efab, int device, int location ); #define LPA_EF_10000FULL 0x00040000 #define LPA_EF_10000HALF 0x00080000 -#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) #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 | \ @@ -1567,7 +1566,7 @@ falcon_gmii_wait ( struct efab_nic *efab ) efab_dword_t md_stat; int count; - /* wait upto 10ms */ + /* wait up to 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 ) { @@ -2196,7 +2195,7 @@ falcon_reset_xaui ( struct efab_nic *efab ) falcon_xmac_writel ( efab, ®, FCN_XX_PWR_RST_REG_MAC ); /* Give some time for the link to establish */ - for (count = 0; count < 1000; count++) { /* wait upto 10ms */ + for (count = 0; count < 1000; count++) { /* wait up to 10ms */ falcon_xmac_readl ( efab, ®, FCN_XX_PWR_RST_REG_MAC ); if ( EFAB_DWORD_FIELD ( reg, FCN_XX_RST_XX_EN ) == 0 ) { falcon_setup_xaui ( efab ); @@ -3396,7 +3395,7 @@ falcon_init_sram ( struct efab_nic *efab ) falcon_read ( efab, ®, 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 */ + } while (++count < 20); /* wait up to 0.4 sec */ EFAB_ERR ( "timed out waiting for SRAM reset\n"); return -ETIMEDOUT; @@ -3427,7 +3426,7 @@ falcon_setup_nic ( struct efab_nic *efab ) falcon_write ( efab, ®, FCN_RX_DC_CFG_REG_KER ); /* Set number of RSS CPUs - * bug7244: Increase filter depth to reduce RX_RESET likelyhood + * bug7244: Increase filter depth to reduce RX_RESET likelihood */ EFAB_POPULATE_OWORD_5 ( reg, FCN_NUM_KER, 0, diff --git a/roms/ipxe/src/drivers/net/forcedeth.c b/roms/ipxe/src/drivers/net/forcedeth.c index c34a42961..d8ece9a7a 100644 --- a/roms/ipxe/src/drivers/net/forcedeth.c +++ b/roms/ipxe/src/drivers/net/forcedeth.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 @@ -61,6 +62,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); static inline void pci_push ( void *ioaddr ) { /* force out pending posted writes */ + wmb(); readl ( ioaddr ); } @@ -334,6 +336,7 @@ nv_disable_hw_interrupts ( struct forcedeth_private *priv ) void *ioaddr = priv->mmio_addr; writel ( 0, ioaddr + NvRegIrqMask ); + pci_push ( ioaddr ); } static void @@ -738,8 +741,7 @@ forcedeth_open ( struct net_device *netdev ) ioaddr + NvRegReceiverStatus ); /* Set up slot time */ - get_random_bytes ( &low, sizeof(low) ); - low &= NVREG_SLOTTIME_MASK; + low = ( random() & NVREG_SLOTTIME_MASK ); writel ( low | NVREG_SLOTTIME_DEFAULT, ioaddr + NvRegSlotTime ); writel ( NVREG_TX_DEFERRAL_DEFAULT , ioaddr + NvRegTxDeferral ); @@ -764,7 +766,6 @@ forcedeth_open ( struct net_device *netdev ) ioaddr + NvRegPowerState ); nv_disable_hw_interrupts ( priv ); - pci_push ( ioaddr ); writel ( NVREG_MIISTAT_MASK_ALL, ioaddr + NvRegMIIStatus ); writel ( NVREG_IRQSTAT_MASK, ioaddr + NvRegIrqStatus ); pci_push ( ioaddr ); @@ -997,7 +998,7 @@ forcedeth_poll ( struct net_device *netdev ) DBG ( "forcedeth_poll: status = %#04x\n", status ); - /* Link change interrupt occured. Call always if link is down, + /* Link change interrupt occurred. 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 ); @@ -1018,7 +1019,6 @@ static void forcedeth_close ( struct net_device *netdev ) { struct forcedeth_private *priv = netdev_priv ( netdev ); - void *ioaddr = priv->mmio_addr; DBGP ( "forcedeth_close\n" ); @@ -1028,7 +1028,6 @@ forcedeth_close ( struct net_device *netdev ) /* Disable interrupts on the nic or we will lock up */ nv_disable_hw_interrupts ( priv ); - pci_push ( ioaddr ); nv_free_rxtx_resources ( priv ); diff --git a/roms/ipxe/src/drivers/net/forcedeth.h b/roms/ipxe/src/drivers/net/forcedeth.h index 70686d151..e1cf6f71a 100644 --- a/roms/ipxe/src/drivers/net/forcedeth.h +++ b/roms/ipxe/src/drivers/net/forcedeth.h @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 @@ -54,7 +55,7 @@ struct ring_desc_ex { #define DESC_VER_3 3 #define RX_RING_SIZE 16 -#define TX_RING_SIZE 16 +#define TX_RING_SIZE 32 #define RXTX_RING_SIZE ( ( RX_RING_SIZE ) + ( TX_RING_SIZE ) ) #define RX_RING_MIN 128 #define TX_RING_MIN 64 diff --git a/roms/ipxe/src/drivers/net/igb/igb.c b/roms/ipxe/src/drivers/net/igb/igb.c deleted file mode 100644 index cd5db1ffe..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb.c +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 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 - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -REQUIRE_OBJECT(igb_main); -REQUIRE_OBJECT(igb_82575); diff --git a/roms/ipxe/src/drivers/net/igb/igb.h b/roms/ipxe/src/drivers/net/igb/igb.h deleted file mode 100644 index c8e8205df..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb.h +++ /dev/null @@ -1,324 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - 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 _IGB_H_ -#define _IGB_H_ - -#include "igb_api.h" - -extern int igb_probe ( struct pci_device *pdev ); -extern void igb_remove ( struct pci_device *pdev ); - -struct igb_adapter; - -/* Interrupt defines */ -#define IGB_START_ITR 648 /* ~6000 ints/sec */ - -/* Interrupt modes, as used by the IntMode paramter */ -#define IGB_INT_MODE_LEGACY 0 -#define IGB_INT_MODE_MSI 1 -#define IGB_INT_MODE_MSIX 2 - -#define HW_PERF -/* TX/RX descriptor defines */ -#define IGB_DEFAULT_TXD 256 -#define IGB_MIN_TXD 80 -#define IGB_MAX_TXD 4096 - -#define IGB_DEFAULT_RXD 256 -#define IGB_MIN_RXD 80 -#define IGB_MAX_RXD 4096 - -#define IGB_MIN_ITR_USECS 10 /* 100k irq/sec */ -#define IGB_MAX_ITR_USECS 8191 /* 120 irq/sec */ - -#define NON_Q_VECTORS 1 -#define MAX_Q_VECTORS 8 - -/* Transmit and receive queues */ -#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \ - (hw->mac.type > e1000_82575 ? 8 : 4)) -#define IGB_ABS_MAX_TX_QUEUES 8 -#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES - -#define IGB_MAX_VF_MC_ENTRIES 30 -#define IGB_MAX_VF_FUNCTIONS 8 -#define IGB_MAX_VFTA_ENTRIES 128 -#define IGB_MAX_UTA_ENTRIES 128 -#define MAX_EMULATION_MAC_ADDRS 16 -#define OUI_LEN 3 - -struct vf_data_storage { - unsigned char vf_mac_addresses[ETH_ALEN]; - u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES]; - u16 num_vf_mc_hashes; - u16 default_vf_vlan_id; - u16 vlans_enabled; - unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN]; - u32 uta_table_copy[IGB_MAX_UTA_ENTRIES]; - u32 flags; - unsigned long last_nack; -}; - -#define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ -#define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */ -#define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */ - -/* 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 IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8) -#define IGB_RX_HTHRESH 8 -#define IGB_RX_WTHRESH 1 -#define IGB_TX_PTHRESH 8 -#define IGB_TX_HTHRESH 1 -#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ - adapter->msix_entries) ? 0 : 16) - -/* this is the size past which hardware will drop packets when setting LPE=0 */ -#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 - -/* Supported Rx Buffer Sizes */ -#define IGB_RXBUFFER_128 128 /* Used for packet split */ -#define IGB_RXBUFFER_256 256 /* Used for packet split */ -#define IGB_RXBUFFER_512 512 -#define IGB_RXBUFFER_1024 1024 -#define IGB_RXBUFFER_2048 2048 -#define IGB_RXBUFFER_4096 4096 -#define IGB_RXBUFFER_8192 8192 -#define IGB_RXBUFFER_16384 16384 - -/* Packet Buffer allocations */ -#define IGB_PBA_BYTES_SHIFT 0xA -#define IGB_TX_HEAD_ADDR_SHIFT 7 -#define IGB_PBA_TX_MASK 0xFFFF0000 - -#define IGB_FC_PAUSE_TIME 0x0680 /* 858 usec */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -#define IGB_TX_QUEUE_WAKE 32 -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define IGB_EEPROM_APME 0x0400 - -#ifndef IGB_MASTER_SLAVE -/* Switch to override PHY master/slave setting */ -#define IGB_MASTER_SLAVE e1000_ms_hw_default -#endif - -#define IGB_MNG_VLAN_NONE -1 - -/* wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer */ -struct igb_buffer { - struct sk_buff *skb; - dma_addr_t dma; - dma_addr_t page_dma; - union { - /* TX */ - struct { - unsigned long time_stamp; - u16 length; - u16 next_to_watch; - }; - -#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT - /* RX */ - struct { - unsigned long page_offset; - struct page *page; - }; -#endif - }; -}; - -struct igb_queue_stats { - u64 packets; - u64 bytes; -}; - -struct igb_q_vector { - struct igb_adapter *adapter; /* backlink */ - struct igb_ring *rx_ring; - struct igb_ring *tx_ring; -#if 0 - struct napi_struct napi; -#endif - u32 eims_value; - u16 cpu; - - u16 itr_val; - u8 set_itr; - u8 itr_shift; - void __iomem *itr_register; - -#if 0 - char name[IFNAMSIZ + 9]; -#endif -#ifndef HAVE_NETDEV_NAPI_LIST - struct net_device poll_dev; -#endif -}; - -struct igb_ring { - struct igb_q_vector *q_vector; /* backlink to q_vector */ - struct pci_dev *pdev; /* pci device for dma mapping */ - dma_addr_t dma; /* phys address of the ring */ - void *desc; /* descriptor ring memory */ - unsigned int size; /* length of desc. ring in bytes */ - u16 count; /* number of desc. in the ring */ - u16 next_to_use; - u16 next_to_clean; - u8 queue_index; - u8 reg_idx; - void __iomem *head; - void __iomem *tail; - struct igb_buffer *buffer_info; /* array of buffer info structs */ - - unsigned int total_bytes; - unsigned int total_packets; - - struct igb_queue_stats stats; - - union { - /* TX */ - struct { - unsigned int restart_queue; - u32 ctx_idx; - bool detect_tx_hung; - }; - /* RX */ - struct { - u64 hw_csum_err; - u64 hw_csum_good; - u32 rx_buffer_len; - u16 rx_ps_hdr_size; - bool rx_csum; -#ifdef IGB_LRO - struct net_lro_mgr lro_mgr; - bool lro_used; -#endif - }; - }; -}; - - -#define IGB_ADVTXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS) - -#define IGB_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ - (R)->next_to_clean - (R)->next_to_use - 1) - -#define E1000_RX_DESC_ADV(R, i) \ - (&(((union e1000_adv_rx_desc *)((R).desc))[i])) -#define E1000_TX_DESC_ADV(R, i) \ - (&(((union e1000_adv_tx_desc *)((R).desc))[i])) -#define E1000_TX_CTXTDESC_ADV(R, i) \ - (&(((struct e1000_adv_tx_context_desc *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) - -#define MAX_MSIX_COUNT 10 -/* board specific private data structure */ - -/* board specific private data structure */ -struct igb_adapter { - - /* 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; - - struct e1000_phy_info phy_info; - - u32 min_frame_size; - u32 max_frame_size; - - u32 wol; - u32 pba; - u32 max_hw_frame_size; - - bool fc_autoneg; - - unsigned int flags; - unsigned int flags2; - -#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]; - - struct e1000_tx_desc *tx_base; - struct e1000_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; -}; - -#define IGB_FLAG_HAS_MSI (1 << 0) -#define IGB_FLAG_MSI_ENABLE (1 << 1) -#define IGB_FLAG_DCA_ENABLED (1 << 3) -#define IGB_FLAG_LLI_PUSH (1 << 4) -#define IGB_FLAG_IN_NETPOLL (1 << 5) -#define IGB_FLAG_QUAD_PORT_A (1 << 6) -#define IGB_FLAG_QUEUE_PAIRS (1 << 7) - -#define IGB_82576_TSYNC_SHIFT 19 - -#endif /* _IGB_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_82575.c b/roms/ipxe/src/drivers/net/igb/igb_82575.c deleted file mode 100644 index b5b615ad4..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_82575.c +++ /dev/null @@ -1,1617 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -/* - * 82575EB Gigabit Network Connection - * 82575EB Gigabit Backplane Connection - * 82575GB Gigabit Network Connection - * 82576 Gigabit Network Connection - * 82576 Quad Port Gigabit Mezzanine Adapter - */ - -#include "igb.h" - -static s32 igb_init_phy_params_82575(struct e1000_hw *hw); -static s32 igb_init_nvm_params_82575(struct e1000_hw *hw); -static s32 igb_init_mac_params_82575(struct e1000_hw *hw); -static s32 igb_acquire_phy_82575(struct e1000_hw *hw); -static void igb_release_phy_82575(struct e1000_hw *hw); -static s32 igb_acquire_nvm_82575(struct e1000_hw *hw); -static void igb_release_nvm_82575(struct e1000_hw *hw); -static s32 igb_check_for_link_82575(struct e1000_hw *hw); -static s32 igb_get_cfg_done_82575(struct e1000_hw *hw); -static s32 igb_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -static s32 igb_init_hw_82575(struct e1000_hw *hw); -static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); -static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 igb_reset_hw_82575(struct e1000_hw *hw); -static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, - bool active); -static s32 igb_setup_copper_link_82575(struct e1000_hw *hw); -static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw); -static s32 igb_valid_led_default_82575(struct e1000_hw *hw, u16 *data); -static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, - u32 offset, u16 data); -static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw); -static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); -static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -static s32 igb_get_phy_id_82575(struct e1000_hw *hw); -static void igb_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask); -static bool igb_sgmii_active_82575(struct e1000_hw *hw); -static s32 igb_reset_init_script_82575(struct e1000_hw *hw); -static s32 igb_read_mac_addr_82575(struct e1000_hw *hw); -static void igb_power_down_phy_copper_82575(struct e1000_hw *hw); -static void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); -static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw); - -/** - * igb_init_phy_params_82575 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 igb_init_phy_params_82575(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_init_phy_params_82575"); - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - goto out; - } - - phy->ops.power_up = igb_power_up_phy_copper; - phy->ops.power_down = igb_power_down_phy_copper_82575; - - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - - phy->ops.acquire = igb_acquire_phy_82575; - phy->ops.check_reset_block = igb_check_reset_block_generic; - phy->ops.commit = igb_phy_sw_reset_generic; - phy->ops.get_cfg_done = igb_get_cfg_done_82575; - phy->ops.release = igb_release_phy_82575; - - if (igb_sgmii_active_82575(hw)) { - phy->ops.reset = igb_phy_hw_reset_sgmii_82575; - phy->ops.read_reg = igb_read_phy_reg_sgmii_82575; - phy->ops.write_reg = igb_write_phy_reg_sgmii_82575; - } else { - phy->ops.reset = igb_phy_hw_reset_generic; - phy->ops.read_reg = igb_read_phy_reg_igp; - phy->ops.write_reg = igb_write_phy_reg_igp; - } - - /* Set phy->phy_addr and phy->id. */ - ret_val = igb_get_phy_id_82575(hw); - - /* Verify phy id and set remaining function pointers */ - switch (phy->id) { - case M88E1111_I_PHY_ID: - phy->type = e1000_phy_m88; - phy->ops.check_polarity = igb_check_polarity_m88; - phy->ops.get_info = igb_get_phy_info_m88; -#if 0 - phy->ops.get_cable_length = igb_get_cable_length_m88; -#endif -#if 0 - phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; -#endif - break; - case IGP03E1000_E_PHY_ID: - case IGP04E1000_E_PHY_ID: - phy->type = e1000_phy_igp_3; - phy->ops.check_polarity = igb_check_polarity_igp; - phy->ops.get_info = igb_get_phy_info_igp; -#if 0 - phy->ops.get_cable_length = igb_get_cable_length_igp_2; -#endif -#if 0 - phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_igp; -#endif - phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82575; - phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_generic; - break; - default: - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_init_nvm_params_82575 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 igb_init_nvm_params_82575(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - u16 size; - - DEBUGFUNC("igb_init_nvm_params_82575"); - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; - - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - - /* - * Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - - /* Function Pointers */ - nvm->ops.acquire = igb_acquire_nvm_82575; - nvm->ops.read = igb_read_nvm_eerd; - nvm->ops.release = igb_release_nvm_82575; - nvm->ops.update = igb_update_nvm_checksum_generic; - nvm->ops.valid_led_default = igb_valid_led_default_82575; - nvm->ops.validate = igb_validate_nvm_checksum_generic; - nvm->ops.write = igb_write_nvm_spi; - - return E1000_SUCCESS; -} - -/** - * igb_init_mac_params_82575 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 igb_init_mac_params_82575(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - u32 ctrl_ext = 0; - - DEBUGFUNC("igb_init_mac_params_82575"); - - /* Set media type */ - /* - * The 82575 uses bits 22:23 for link mode. The mode can be changed - * based on the EEPROM. We cannot rely upon device ID. There - * is no distinguishable difference between fiber and internal - * SerDes mode on the 82575. There can be an external PHY attached - * on the SGMII interface. For this, we'll set sgmii_active to true. - */ - hw->phy.media_type = e1000_media_type_copper; - dev_spec->sgmii_active = false; - - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { - case E1000_CTRL_EXT_LINK_MODE_SGMII: - dev_spec->sgmii_active = true; - ctrl_ext |= E1000_CTRL_I2C_ENA; - break; - case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: - hw->phy.media_type = e1000_media_type_internal_serdes; - ctrl_ext |= E1000_CTRL_I2C_ENA; - break; - default: - ctrl_ext &= ~E1000_CTRL_I2C_ENA; - break; - } - - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set uta register count */ - mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES_82575; - if (mac->type == e1000_82576) - mac->rar_entry_count = E1000_RAR_ENTRIES_82576; - /* Set if part includes ASF firmware */ - mac->asf_firmware_present = true; - /* Set if manageability features are enabled. */ - mac->arc_subsystem_valid = - (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) - ? true : false; - - /* Function pointers */ - - /* bus type/speed/width */ - mac->ops.get_bus_info = igb_get_bus_info_pcie_generic; - /* reset */ - mac->ops.reset_hw = igb_reset_hw_82575; - /* hw initialization */ - mac->ops.init_hw = igb_init_hw_82575; - /* link setup */ - mac->ops.setup_link = igb_setup_link_generic; - /* physical interface link setup */ - mac->ops.setup_physical_interface = - (hw->phy.media_type == e1000_media_type_copper) - ? igb_setup_copper_link_82575 - : igb_setup_serdes_link_82575; - /* physical interface shutdown */ - mac->ops.shutdown_serdes = igb_shutdown_serdes_link_82575; - /* check for link */ - mac->ops.check_for_link = igb_check_for_link_82575; - /* receive address register setting */ - mac->ops.rar_set = igb_rar_set_generic; - /* read mac address */ - mac->ops.read_mac_addr = igb_read_mac_addr_82575; - /* multicast address update */ - mac->ops.update_mc_addr_list = igb_update_mc_addr_list_generic; - /* writing VFTA */ - mac->ops.write_vfta = igb_write_vfta_generic; - /* clearing VFTA */ - mac->ops.clear_vfta = igb_clear_vfta_generic; - /* setting MTA */ -#if 0 - mac->ops.mta_set = igb_mta_set_generic; - /* ID LED init */ - mac->ops.id_led_init = igb_id_led_init_generic; - /* blink LED */ - mac->ops.blink_led = igb_blink_led_generic; - /* setup LED */ - mac->ops.setup_led = igb_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = igb_cleanup_led_generic; - /* turn on/off LED */ - mac->ops.led_on = igb_led_on_generic; - mac->ops.led_off = igb_led_off_generic; -#endif - /* clear hardware counters */ - mac->ops.clear_hw_cntrs = igb_clear_hw_cntrs_82575; - /* link info */ - mac->ops.get_link_up_info = igb_get_link_up_info_82575; - - /* set lan id for port to determine which phy lock to use */ - hw->mac.ops.set_lan_id(hw); - - return E1000_SUCCESS; -} - -/** - * igb_init_function_pointers_82575 - Init func ptrs. - * @hw: pointer to the HW structure - * - * Called to initialize all function pointers and parameters. - **/ -void igb_init_function_pointers_82575(struct e1000_hw *hw) -{ - DEBUGFUNC("igb_init_function_pointers_82575"); - - hw->mac.ops.init_params = igb_init_mac_params_82575; - hw->nvm.ops.init_params = igb_init_nvm_params_82575; - hw->phy.ops.init_params = igb_init_phy_params_82575; -#if 0 - hw->mbx.ops.init_params = igb_init_mbx_params_pf; -#endif -} - -/** - * igb_acquire_phy_82575 - Acquire rights to access PHY - * @hw: pointer to the HW structure - * - * Acquire access rights to the correct PHY. - **/ -static s32 igb_acquire_phy_82575(struct e1000_hw *hw) -{ - u16 mask = E1000_SWFW_PHY0_SM; - - DEBUGFUNC("igb_acquire_phy_82575"); - - if (hw->bus.func == E1000_FUNC_1) - mask = E1000_SWFW_PHY1_SM; - - return igb_acquire_swfw_sync_82575(hw, mask); -} - -/** - * igb_release_phy_82575 - Release rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to release access rights to the correct PHY. - **/ -static void igb_release_phy_82575(struct e1000_hw *hw) -{ - u16 mask = E1000_SWFW_PHY0_SM; - - DEBUGFUNC("igb_release_phy_82575"); - - if (hw->bus.func == E1000_FUNC_1) - mask = E1000_SWFW_PHY1_SM; - - igb_release_swfw_sync_82575(hw, mask); -} - -/** - * igb_read_phy_reg_sgmii_82575 - Read PHY register using sgmii - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the serial gigabit media independent - * interface and stores the retrieved information in data. - **/ -static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - s32 ret_val = -E1000_ERR_PARAM; - - DEBUGFUNC("igb_read_phy_reg_sgmii_82575"); - - if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { - DEBUGOUT1("PHY Address %u is out of range\n", offset); - goto out; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = igb_read_phy_reg_i2c(hw, offset, data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_write_phy_reg_sgmii_82575 - Write PHY register using sgmii - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset using the serial gigabit - * media independent interface. - **/ -static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, - u16 data) -{ - s32 ret_val = -E1000_ERR_PARAM; - - DEBUGFUNC("igb_write_phy_reg_sgmii_82575"); - - if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { - DEBUGOUT1("PHY Address %d is out of range\n", offset); - goto out; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = igb_write_phy_reg_i2c(hw, offset, data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_get_phy_id_82575 - Retrieve PHY addr and id - * @hw: pointer to the HW structure - * - * Retrieves the PHY address and ID for both PHY's which do and do not use - * sgmi interface. - **/ -static s32 igb_get_phy_id_82575(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_id; - u32 ctrl_ext; - - DEBUGFUNC("igb_get_phy_id_82575"); - - /* - * For SGMII PHYs, we try the list of possible addresses until - * we find one that works. For non-SGMII PHYs - * (e.g. integrated copper PHYs), an address of 1 should - * work. The result of this function should mean phy->phy_addr - * and phy->id are set correctly. - */ - if (!igb_sgmii_active_82575(hw)) { - phy->addr = 1; - ret_val = igb_get_phy_id(hw); - goto out; - } - - /* Power on sgmii phy if it is disabled */ - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - E1000_WRITE_REG(hw, E1000_CTRL_EXT, - ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); - E1000_WRITE_FLUSH(hw); - msec_delay(300); - - /* - * The address field in the I2CCMD register is 3 bits and 0 is invalid. - * Therefore, we need to test 1-7 - */ - for (phy->addr = 1; phy->addr < 8; phy->addr++) { - ret_val = igb_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); - if (ret_val == E1000_SUCCESS) { - DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", - phy_id, - phy->addr); - /* - * At the time of this writing, The M88 part is - * the only supported SGMII PHY product. - */ - if (phy_id == M88_VENDOR) - break; - } else { - DEBUGOUT1("PHY address %u was unreadable\n", - phy->addr); - } - } - - /* A valid PHY type couldn't be found. */ - if (phy->addr == 8) { - phy->addr = 0; - ret_val = -E1000_ERR_PHY; - } else { - ret_val = igb_get_phy_id(hw); - } - - /* restore previous sfp cage power state */ - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - -out: - return ret_val; -} - -/** - * igb_phy_hw_reset_sgmii_82575 - Performs a PHY reset - * @hw: pointer to the HW structure - * - * Resets the PHY using the serial gigabit media independent interface. - **/ -static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_phy_hw_reset_sgmii_82575"); - - /* - * This isn't a true "hard" reset, but is the only reset - * available to us at this time. - */ - - DEBUGOUT("Soft resetting SGMII attached PHY...\n"); - - if (!(hw->phy.ops.write_reg)) - goto out; - - /* - * SFP documentation requires the following to configure the SPF module - * to work on SGMII. No further documentation is given. - */ - ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.commit(hw); - -out: - return ret_val; -} - -/** - * igb_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 data; - - DEBUGFUNC("igb_set_d0_lplu_state_82575"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - goto out; - - if (active) { - data |= IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else { - data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } - -out: - return ret_val; -} - -/** - * igb_acquire_nvm_82575 - Request for access to EEPROM - * @hw: pointer to the HW structure - * - * Acquire the necessary semaphores for exclusive access to the EEPROM. - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -static s32 igb_acquire_nvm_82575(struct e1000_hw *hw) -{ - s32 ret_val; - - DEBUGFUNC("igb_acquire_nvm_82575"); - - ret_val = igb_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); - if (ret_val) - goto out; - - ret_val = igb_acquire_nvm_generic(hw); - - if (ret_val) - igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); - -out: - return ret_val; -} - -/** - * igb_release_nvm_82575 - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit, - * then release the semaphores acquired. - **/ -static void igb_release_nvm_82575(struct e1000_hw *hw) -{ - DEBUGFUNC("igb_release_nvm_82575"); - - igb_release_nvm_generic(hw); - igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); -} - -/** - * igb_acquire_swfw_sync_82575 - Acquire SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Acquire the SW/FW semaphore to access the PHY or NVM. The mask - * will also specify which port we're acquiring the lock for. - **/ -static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - u32 swmask = mask; - u32 fwmask = mask << 16; - s32 ret_val = E1000_SUCCESS; - s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ - - DEBUGFUNC("igb_acquire_swfw_sync_82575"); - - while (i < timeout) { - if (igb_get_hw_semaphore_generic(hw)) { - ret_val = -E1000_ERR_SWFW_SYNC; - goto out; - } - - swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); - if (!(swfw_sync & (fwmask | swmask))) - break; - - /* - * Firmware currently using resource (fwmask) - * or other software thread using resource (swmask) - */ - igb_put_hw_semaphore_generic(hw); - msec_delay_irq(5); - i++; - } - - if (i == timeout) { - DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); - ret_val = -E1000_ERR_SWFW_SYNC; - goto out; - } - - swfw_sync |= swmask; - E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); - - igb_put_hw_semaphore_generic(hw); - -out: - return ret_val; -} - -/** - * igb_release_swfw_sync_82575 - Release SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Release the SW/FW semaphore used to access the PHY or NVM. The mask - * will also specify which port we're releasing the lock for. - **/ -static void igb_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - - DEBUGFUNC("igb_release_swfw_sync_82575"); - - while (igb_get_hw_semaphore_generic(hw) != E1000_SUCCESS); - /* Empty */ - - swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); - swfw_sync &= ~mask; - E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); - - igb_put_hw_semaphore_generic(hw); -} - -/** - * igb_get_cfg_done_82575 - Read config done bit - * @hw: pointer to the HW structure - * - * Read the management control register for the config done bit for - * completion status. NOTE: silicon which is EEPROM-less will fail trying - * to read the config done bit, so an error is *ONLY* logged and returns - * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon - * would not be able to be reset or change link. - **/ -static s32 igb_get_cfg_done_82575(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - u32 mask = E1000_NVM_CFG_DONE_PORT_0; - - DEBUGFUNC("igb_get_cfg_done_82575"); - - if (hw->bus.func == E1000_FUNC_1) - mask = E1000_NVM_CFG_DONE_PORT_1; - while (timeout) { - if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) - break; - msec_delay(1); - timeout--; - } - if (!timeout) { - DEBUGOUT("MNG configuration cycle has not completed.\n"); - } - - /* If EEPROM is not marked present, init the PHY manually */ - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && - (hw->phy.type == e1000_phy_igp_3)) - igb_phy_init_script_igp3(hw); - - return ret_val; -} - -/** - * igb_get_link_up_info_82575 - Get link speed/duplex info - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * This is a wrapper function, if using the serial gigabit media independent - * interface, use PCS to retrieve the link speed and duplex information. - * Otherwise, use the generic function to get the link speed and duplex info. - **/ -static s32 igb_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - DEBUGFUNC("igb_get_link_up_info_82575"); - - if (hw->phy.media_type != e1000_media_type_copper) - ret_val = igb_get_pcs_speed_and_duplex_82575(hw, speed, - duplex); - else - ret_val = igb_get_speed_and_duplex_copper_generic(hw, speed, - duplex); - - return ret_val; -} - -/** - * igb_check_for_link_82575 - Check for link - * @hw: pointer to the HW structure - * - * If sgmii is enabled, then use the pcs register to determine link, otherwise - * use the generic interface for determining link. - **/ -static s32 igb_check_for_link_82575(struct e1000_hw *hw) -{ - s32 ret_val; - u16 speed, duplex; - - DEBUGFUNC("igb_check_for_link_82575"); - - if (hw->phy.media_type != e1000_media_type_copper) { - ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed, - &duplex); - /* - * Use this flag to determine if link needs to be checked or - * not. If we have link clear the flag so that we do not - * continue to check for link. - */ - hw->mac.get_link_status = !hw->mac.serdes_has_link; - } else { - ret_val = igb_check_for_copper_link_generic(hw); - } - - return ret_val; -} - -/** - * igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Using the physical coding sub-layer (PCS), retrieve the current speed and - * duplex, then store the values in the pointers provided. - **/ -static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, - u16 *speed, u16 *duplex) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 pcs; - - DEBUGFUNC("igb_get_pcs_speed_and_duplex_82575"); - - /* Set up defaults for the return values of this function */ - mac->serdes_has_link = false; - *speed = 0; - *duplex = 0; - - /* - * Read the PCS Status register for link state. For non-copper mode, - * the status register is not accurate. The PCS status register is - * used instead. - */ - pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); - - /* - * The link up bit determines when link is up on autoneg. The sync ok - * gets set once both sides sync up and agree upon link. Stable link - * can be determined by checking for both link up and link sync ok - */ - if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) { - mac->serdes_has_link = true; - - /* Detect and store PCS speed */ - if (pcs & E1000_PCS_LSTS_SPEED_1000) { - *speed = SPEED_1000; - } else if (pcs & E1000_PCS_LSTS_SPEED_100) { - *speed = SPEED_100; - } else { - *speed = SPEED_10; - } - - /* Detect and store PCS duplex */ - if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) { - *duplex = FULL_DUPLEX; - } else { - *duplex = HALF_DUPLEX; - } - } - - return E1000_SUCCESS; -} - -/** - * igb_shutdown_serdes_link_82575 - Remove link during power down - * @hw: pointer to the HW structure - * - * In the case of serdes shut down sfp and PCS on driver unload - * when management pass thru is not enabled. - **/ -void igb_shutdown_serdes_link_82575(struct e1000_hw *hw) -{ -#if 0 - u32 reg; -#endif - u16 eeprom_data = 0; - - if ((hw->phy.media_type != e1000_media_type_internal_serdes) && - !igb_sgmii_active_82575(hw)) - return; - - if (hw->bus.func == E1000_FUNC_0) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - else if (hw->bus.func == E1000_FUNC_1) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - - /* - * If APM is not enabled in the EEPROM and management interface is - * not enabled, then power down. - */ -#if 0 - if (!(eeprom_data & E1000_NVM_APME_82575) && - !igb_enable_mng_pass_thru(hw)) { - /* Disable PCS to turn off link */ - reg = E1000_READ_REG(hw, E1000_PCS_CFG0); - reg &= ~E1000_PCS_CFG_PCS_EN; - E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); - - /* shutdown the laser */ - reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - reg |= E1000_CTRL_EXT_SDP3_DATA; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); - - /* flush the write to verify completion */ - E1000_WRITE_FLUSH(hw); - msec_delay(1); - } -#endif - return; -} - -/** - * igb_reset_hw_82575 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 igb_reset_hw_82575(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - DEBUGFUNC("igb_reset_hw_82575"); - - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = igb_disable_pcie_master_generic(hw); - if (ret_val) { - DEBUGOUT("PCI-E Master disable polling has failed.\n"); - } - - /* set the completion timeout for interface */ - ret_val = igb_set_pcie_completion_timeout(hw); - if (ret_val) { - DEBUGOUT("PCI-E Set completion timeout has failed.\n"); - } - - DEBUGOUT("Masking off all interrupts\n"); - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - - E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(hw); - - msec_delay(10); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - DEBUGOUT("Issuing a global reset to MAC\n"); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); - - ret_val = igb_get_auto_rd_done_generic(hw); - if (ret_val) { - /* - * When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - DEBUGOUT("Auto Read Done did not complete\n"); - } - - /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) - igb_reset_init_script_82575(hw); - - /* Clear any pending interrupt events. */ - E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - E1000_READ_REG(hw, E1000_ICR); - - /* Install any alternate MAC address into RAR0 */ - ret_val = igb_check_alt_mac_addr_generic(hw); - - return ret_val; -} - -/** - * igb_init_hw_82575 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 igb_init_hw_82575(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - u16 i, rar_count = mac->rar_entry_count; - - DEBUGFUNC("igb_init_hw_82575"); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - if (ret_val) { - DEBUGOUT("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ - } - - /* Disabling VLAN filtering */ - DEBUGOUT("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address */ - igb_init_rx_addrs_generic(hw, rar_count); - - /* Zero out the Multicast HASH table */ - DEBUGOUT("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Zero out the Unicast HASH table */ - DEBUGOUT("Zeroing the UTA\n"); - for (i = 0; i < mac->uta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* - * Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - igb_clear_hw_cntrs_82575(hw); - - return ret_val; -} - -/** - * igb_setup_copper_link_82575 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Configures the link for auto-neg or forced speed and duplex. Then we check - * for link, once link is established calls to configure collision distance - * and flow control are called. - **/ -static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - DEBUGFUNC("igb_setup_copper_link_82575"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - ret_val = igb_setup_serdes_link_82575(hw); - if (ret_val) - goto out; - - if (igb_sgmii_active_82575(hw) && !hw->phy.reset_disable) { - ret_val = hw->phy.ops.reset(hw); - if (ret_val) { - DEBUGOUT("Error resetting the PHY.\n"); - goto out; - } - } - switch (hw->phy.type) { - case e1000_phy_m88: - ret_val = igb_copper_link_setup_m88(hw); - break; - case e1000_phy_igp_3: - ret_val = igb_copper_link_setup_igp(hw); - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - if (ret_val) - goto out; - - ret_val = igb_setup_copper_link_generic(hw); -out: - return ret_val; -} - -/** - * igb_setup_serdes_link_82575 - Setup link for serdes - * @hw: pointer to the HW structure - * - * Configure the physical coding sub-layer (PCS) link. The PCS link is - * used on copper connections where the serialized gigabit media independent - * interface (sgmii), or serdes fiber is being used. Configures the link - * for auto-negotiation or forces speed/duplex. - **/ -static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) -{ - u32 ctrl_reg, reg; - - DEBUGFUNC("igb_setup_serdes_link_82575"); - - if ((hw->phy.media_type != e1000_media_type_internal_serdes) && - !igb_sgmii_active_82575(hw)) - return E1000_SUCCESS; - - /* - * On the 82575, SerDes loopback mode persists until it is - * explicitly turned off or a power cycle is performed. A read to - * the register does not indicate its status. Therefore, we ensure - * loopback mode is disabled during initialization. - */ - E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - - /* power on the sfp cage if present */ - reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - reg &= ~E1000_CTRL_EXT_SDP3_DATA; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); - - ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); - ctrl_reg |= E1000_CTRL_SLU; - - if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { - /* set both sw defined pins */ - ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; - - /* Set switch control to serdes energy detect */ - reg = E1000_READ_REG(hw, E1000_CONNSW); - reg |= E1000_CONNSW_ENRGSRC; - E1000_WRITE_REG(hw, E1000_CONNSW, reg); - } - - reg = E1000_READ_REG(hw, E1000_PCS_LCTL); - - if (igb_sgmii_active_82575(hw)) { - /* allow time for SFP cage to power up phy */ - msec_delay(300); - - /* AN time out should be disabled for SGMII mode */ - reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); - } else { - ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | - E1000_CTRL_FD | E1000_CTRL_FRCDPX; - } - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); - - /* - * New SerDes mode allows for forcing speed or autonegotiating speed - * at 1gb. Autoneg should be default set by most drivers. This is the - * mode that will be compatible with older link partners and switches. - * However, both are supported by the hardware and some drivers/tools. - */ - - reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | - E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - - /* - * We force flow control to prevent the CTRL register values from being - * overwritten by the autonegotiated flow control values - */ - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - - /* - * we always set sgmii to autoneg since it is the phy that will be - * forcing the link and the serdes is just a go-between - */ - if (hw->mac.autoneg || igb_sgmii_active_82575(hw)) { - /* Set PCS register for autoneg */ - reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ - E1000_PCS_LCTL_FDV_FULL | /* SerDes Full dplx */ - E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ - E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ - DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); - } else { - /* Check for duplex first */ - if (hw->mac.forced_speed_duplex & E1000_ALL_FULL_DUPLEX) - reg |= E1000_PCS_LCTL_FDV_FULL; - - /* No need to check for 1000/full since the spec states that - * it requires autoneg to be enabled */ - /* Now set speed */ - if (hw->mac.forced_speed_duplex & E1000_ALL_100_SPEED) - reg |= E1000_PCS_LCTL_FSV_100; - - /* Force speed and force link */ - reg |= E1000_PCS_LCTL_FSD | - E1000_PCS_LCTL_FORCE_LINK | - E1000_PCS_LCTL_FLV_LINK_UP; - - DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); - } - - E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); - - if (!igb_sgmii_active_82575(hw)) - igb_force_mac_fc_generic(hw); - - return E1000_SUCCESS; -} - -/** - * igb_valid_led_default_82575 - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -static s32 igb_valid_led_default_82575(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - DEBUGFUNC("igb_valid_led_default_82575"); - - ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { - switch(hw->phy.media_type) { - case e1000_media_type_internal_serdes: - *data = ID_LED_DEFAULT_82575_SERDES; - break; - case e1000_media_type_copper: - default: - *data = ID_LED_DEFAULT; - break; - } - } -out: - return ret_val; -} - -/** - * igb_sgmii_active_82575 - Return sgmii state - * @hw: pointer to the HW structure - * - * 82575 silicon has a serialized gigabit media independent interface (sgmii) - * which can be enabled for use in the embedded applications. Simply - * return the current state of the sgmii interface. - **/ -static bool igb_sgmii_active_82575(struct e1000_hw *hw) -{ - struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - return dev_spec->sgmii_active; -} - -/** - * igb_reset_init_script_82575 - Inits HW defaults after reset - * @hw: pointer to the HW structure - * - * Inits recommended HW defaults after a reset when there is no EEPROM - * detected. This is only for the 82575. - **/ -static s32 igb_reset_init_script_82575(struct e1000_hw* hw) -{ - DEBUGFUNC("igb_reset_init_script_82575"); - - if (hw->mac.type == e1000_82575) { - DEBUGOUT("Running reset init script for 82575\n"); - /* SerDes configuration via SERDESCTRL */ - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); - - /* CCM configuration via CCMCTL register */ - igb_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); - igb_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); - - /* PCIe lanes configuration */ - igb_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); - igb_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); - igb_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); - igb_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); - - /* PCIe PLL Configuration */ - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); - igb_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); - } - - return E1000_SUCCESS; -} - -/** - * igb_read_mac_addr_82575 - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 igb_read_mac_addr_82575(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_read_mac_addr_82575"); - - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = igb_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; - - ret_val = igb_read_mac_addr_generic(hw); - -out: - return ret_val; -} - -/** - * igb_power_down_phy_copper_82575 - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void igb_power_down_phy_copper_82575(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_mac_info *mac = &hw->mac; - - if (!(phy->ops.check_reset_block)) - return; - - /* If the management interface is not enabled, then power down */ - if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) - igb_power_down_phy_copper(hw); - - return; -} - -/** - * igb_clear_hw_cntrs_82575 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw) -{ - DEBUGFUNC("igb_clear_hw_cntrs_82575"); - - igb_clear_hw_cntrs_base_generic(hw); - - E1000_READ_REG(hw, E1000_PRC64); - E1000_READ_REG(hw, E1000_PRC127); - E1000_READ_REG(hw, E1000_PRC255); - E1000_READ_REG(hw, E1000_PRC511); - E1000_READ_REG(hw, E1000_PRC1023); - E1000_READ_REG(hw, E1000_PRC1522); - E1000_READ_REG(hw, E1000_PTC64); - E1000_READ_REG(hw, E1000_PTC127); - E1000_READ_REG(hw, E1000_PTC255); - E1000_READ_REG(hw, E1000_PTC511); - E1000_READ_REG(hw, E1000_PTC1023); - E1000_READ_REG(hw, E1000_PTC1522); - - E1000_READ_REG(hw, E1000_ALGNERRC); - E1000_READ_REG(hw, E1000_RXERRC); - E1000_READ_REG(hw, E1000_TNCRS); - E1000_READ_REG(hw, E1000_CEXTERR); - E1000_READ_REG(hw, E1000_TSCTC); - E1000_READ_REG(hw, E1000_TSCTFC); - - E1000_READ_REG(hw, E1000_MGTPRC); - E1000_READ_REG(hw, E1000_MGTPDC); - E1000_READ_REG(hw, E1000_MGTPTC); - - E1000_READ_REG(hw, E1000_IAC); - E1000_READ_REG(hw, E1000_ICRXOC); - - E1000_READ_REG(hw, E1000_ICRXPTC); - E1000_READ_REG(hw, E1000_ICRXATC); - E1000_READ_REG(hw, E1000_ICTXPTC); - E1000_READ_REG(hw, E1000_ICTXATC); - E1000_READ_REG(hw, E1000_ICTXQEC); - E1000_READ_REG(hw, E1000_ICTXQMTC); - E1000_READ_REG(hw, E1000_ICRXDMTC); - - E1000_READ_REG(hw, E1000_CBTMPC); - E1000_READ_REG(hw, E1000_HTDPMC); - E1000_READ_REG(hw, E1000_CBRMPC); - E1000_READ_REG(hw, E1000_RPTHC); - E1000_READ_REG(hw, E1000_HGPTC); - E1000_READ_REG(hw, E1000_HTCBDPC); - E1000_READ_REG(hw, E1000_HGORCL); - E1000_READ_REG(hw, E1000_HGORCH); - E1000_READ_REG(hw, E1000_HGOTCL); - E1000_READ_REG(hw, E1000_HGOTCH); - E1000_READ_REG(hw, E1000_LENERRS); - - /* This register should not be read in copper configurations */ - if ((hw->phy.media_type == e1000_media_type_internal_serdes) || - igb_sgmii_active_82575(hw)) - E1000_READ_REG(hw, E1000_SCVPC); -} - -/** - * igb_rx_fifo_flush_82575 - Clean rx fifo after RX enable - * @hw: pointer to the HW structure - * - * After rx enable if managability is enabled then there is likely some - * bad data at the start of the fifo and possibly in the DMA fifo. This - * function clears the fifos and flushes any packets that came in as rx was - * being enabled. - **/ -void igb_rx_fifo_flush_82575(struct e1000_hw *hw) -{ - u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; - int i, ms_wait; - - DEBUGFUNC("igb_rx_fifo_workaround_82575"); - if (hw->mac.type != e1000_82575 || - !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) - return; - - /* Disable all RX queues */ - for (i = 0; i < 4; i++) { - rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); - E1000_WRITE_REG(hw, E1000_RXDCTL(i), - rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); - } - /* Poll all queues to verify they have shut down */ - for (ms_wait = 0; ms_wait < 10; ms_wait++) { - msec_delay(1); - rx_enabled = 0; - for (i = 0; i < 4; i++) - rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); - if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) - break; - } - - if (ms_wait == 10) { - DEBUGOUT("Queue disable timed out after 10ms\n"); - } - /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all - * incoming packets are rejected. Set enable and wait 2ms so that - * any packet that was coming in as RCTL.EN was set is flushed - */ - rfctl = E1000_READ_REG(hw, E1000_RFCTL); - E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); - - rlpml = E1000_READ_REG(hw, E1000_RLPML); - E1000_WRITE_REG(hw, E1000_RLPML, 0); - - rctl = E1000_READ_REG(hw, E1000_RCTL); - temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); - temp_rctl |= E1000_RCTL_LPE; - - E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); - E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); - E1000_WRITE_FLUSH(hw); - msec_delay(2); - - /* Enable RX queues that were previously enabled and restore our - * previous state - */ - for (i = 0; i < 4; i++) - E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); - E1000_WRITE_REG(hw, E1000_RCTL, rctl); - E1000_WRITE_FLUSH(hw); - - E1000_WRITE_REG(hw, E1000_RLPML, rlpml); - E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); - - /* Flush receive errors generated by workaround */ - E1000_READ_REG(hw, E1000_ROC); - E1000_READ_REG(hw, E1000_RNBC); - E1000_READ_REG(hw, E1000_MPC); -} - -/** - * igb_set_pcie_completion_timeout - set pci-e completion timeout - * @hw: pointer to the HW structure - * - * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, - * however the hardware default for these parts is 500us to 1ms which is less - * than the 10ms recommended by the pci-e spec. To address this we need to - * increase the value to either 10ms to 200ms for capability version 1 config, - * or 16ms to 55ms for version 2. - **/ -static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw) -{ - u32 gcr = E1000_READ_REG(hw, E1000_GCR); - s32 ret_val = E1000_SUCCESS; - u16 pcie_devctl2; - - /* only take action if timeout value is defaulted to 0 */ - if (gcr & E1000_GCR_CMPL_TMOUT_MASK) - goto out; - - /* - * if capababilities version is type 1 we can write the - * timeout of 10ms to 200ms through the GCR register - */ - if (!(gcr & E1000_GCR_CAP_VER2)) { - gcr |= E1000_GCR_CMPL_TMOUT_10ms; - goto out; - } - - /* - * for version 2 capabilities we need to write the config space - * directly in order to set the completion timeout value for - * 16ms to 55ms - */ - ret_val = igb_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, - &pcie_devctl2); - if (ret_val) - goto out; - - pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; - - ret_val = igb_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, - &pcie_devctl2); -out: - /* disable completion timeout resend */ - gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; - - E1000_WRITE_REG(hw, E1000_GCR, gcr); - return ret_val; -} - -/** - * igb_vmdq_set_loopback_pf - enable or disable vmdq loopback - * @hw: pointer to the hardware struct - * @enable: state to enter, either enabled or disabled - * - * enables/disables L2 switch loopback functionality. - **/ -void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) -{ - u32 dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); - - if (enable) - dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; - else - dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; - - E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); -} - -/** - * igb_vmdq_set_replication_pf - enable or disable vmdq replication - * @hw: pointer to the hardware struct - * @enable: state to enter, either enabled or disabled - * - * enables/disables replication of packets across multiple pools. - **/ -void igb_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) -{ - u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); - - if (enable) - vt_ctl |= E1000_VT_CTL_VM_REPL_EN; - else - vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; - - E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); -} - -static struct pci_device_id igb_82575_nics[] = { - PCI_ROM(0x8086, 0x10C9, "E1000_DEV_ID_82576", "E1000_DEV_ID_82576", 0), - PCI_ROM(0x8086, 0x150A, "E1000_DEV_ID_82576_NS", "E1000_DEV_ID_82576_NS", 0), - PCI_ROM(0x8086, 0x1518, "E1000_DEV_ID_82576_NS_SERDES", "E1000_DEV_ID_82576_NS_SERDES", 0), - PCI_ROM(0x8086, 0x10E6, "E1000_DEV_ID_82576_FIBER", "E1000_DEV_ID_82576_FIBER", 0), - PCI_ROM(0x8086, 0x10E7, "E1000_DEV_ID_82576_SERDES", "E1000_DEV_ID_82576_SERDES", 0), - PCI_ROM(0x8086, 0x150D, "E1000_DEV_ID_82576_SERDES_QUAD", "E1000_DEV_ID_82576_SERDES_QUAD", 0), - PCI_ROM(0x8086, 0x10E8, "E1000_DEV_ID_82576_QUAD_COPPER", "E1000_DEV_ID_82576_QUAD_COPPER", 0), - PCI_ROM(0x8086, 0x10A7, "E1000_DEV_ID_82575EB_COPPER", "E1000_DEV_ID_82575EB_COPPER", 0), - PCI_ROM(0x8086, 0x10A9, "E1000_DEV_ID_82575EB_FIBER_SERDES", "E1000_DEV_ID_82575EB_FIBER_SERDES", 0), - PCI_ROM(0x8086, 0x10D6, "E1000_DEV_ID_82575GB_QUAD_COPPER", "E1000_DEV_ID_82575GB_QUAD_COPPER", 0), -}; - -struct pci_driver igb_82575_driver __pci_driver = { - .ids = igb_82575_nics, - .id_count = (sizeof (igb_82575_nics) / sizeof (igb_82575_nics[0])), - .probe = igb_probe, - .remove = igb_remove, -}; diff --git a/roms/ipxe/src/drivers/net/igb/igb_82575.h b/roms/ipxe/src/drivers/net/igb/igb_82575.h deleted file mode 100644 index 12c9a249d..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_82575.h +++ /dev/null @@ -1,442 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_82575_H_ -#define _IGB_82575_H_ - -#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_DEF1_DEF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_OFF1_ON2)) -/* - * Receive Address Register Count - * Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. - * These entries are also used for MAC-based filtering. - */ -/* - * For 82576, there are an additional set of RARs that begin at an offset - * separate from the first set of RARs. - */ -#define E1000_RAR_ENTRIES_82575 16 -#define E1000_RAR_ENTRIES_82576 24 - -struct e1000_adv_data_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - u32 data; - struct { - u32 datalen :16; /* Data buffer length */ - u32 rsvd :4; - u32 dtyp :4; /* Descriptor type */ - u32 dcmd :8; /* Descriptor command */ - } config; - } lower; - union { - u32 data; - struct { - u32 status :4; /* Descriptor status */ - u32 idx :4; - u32 popts :6; /* Packet Options */ - u32 paylen :18; /* Payload length */ - } options; - } upper; -}; - -#define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */ -#define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */ -#define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */ -#define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */ -#define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */ -#define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */ -#define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */ -#define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */ -#define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */ -#define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */ -#define E1000_ADV_DCMD_RS 0x8 /* Report Status */ -#define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */ -#define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */ -/* Extended Device Control */ -#define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */ - -struct e1000_adv_context_desc { - union { - u32 ip_config; - struct { - u32 iplen :9; - u32 maclen :7; - u32 vlan_tag :16; - } fields; - } ip_setup; - u32 seq_num; - union { - u64 l4_config; - struct { - u32 mkrloc :9; - u32 tucmd :11; - u32 dtyp :4; - u32 adv :8; - u32 rsvd :4; - u32 idx :4; - u32 l4len :8; - u32 mss :16; - } fields; - } l4_setup; -}; - -/* 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 - -#define E1000_TX_HEAD_WB_ENABLE 0x1 -#define E1000_TX_SEQNUM_WB_ENABLE 0x2 - -#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 -#define E1000_MRQC_ENABLE_VMDQ 0x00000003 -#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 -#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 -#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 -#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 - -#define E1000_VMRCTL_MIRROR_PORT_SHIFT 8 -#define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << E1000_VMRCTL_MIRROR_PORT_SHIFT) -#define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0) -#define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1) -#define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2) - -#define E1000_EICR_TX_QUEUE ( \ - E1000_EICR_TX_QUEUE0 | \ - E1000_EICR_TX_QUEUE1 | \ - E1000_EICR_TX_QUEUE2 | \ - E1000_EICR_TX_QUEUE3) - -#define E1000_EICR_RX_QUEUE ( \ - E1000_EICR_RX_QUEUE0 | \ - E1000_EICR_RX_QUEUE1 | \ - E1000_EICR_RX_QUEUE2 | \ - E1000_EICR_RX_QUEUE3) - -#define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE -#define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE - -#define EIMS_ENABLE_MASK ( \ - E1000_EIMS_RX_QUEUE | \ - E1000_EIMS_TX_QUEUE | \ - E1000_EIMS_TCP_TIMER | \ - E1000_EIMS_OTHER) - -/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ -#define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ -#define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ -#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ -#define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */ -#define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */ -#define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */ -#define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */ -#define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */ -#define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */ -#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */ - -/* Receive Descriptor - Advanced */ -union e1000_adv_rx_desc { - struct { - __le64 pkt_addr; /* Packet buffer address */ - __le64 hdr_addr; /* Header buffer address */ - } read; - struct { - struct { - union { - __le32 data; - struct { - __le16 pkt_info; /*RSS type, Pkt type*/ - __le16 hdr_info; /* Split Header, - * header buffer len*/ - } hs_rss; - } lo_dword; - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; /* Packet length */ - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define E1000_RXDADV_RSSTYPE_MASK 0x0000000F -#define E1000_RXDADV_RSSTYPE_SHIFT 12 -#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 -#define E1000_RXDADV_HDRBUFLEN_SHIFT 5 -#define E1000_RXDADV_SPLITHEADER_EN 0x00001000 -#define E1000_RXDADV_SPH 0x8000 -#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */ -#define E1000_RXDADV_ERR_HBO 0x00800000 - -/* RSS Hash results */ -#define E1000_RXDADV_RSSTYPE_NONE 0x00000000 -#define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001 -#define E1000_RXDADV_RSSTYPE_IPV4 0x00000002 -#define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003 -#define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004 -#define E1000_RXDADV_RSSTYPE_IPV6 0x00000005 -#define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006 -#define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007 -#define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008 -#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 - -/* RSS Packet Types as indicated in the receive descriptor */ -#define E1000_RXDADV_PKTTYPE_NONE 0x00000000 -#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */ -#define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */ -#define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */ -#define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */ -#define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ -#define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ -#define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ -#define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ - -#define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ -#define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ -#define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ -#define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ -#define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ -#define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ - -/* LinkSec results */ -/* Security Processing bit Indication */ -#define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000 -#define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 -#define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 -#define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 -#define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 - -#define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000 -#define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 -#define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 -#define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 -#define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000 - -/* Transmit Descriptor - Advanced */ -union e1000_adv_tx_desc { - struct { - __le64 buffer_addr; /* Address of descriptor's data buf */ - __le32 cmd_type_len; - __le32 olinfo_status; - } read; - struct { - __le64 rsvd; /* Reserved */ - __le32 nxtseq_seed; - __le32 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_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ -#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_MAC_LINKSEC 0x00040000 /* Apply LinkSec on packet */ -#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */ -#define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */ -#define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ -#define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ -#define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ -#define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ -#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/ -#define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ -#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ - -/* Context descriptors */ -struct e1000_adv_tx_context_desc { - __le32 vlan_macip_lens; - __le32 seqnum_seed; - __le32 type_tucmd_mlhl; - __le32 mss_l4len_idx; -}; - -#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ -#define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ -#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ -#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ -#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ -#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ -#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ -#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ -/* IPSec Encrypt Enable for ESP */ -#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000 -#define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */ -#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ -#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ -/* Adv ctxt IPSec SA IDX mask */ -#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF -/* Adv ctxt IPSec ESP len mask */ -#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF - -/* Additional Transmit Descriptor Control definitions */ -#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ -#define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */ -/* Tx Queue Arbitration Priority 0=low, 1=high */ -#define E1000_TXDCTL_PRIORITY 0x08000000 - -/* Additional Receive Descriptor Control definitions */ -#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */ -#define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. write-back flushing */ - -/* Direct Cache Access (DCA) definitions */ -#define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ -#define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ - -#define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ -#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ - -#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ -#define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ -#define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ -#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ - -#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ -#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ -#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ - -#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ -#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ -#define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */ -#define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */ - -/* Additional interrupt register bit definitions */ -#define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ -#define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ -#define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ - -/* ETQF register bit definitions */ -#define E1000_ETQF_FILTER_ENABLE (1 << 26) -#define E1000_ETQF_IMM_INT (1 << 29) -#define E1000_ETQF_1588 (1 << 30) -#define E1000_ETQF_QUEUE_ENABLE (1 << 31) -/* - * ETQF filter list: one static filter per filter consumer. This is - * to avoid filter collisions later. Add new filters - * here!! - * - * Current filters: - * EAPOL 802.1x (0x888e): Filter 0 - */ -#define E1000_ETQF_FILTER_EAPOL 0 - -#define E1000_FTQF_VF_BP 0x00008000 -#define E1000_FTQF_1588_TIME_STAMP 0x08000000 -#define E1000_FTQF_MASK 0xF0000000 -#define E1000_FTQF_MASK_PROTO_BP 0x10000000 -#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000 -#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000 -#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000 - -#define E1000_NVM_APME_82575 0x0400 -#define MAX_NUM_VFS 8 - -#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */ -#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */ -#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ -#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 -#define E1000_DTXSWC_LLE_SHIFT 16 -#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ - -/* Easy defines for setting default pool, would normally be left a zero */ -#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 -#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) - -/* Other useful VMD_CTL register defines */ -#define E1000_VT_CTL_IGNORE_MAC (1 << 28) -#define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29) -#define E1000_VT_CTL_VM_REPL_EN (1 << 30) - -/* Per VM Offload register setup */ -#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */ -#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ -#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */ -#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ -#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */ -#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */ -#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ -#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ -#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ -#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */ - -#define E1000_VLVF_ARRAY_SIZE 32 -#define E1000_VLVF_VLANID_MASK 0x00000FFF -#define E1000_VLVF_POOLSEL_SHIFT 12 -#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT) -#define E1000_VLVF_LVLAN 0x00100000 -#define E1000_VLVF_VLANID_ENABLE 0x80000000 - -#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ - -#define E1000_IOVCTL 0x05BBC -#define E1000_IOVCTL_REUSE_VFQ 0x00000001 - -#define E1000_RPLOLR_STRVLAN 0x40000000 -#define E1000_RPLOLR_STRCRC 0x80000000 - -#define E1000_DTXCTL_8023LL 0x0004 -#define E1000_DTXCTL_VLAN_ADDED 0x0008 -#define E1000_DTXCTL_OOS_ENABLE 0x0010 -#define E1000_DTXCTL_MDP_EN 0x0020 -#define E1000_DTXCTL_SPOOF_INT 0x0040 - -#define ALL_QUEUES 0xFFFF - -/* RX packet buffer size defines */ -#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F -void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable); -void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable); - -#endif /* _IGB_82575_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_api.c b/roms/ipxe/src/drivers/net/igb/igb_api.c deleted file mode 100644 index eda6bc018..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_api.c +++ /dev/null @@ -1,1108 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -/** - * igb_init_mac_params - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the MAC - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 igb_init_mac_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->mac.ops.init_params) { - ret_val = hw->mac.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("MAC Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("mac.init_mac_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -/** - * igb_init_nvm_params - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the NVM - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 igb_init_nvm_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->nvm.ops.init_params) { - ret_val = hw->nvm.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("NVM Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("nvm.init_nvm_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -/** - * igb_init_phy_params - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the PHY - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 igb_init_phy_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->phy.ops.init_params) { - ret_val = hw->phy.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("PHY Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("phy.init_phy_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} - -#if 0 -/** - * igb_init_mbx_params - Initialize mailbox function pointers - * @hw: pointer to the HW structure - * - * This function initializes the function pointers for the PHY - * set of functions. Called by drivers or by e1000_setup_init_funcs. - **/ -s32 igb_init_mbx_params(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - if (hw->mbx.ops.init_params) { - ret_val = hw->mbx.ops.init_params(hw); - if (ret_val) { - DEBUGOUT("Mailbox Initialization Error\n"); - goto out; - } - } else { - DEBUGOUT("mbx.init_mbx_params was NULL\n"); - ret_val = -E1000_ERR_CONFIG; - } - -out: - return ret_val; -} -#endif - -/** - * igb_set_mac_type - Sets MAC type - * @hw: pointer to the HW structure - * - * This function sets the mac type of the adapter based on the - * device ID stored in the hw structure. - * MUST BE FIRST FUNCTION CALLED (explicitly or through - * igb_setup_init_funcs()). - **/ -s32 igb_set_mac_type(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_set_mac_type"); - - switch (hw->device_id) { - case E1000_DEV_ID_82575EB_COPPER: - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82575GB_QUAD_COPPER: - mac->type = e1000_82575; - break; - case E1000_DEV_ID_82576: - case E1000_DEV_ID_82576_FIBER: - case E1000_DEV_ID_82576_SERDES: - case E1000_DEV_ID_82576_QUAD_COPPER: - case E1000_DEV_ID_82576_NS: - case E1000_DEV_ID_82576_NS_SERDES: - case E1000_DEV_ID_82576_SERDES_QUAD: - mac->type = e1000_82576; - break; - default: - /* Should never have loaded on this device */ - ret_val = -E1000_ERR_MAC_INIT; - break; - } - - return ret_val; -} - -/** - * igb_setup_init_funcs - Initializes function pointers - * @hw: pointer to the HW structure - * @init_device: true will initialize the rest of the function pointers - * getting the device ready for use. false will only set - * MAC type and the function pointers for the other init - * functions. Passing false will not generate any hardware - * reads or writes. - * - * This function must be called by a driver in order to use the rest - * of the 'shared' code files. Called by drivers only. - **/ -s32 igb_setup_init_funcs(struct e1000_hw *hw, bool init_device) -{ - s32 ret_val; - - /* Can't do much good without knowing the MAC type. */ - ret_val = igb_set_mac_type(hw); - if (ret_val) { - DEBUGOUT("ERROR: MAC type could not be set properly.\n"); - goto out; - } - - if (!hw->hw_addr) { - DEBUGOUT("ERROR: Registers not mapped\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Init function pointers to generic implementations. We do this first - * allowing a driver module to override it afterward. - */ - igb_init_mac_ops_generic(hw); - igb_init_nvm_ops_generic(hw); -#if 0 - igb_init_mbx_ops_generic(hw); -#endif - /* - * Set up the init function pointers. These are functions within the - * adapter family file that sets up function pointers for the rest of - * the functions in that family. - */ - switch (hw->mac.type) { - case e1000_82575: - case e1000_82576: - igb_init_function_pointers_82575(hw); - break; - default: - DEBUGOUT("Hardware not supported\n"); - ret_val = -E1000_ERR_CONFIG; - break; - } - - /* - * Initialize the rest of the function pointers. These require some - * register reads/writes in some cases. - */ - if (!(ret_val) && init_device) { - ret_val = igb_init_mac_params(hw); - if (ret_val) - goto out; - - ret_val = igb_init_nvm_params(hw); - if (ret_val) - goto out; - - ret_val = igb_init_phy_params(hw); - if (ret_val) - goto out; -#if 0 - ret_val = igb_init_mbx_params(hw); - if (ret_val) - goto out; -#endif - } - -out: - return ret_val; -} - -/** - * igb_get_bus_info - Obtain bus information for adapter - * @hw: pointer to the HW structure - * - * This will obtain information about the HW bus for which the - * adapter is attached and stores it in the hw structure. This is a - * function pointer entry point called by drivers. - **/ -s32 igb_get_bus_info(struct e1000_hw *hw) -{ - if (hw->mac.ops.get_bus_info) - return hw->mac.ops.get_bus_info(hw); - - return E1000_SUCCESS; -} - -/** - * igb_clear_vfta - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * This clears the VLAN filter table on the adapter. This is a function - * pointer entry point called by drivers. - **/ -void igb_clear_vfta(struct e1000_hw *hw) -{ - if (hw->mac.ops.clear_vfta) - hw->mac.ops.clear_vfta(hw); -} - -/** - * igb_write_vfta - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: the 32-bit offset in which to write the value to. - * @value: the 32-bit value to write at location offset. - * - * This writes a 32-bit value to a 32-bit offset in the VLAN filter - * table. This is a function pointer entry point called by drivers. - **/ -void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) -{ - if (hw->mac.ops.write_vfta) - hw->mac.ops.write_vfta(hw, offset, value); -} - -/** - * igb_update_mc_addr_list - 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 igb_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count) -{ - if (hw->mac.ops.update_mc_addr_list) - hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, - mc_addr_count); -} - -/** - * igb_force_mac_fc - Force MAC flow control - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Currently no func pointer exists - * and all implementations are handled in the generic version of this - * function. - **/ -s32 igb_force_mac_fc(struct e1000_hw *hw) -{ - return igb_force_mac_fc_generic(hw); -} - -/** - * igb_check_for_link - Check/Store link connection - * @hw: pointer to the HW structure - * - * This checks the link condition of the adapter and stores the - * results in the hw->mac structure. This is a function pointer entry - * point called by drivers. - **/ -s32 igb_check_for_link(struct e1000_hw *hw) -{ - if (hw->mac.ops.check_for_link) - return hw->mac.ops.check_for_link(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_check_mng_mode - Check management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has manageability enabled. - * This is a function pointer entry point called by drivers. - **/ -bool igb_check_mng_mode(struct e1000_hw *hw) -{ - if (hw->mac.ops.check_mng_mode) - return hw->mac.ops.check_mng_mode(hw); - - return false; -} - -#if 0 -/** - * igb_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 igb_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) -{ - return igb_mng_write_dhcp_info_generic(hw, buffer, length); -} -#endif - -/** - * igb_reset_hw - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. This is a function pointer - * entry point called by drivers. - **/ -s32 igb_reset_hw(struct e1000_hw *hw) -{ - if (hw->mac.ops.reset_hw) - return hw->mac.ops.reset_hw(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_init_hw - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. This is a function - * pointer entry point called by drivers. - **/ -s32 igb_init_hw(struct e1000_hw *hw) -{ - if (hw->mac.ops.init_hw) - return hw->mac.ops.init_hw(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_setup_link - Configures link and flow control - * @hw: pointer to the HW structure - * - * This configures link and flow control settings for the adapter. This - * is a function pointer entry point called by drivers. While modules can - * also call this, they probably call their own version of this function. - **/ -s32 igb_setup_link(struct e1000_hw *hw) -{ - if (hw->mac.ops.setup_link) - return hw->mac.ops.setup_link(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_get_speed_and_duplex - Returns current speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to a 16-bit value to store the speed - * @duplex: pointer to a 16-bit value to store the duplex. - * - * This returns the speed and duplex of the adapter in the two 'out' - * variables passed in. This is a function pointer entry point called - * by drivers. - **/ -s32 igb_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) -{ - if (hw->mac.ops.get_link_up_info) - return hw->mac.ops.get_link_up_info(hw, speed, duplex); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_setup_led - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. This is a function pointer entry - * point called by drivers. - **/ -s32 igb_setup_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.setup_led) - return hw->mac.ops.setup_led(hw); - - return E1000_SUCCESS; -} - -/** - * igb_cleanup_led - Restores SW controllable LED - * @hw: pointer to the HW structure - * - * This restores the SW controllable LED to the value saved off by - * e1000_setup_led. This is a function pointer entry point called by drivers. - **/ -s32 igb_cleanup_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.cleanup_led) - return hw->mac.ops.cleanup_led(hw); - - return E1000_SUCCESS; -} - -/** - * igb_blink_led - Blink SW controllable LED - * @hw: pointer to the HW structure - * - * This starts the adapter LED blinking. Request the LED to be setup first - * and cleaned up after. This is a function pointer entry point called by - * drivers. - **/ -s32 igb_blink_led(struct e1000_hw *hw) -{ - if (hw->mac.ops.blink_led) - return hw->mac.ops.blink_led(hw); - - return E1000_SUCCESS; -} - -/** - * igb_id_led_init - store LED configurations in SW - * @hw: pointer to the HW structure - * - * Initializes the LED config in SW. This is a function pointer entry point - * called by drivers. - **/ -s32 igb_id_led_init(struct e1000_hw *hw) -{ - if (hw->mac.ops.id_led_init) - return hw->mac.ops.id_led_init(hw); - - return E1000_SUCCESS; -} - -/** - * igb_led_on - Turn on SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED on. This is a function pointer entry point - * called by drivers. - **/ -s32 igb_led_on(struct e1000_hw *hw) -{ - if (hw->mac.ops.led_on) - return hw->mac.ops.led_on(hw); - - return E1000_SUCCESS; -} - -/** - * igb_led_off - Turn off SW controllable LED - * @hw: pointer to the HW structure - * - * Turns the SW defined LED off. This is a function pointer entry point - * called by drivers. - **/ -s32 igb_led_off(struct e1000_hw *hw) -{ - if (hw->mac.ops.led_off) - return hw->mac.ops.led_off(hw); - - return E1000_SUCCESS; -} - -/** - * igb_reset_adaptive - Reset adaptive IFS - * @hw: pointer to the HW structure - * - * Resets the adaptive IFS. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -void igb_reset_adaptive(struct e1000_hw *hw) -{ - igb_reset_adaptive_generic(hw); -} - -/** - * igb_update_adaptive - Update adaptive IFS - * @hw: pointer to the HW structure - * - * Updates adapter IFS. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -void igb_update_adaptive(struct e1000_hw *hw) -{ - igb_update_adaptive_generic(hw); -} - -/** - * igb_disable_pcie_master - Disable PCI-Express master access - * @hw: pointer to the HW structure - * - * Disables PCI-Express master access and verifies there are no pending - * requests. Currently no func pointer exists and all implementations are - * handled in the generic version of this function. - **/ -s32 igb_disable_pcie_master(struct e1000_hw *hw) -{ - return igb_disable_pcie_master_generic(hw); -} - -/** - * igb_config_collision_dist - Configure collision distance - * @hw: pointer to the HW structure - * - * Configures the collision distance to the default value and is used - * during link setup. - **/ -void igb_config_collision_dist(struct e1000_hw *hw) -{ - if (hw->mac.ops.config_collision_dist) - hw->mac.ops.config_collision_dist(hw); -} - -/** - * igb_rar_set - Sets a receive address register - * @hw: pointer to the HW structure - * @addr: address to set the RAR to - * @index: the RAR to set - * - * Sets a Receive Address Register (RAR) to the specified address. - **/ -void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) -{ - if (hw->mac.ops.rar_set) - hw->mac.ops.rar_set(hw, addr, index); -} - -/** - * igb_validate_mdi_setting - Ensures valid MDI/MDIX SW state - * @hw: pointer to the HW structure - * - * Ensures that the MDI/MDIX SW state is valid. - **/ -s32 igb_validate_mdi_setting(struct e1000_hw *hw) -{ - if (hw->mac.ops.validate_mdi_setting) - return hw->mac.ops.validate_mdi_setting(hw); - - return E1000_SUCCESS; -} - -/** - * igb_mta_set - Sets multicast table bit - * @hw: pointer to the HW structure - * @hash_value: Multicast hash value. - * - * This sets the bit in the multicast table corresponding to the - * hash value. This is a function pointer entry point called by drivers. - **/ -void igb_mta_set(struct e1000_hw *hw, u32 hash_value) -{ - if (hw->mac.ops.mta_set) - hw->mac.ops.mta_set(hw, hash_value); -} - -/** - * igb_hash_mc_addr - Determines address location in multicast table - * @hw: pointer to the HW structure - * @mc_addr: Multicast address to hash. - * - * This hashes an address to determine its location in the multicast - * table. Currently no func pointer exists and all implementations - * are handled in the generic version of this function. - **/ -u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - return igb_hash_mc_addr_generic(hw, mc_addr); -} - -/** - * igb_enable_tx_pkt_filtering - Enable packet filtering on TX - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -#if 0 -bool igb_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - return igb_enable_tx_pkt_filtering_generic(hw); -} -#endif - -/** - * igb_mng_host_if_write - Writes to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -s32 igb_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length, - u16 offset, u8 *sum) -{ - if (hw->mac.ops.mng_host_if_write) - return hw->mac.ops.mng_host_if_write(hw, buffer, length, - offset, sum); - - return E1000_NOT_IMPLEMENTED; -} - -/** - * igb_mng_write_cmd_header - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -s32 igb_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - if (hw->mac.ops.mng_write_cmd_header) - return hw->mac.ops.mng_write_cmd_header(hw, hdr); - - return E1000_NOT_IMPLEMENTED; -} - -/** - * igb_mng_enable_host_if - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -s32 igb_mng_enable_host_if(struct e1000_hw * hw) -{ - if (hw->mac.ops.mng_enable_host_if) - return hw->mac.ops.mng_enable_host_if(hw); - - return E1000_NOT_IMPLEMENTED; -} - -/** - * igb_wait_autoneg - Waits for autonegotiation completion - * @hw: pointer to the HW structure - * - * Waits for autoneg to complete. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -s32 igb_wait_autoneg(struct e1000_hw *hw) -{ - if (hw->mac.ops.wait_autoneg) - return hw->mac.ops.wait_autoneg(hw); - - return E1000_SUCCESS; -} - -/** - * igb_check_reset_block - Verifies PHY can be reset - * @hw: pointer to the HW structure - * - * Checks if the PHY is in a state that can be reset or if manageability - * has it tied up. This is a function pointer entry point called by drivers. - **/ -s32 igb_check_reset_block(struct e1000_hw *hw) -{ - if (hw->phy.ops.check_reset_block) - return hw->phy.ops.check_reset_block(hw); - - return E1000_SUCCESS; -} - -/** - * igb_read_phy_reg - Reads PHY register - * @hw: pointer to the HW structure - * @offset: the register to read - * @data: the buffer to store the 16-bit read. - * - * Reads the PHY register and returns the value in data. - * This is a function pointer entry point called by drivers. - **/ -s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - if (hw->phy.ops.read_reg) - return hw->phy.ops.read_reg(hw, offset, data); - - return E1000_SUCCESS; -} - -/** - * igb_write_phy_reg - Writes PHY register - * @hw: pointer to the HW structure - * @offset: the register to write - * @data: the value to write. - * - * Writes the PHY register at offset with the value in data. - * This is a function pointer entry point called by drivers. - **/ -s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - if (hw->phy.ops.write_reg) - return hw->phy.ops.write_reg(hw, offset, data); - - return E1000_SUCCESS; -} - -/** - * igb_release_phy - Generic release PHY - * @hw: pointer to the HW structure - * - * Return if silicon family does not require a semaphore when accessing the - * PHY. - **/ -void igb_release_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.release) - hw->phy.ops.release(hw); -} - -/** - * igb_acquire_phy - Generic acquire PHY - * @hw: pointer to the HW structure - * - * Return success if silicon family does not require a semaphore when - * accessing the PHY. - **/ -s32 igb_acquire_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.acquire) - return hw->phy.ops.acquire(hw); - - return E1000_SUCCESS; -} - -/** - * igb_read_kmrn_reg - Reads register using Kumeran interface - * @hw: pointer to the HW structure - * @offset: the register to read - * @data: the location to store the 16-bit value read. - * - * Reads a register out of the Kumeran interface. Currently no func pointer - * exists and all implementations are handled in the generic version of - * this function. - **/ -s32 igb_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return igb_read_kmrn_reg_generic(hw, offset, data); -} - -/** - * igb_write_kmrn_reg - Writes register using Kumeran interface - * @hw: pointer to the HW structure - * @offset: the register to write - * @data: the value to write. - * - * Writes a register to the Kumeran interface. Currently no func pointer - * exists and all implementations are handled in the generic version of - * this function. - **/ -s32 igb_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - return igb_write_kmrn_reg_generic(hw, offset, data); -} - -#if 0 -/** - * igb_get_cable_length - Retrieves cable length estimation - * @hw: pointer to the HW structure - * - * This function estimates the cable length and stores them in - * hw->phy.min_length and hw->phy.max_length. This is a function pointer - * entry point called by drivers. - **/ -s32 igb_get_cable_length(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_cable_length) - return hw->phy.ops.get_cable_length(hw); - - return E1000_SUCCESS; -} -#endif - -/** - * igb_get_phy_info - Retrieves PHY information from registers - * @hw: pointer to the HW structure - * - * This function gets some information from various PHY registers and - * populates hw->phy values with it. This is a function pointer entry - * point called by drivers. - **/ -s32 igb_get_phy_info(struct e1000_hw *hw) -{ - if (hw->phy.ops.get_info) - return hw->phy.ops.get_info(hw); - - return E1000_SUCCESS; -} - -/** - * igb_phy_hw_reset - Hard PHY reset - * @hw: pointer to the HW structure - * - * Performs a hard PHY reset. This is a function pointer entry point called - * by drivers. - **/ -s32 igb_phy_hw_reset(struct e1000_hw *hw) -{ - if (hw->phy.ops.reset) - return hw->phy.ops.reset(hw); - - return E1000_SUCCESS; -} - -/** - * igb_phy_commit - Soft PHY reset - * @hw: pointer to the HW structure - * - * Performs a soft PHY reset on those that apply. This is a function pointer - * entry point called by drivers. - **/ -s32 igb_phy_commit(struct e1000_hw *hw) -{ - if (hw->phy.ops.commit) - return hw->phy.ops.commit(hw); - - return E1000_SUCCESS; -} - -/** - * igb_set_d0_lplu_state - Sets low power link up state for D0 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D0 - * and SmartSpeed is disabled when active is true, else clear lplu for D0 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. This is a function pointer entry point called by drivers. - **/ -s32 igb_set_d0_lplu_state(struct e1000_hw *hw, bool active) -{ - if (hw->phy.ops.set_d0_lplu_state) - return hw->phy.ops.set_d0_lplu_state(hw, active); - - return E1000_SUCCESS; -} - -/** - * igb_set_d3_lplu_state - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. This is a function pointer entry point called by drivers. - **/ -s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - if (hw->phy.ops.set_d3_lplu_state) - return hw->phy.ops.set_d3_lplu_state(hw, active); - - return E1000_SUCCESS; -} - -/** - * igb_read_mac_addr - Reads MAC address - * @hw: pointer to the HW structure - * - * Reads the MAC address out of the adapter and stores it in the HW structure. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -s32 igb_read_mac_addr(struct e1000_hw *hw) -{ - if (hw->mac.ops.read_mac_addr) - return hw->mac.ops.read_mac_addr(hw); - - return igb_read_mac_addr_generic(hw); -} - -/** - * igb_read_pba_num - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - * Currently no func pointer exists and all implementations are handled in the - * generic version of this function. - **/ -s32 igb_read_pba_num(struct e1000_hw *hw, u32 *pba_num) -{ - return igb_read_pba_num_generic(hw, pba_num); -} - -/** - * igb_validate_nvm_checksum - Verifies NVM (EEPROM) checksum - * @hw: pointer to the HW structure - * - * Validates the NVM checksum is correct. This is a function pointer entry - * point called by drivers. - **/ -s32 igb_validate_nvm_checksum(struct e1000_hw *hw) -{ - if (hw->nvm.ops.validate) - return hw->nvm.ops.validate(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_update_nvm_checksum - Updates NVM (EEPROM) checksum - * @hw: pointer to the HW structure - * - * Updates the NVM checksum. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. - **/ -s32 igb_update_nvm_checksum(struct e1000_hw *hw) -{ - if (hw->nvm.ops.update) - return hw->nvm.ops.update(hw); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_reload_nvm - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -void igb_reload_nvm(struct e1000_hw *hw) -{ - if (hw->nvm.ops.reload) - hw->nvm.ops.reload(hw); -} - -/** - * igb_read_nvm - Reads NVM (EEPROM) - * @hw: pointer to the HW structure - * @offset: the word offset to read - * @words: number of 16-bit words to read - * @data: pointer to the properly sized buffer for the data. - * - * Reads 16-bit chunks of data from the NVM (EEPROM). This is a function - * pointer entry point called by drivers. - **/ -s32 igb_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - if (hw->nvm.ops.read) - return hw->nvm.ops.read(hw, offset, words, data); - - return -E1000_ERR_CONFIG; -} - -/** - * igb_write_nvm - Writes to NVM (EEPROM) - * @hw: pointer to the HW structure - * @offset: the word offset to read - * @words: number of 16-bit words to write - * @data: pointer to the properly sized buffer for the data. - * - * Writes 16-bit chunks of data to the NVM (EEPROM). This is a function - * pointer entry point called by drivers. - **/ -s32 igb_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - if (hw->nvm.ops.write) - return hw->nvm.ops.write(hw, offset, words, data); - - return E1000_SUCCESS; -} - -/** - * igb_write_8bit_ctrl_reg - Writes 8bit Control register - * @hw: pointer to the HW structure - * @reg: 32bit register offset - * @offset: the register to write - * @data: the value to write. - * - * Writes the PHY register at offset with the value in data. - * This is a function pointer entry point called by drivers. - **/ -s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, - u8 data) -{ - return igb_write_8bit_ctrl_reg_generic(hw, reg, offset, data); -} - -/** - * igb_power_up_phy - Restores link in case of PHY power down - * @hw: pointer to the HW structure - * - * The phy may be powered down to save power, to turn off link when the - * driver is unloaded, or wake on lan is not enabled (among others). - **/ -void igb_power_up_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.power_up) - hw->phy.ops.power_up(hw); - - igb_setup_link(hw); -} - -/** - * igb_power_down_phy - Power down PHY - * @hw: pointer to the HW structure - * - * The phy may be powered down to save power, to turn off link when the - * driver is unloaded, or wake on lan is not enabled (among others). - **/ -void igb_power_down_phy(struct e1000_hw *hw) -{ - if (hw->phy.ops.power_down) - hw->phy.ops.power_down(hw); -} - -/** - * igb_shutdown_fiber_serdes_link - Remove link during power down - * @hw: pointer to the HW structure - * - * Shutdown the optics and PCS on driver unload. - **/ -void igb_shutdown_fiber_serdes_link(struct e1000_hw *hw) -{ - if (hw->mac.ops.shutdown_serdes) - hw->mac.ops.shutdown_serdes(hw); -} - diff --git a/roms/ipxe/src/drivers/net/igb/igb_api.h b/roms/ipxe/src/drivers/net/igb/igb_api.h deleted file mode 100644 index 2d97fecc2..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_api.h +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_API_H_ -#define _IGB_API_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "igb_hw.h" - -extern void igb_init_function_pointers_82575(struct e1000_hw *hw) __attribute__((weak)); -extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw) __attribute__((weak)); -extern void igb_init_function_pointers_vf(struct e1000_hw *hw) __attribute__((weak)); -extern void igb_shutdown_fiber_serdes_link(struct e1000_hw *hw) __attribute__((weak)); - -s32 igb_set_mac_type(struct e1000_hw *hw); -s32 igb_setup_init_funcs(struct e1000_hw *hw, bool init_device); -s32 igb_init_mac_params(struct e1000_hw *hw); -s32 igb_init_nvm_params(struct e1000_hw *hw); -s32 igb_init_phy_params(struct e1000_hw *hw); -s32 igb_init_mbx_params(struct e1000_hw *hw); -s32 igb_get_bus_info(struct e1000_hw *hw); -void igb_clear_vfta(struct e1000_hw *hw); -void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); -s32 igb_force_mac_fc(struct e1000_hw *hw); -s32 igb_check_for_link(struct e1000_hw *hw); -s32 igb_reset_hw(struct e1000_hw *hw); -s32 igb_init_hw(struct e1000_hw *hw); -s32 igb_setup_link(struct e1000_hw *hw); -s32 igb_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 igb_disable_pcie_master(struct e1000_hw *hw); -void igb_config_collision_dist(struct e1000_hw *hw); -void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); -void igb_mta_set(struct e1000_hw *hw, u32 hash_value); -u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); -void igb_update_mc_addr_list(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 igb_setup_led(struct e1000_hw *hw); -s32 igb_cleanup_led(struct e1000_hw *hw); -s32 igb_check_reset_block(struct e1000_hw *hw); -s32 igb_blink_led(struct e1000_hw *hw); -s32 igb_led_on(struct e1000_hw *hw); -s32 igb_led_off(struct e1000_hw *hw); -s32 igb_id_led_init(struct e1000_hw *hw); -void igb_reset_adaptive(struct e1000_hw *hw); -void igb_update_adaptive(struct e1000_hw *hw); -#if 0 -s32 igb_get_cable_length(struct e1000_hw *hw); -#endif -s32 igb_validate_mdi_setting(struct e1000_hw *hw); -s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, - u32 offset, u8 data); -s32 igb_get_phy_info(struct e1000_hw *hw); -void igb_release_phy(struct e1000_hw *hw); -s32 igb_acquire_phy(struct e1000_hw *hw); -s32 igb_phy_hw_reset(struct e1000_hw *hw); -s32 igb_phy_commit(struct e1000_hw *hw); -void igb_power_up_phy(struct e1000_hw *hw); -void igb_power_down_phy(struct e1000_hw *hw); -s32 igb_read_mac_addr(struct e1000_hw *hw); -s32 igb_read_pba_num(struct e1000_hw *hw, u32 *part_num); -void igb_reload_nvm(struct e1000_hw *hw); -s32 igb_update_nvm_checksum(struct e1000_hw *hw); -s32 igb_validate_nvm_checksum(struct e1000_hw *hw); -s32 igb_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 igb_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 igb_wait_autoneg(struct e1000_hw *hw); -s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active); -s32 igb_set_d0_lplu_state(struct e1000_hw *hw, bool active); -bool igb_check_mng_mode(struct e1000_hw *hw); -bool igb_enable_tx_pkt_filtering(struct e1000_hw *hw); -s32 igb_mng_enable_host_if(struct e1000_hw *hw); -s32 igb_mng_host_if_write(struct e1000_hw *hw, - u8 *buffer, u16 length, u16 offset, u8 *sum); -s32 igb_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr); -s32 igb_mng_write_dhcp_info(struct e1000_hw * hw, - u8 *buffer, u16 length); - -/* - * TBI_ACCEPT macro definition: - * - * This macro requires: - * adapter = a pointer to struct e1000_hw - * status = the 8 bit status field of the Rx descriptor with EOP set - * error = the 8 bit error field of the Rx descriptor with EOP set - * length = the sum of all the length fields of the Rx descriptors that - * make up the current frame - * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. - * - * This macro is a conditional that should be used in the interrupt - * handler's Rx processing routine when RxErrors have been detected. - * - * Typical use: - * ... - * if (TBI_ACCEPT) { - * accept_frame = true; - * e1000_tbi_adjust_stats(adapter, MacAddress); - * frame_length--; - * } else { - * accept_frame = false; - * } - * ... - */ - -/* The carrier extension symbol, as received by the NIC. */ -#define CARRIER_EXTENSION 0x0F - -#define TBI_ACCEPT(a, status, errors, length, last_byte, min_frame_size, max_frame_size) \ - (e1000_tbi_sbp_enabled_82543(a) && \ - (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ - ((last_byte) == CARRIER_EXTENSION) && \ - (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= (max_frame_size + 1))) : \ - (((length) > min_frame_size) && \ - ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) - -#endif /* _IGB_API_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_defines.h b/roms/ipxe/src/drivers/net/igb/igb_defines.h deleted file mode 100644 index 4f58ba83d..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_defines.h +++ /dev/null @@ -1,1515 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_DEFINES_H_ -#define _IGB_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_FLX4 0x00100000 /* Flexible Filter 4 Enable */ -#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 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 */ -/* - * For 82576 to utilize Extended filter masks in addition to - * existing (filter) masks - */ -#define E1000_WUFC_EXT_FLX_FILTERS 0x00300000 /* Ext. FLX filter mask */ - -/* 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 -/* Two Extended Flexible Filters are supported (82576) */ -#define E1000_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 -#define E1000_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */ -#define E1000_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */ - -/* 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 */ -/* Physical Func Reset Done Indication */ -#define E1000_CTRL_EXT_PFRSTD 0x00004000 -#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 -#define E1000_IVAR_VALID 0x80 -#define E1000_GPIE_NSICR 0x00000001 -#define E1000_GPIE_MSIX_MODE 0x00000010 -#define E1000_GPIE_EIAME 0x40000000 -#define E1000_GPIE_PBA 0x80000000 - -/* 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_ADVD3WUC 0x00100000 /* D3 WUC */ -#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 */ - - -/* Extended Interrupt Cause Read */ -#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ -#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ -#define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ -#define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ -#define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ -#define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ -#define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ -#define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ -#define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ -#define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ -/* TCP Timer */ -#define E1000_TCPTIMER_KS 0x00000100 /* KickStart */ -#define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */ -#define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ -#define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ - -/* - * 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 - -/* Extended Interrupt Mask Set */ -#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ -#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ -#define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ -#define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ -#define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ -#define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ -#define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ -#define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ -#define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ -#define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ - -/* 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 - -/* Extended Interrupt Cause Set */ -#define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ -#define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ -#define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ -#define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ -#define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ -#define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ -#define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ -#define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ -#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ -#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ - -#define E1000_EITR_ITR_INT_MASK 0x0000FFFF - -/* 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 */ - -#define E1000_TSYNCTXCTL_VALID 0x00000001 /* tx timestamp valid */ -#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable tx timestampping */ - -#define E1000_TSYNCRXCTL_VALID 0x00000001 /* rx timestamp valid */ -#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* rx type mask */ -#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 -#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 -#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 -#define E1000_TSYNCRXCTL_TYPE_ALL 0x08 -#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A -#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable rx timestampping */ - -#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF -#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 -#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 -#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02 -#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03 -#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04 - -#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00 -#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000 -#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100 -#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200 -#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300 -#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800 -#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900 -#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00 -#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00 -#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00 -#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 - -#define E1000_TIMINCA_16NS_SHIFT 24 - -/* 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 IGP04E1000_E_PHY_ID 0x02A80391 -#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 - -/* LinkSec register fields */ -#define E1000_LSECTXCAP_SUM_MASK 0x00FF0000 -#define E1000_LSECTXCAP_SUM_SHIFT 16 -#define E1000_LSECRXCAP_SUM_MASK 0x00FF0000 -#define E1000_LSECRXCAP_SUM_SHIFT 16 - -#define E1000_LSECTXCTRL_EN_MASK 0x00000003 -#define E1000_LSECTXCTRL_DISABLE 0x0 -#define E1000_LSECTXCTRL_AUTH 0x1 -#define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2 -#define E1000_LSECTXCTRL_AISCI 0x00000020 -#define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 -#define E1000_LSECTXCTRL_RSV_MASK 0x000000D8 - -#define E1000_LSECRXCTRL_EN_MASK 0x0000000C -#define E1000_LSECRXCTRL_EN_SHIFT 2 -#define E1000_LSECRXCTRL_DISABLE 0x0 -#define E1000_LSECRXCTRL_CHECK 0x1 -#define E1000_LSECRXCTRL_STRICT 0x2 -#define E1000_LSECRXCTRL_DROP 0x3 -#define E1000_LSECRXCTRL_PLSH 0x00000040 -#define E1000_LSECRXCTRL_RP 0x00000080 -#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 - - - -#endif /* _IGB_DEFINES_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_hw.h b/roms/ipxe/src/drivers/net/igb/igb_hw.h deleted file mode 100644 index 65a04f208..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_hw.h +++ /dev/null @@ -1,697 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_HW_H_ -#define _IGB_HW_H_ - -#include "igb_osdep.h" -#include "igb_regs.h" -#include "igb_defines.h" - -struct e1000_hw; - -#define E1000_DEV_ID_82576 0x10C9 -#define E1000_DEV_ID_82576_FIBER 0x10E6 -#define E1000_DEV_ID_82576_SERDES 0x10E7 -#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 -#define E1000_DEV_ID_82576_NS 0x150A -#define E1000_DEV_ID_82576_NS_SERDES 0x1518 -#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D -#define E1000_DEV_ID_82575EB_COPPER 0x10A7 -#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 -#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 -#define E1000_REVISION_0 0 -#define E1000_REVISION_1 1 -#define E1000_REVISION_2 2 -#define E1000_REVISION_3 3 -#define E1000_REVISION_4 4 - -#define E1000_FUNC_0 0 -#define E1000_FUNC_1 1 - -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 - -enum e1000_mac_type { - e1000_undefined = 0, - e1000_82575, - e1000_82576, - e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ -}; - -enum e1000_media_type { - e1000_media_type_unknown = 0, - e1000_media_type_copper = 1, - e1000_media_type_fiber = 2, - e1000_media_type_internal_serdes = 3, - e1000_num_media_types -}; - -enum e1000_nvm_type { - e1000_nvm_unknown = 0, - e1000_nvm_none, - e1000_nvm_eeprom_spi, - e1000_nvm_flash_hw, - e1000_nvm_flash_sw -}; - -enum e1000_nvm_override { - e1000_nvm_override_none = 0, - e1000_nvm_override_spi_small, - e1000_nvm_override_spi_large, -}; - -enum e1000_phy_type { - e1000_phy_unknown = 0, - e1000_phy_none, - e1000_phy_m88, - e1000_phy_igp, - e1000_phy_igp_2, - e1000_phy_gg82563, - e1000_phy_igp_3, - e1000_phy_ife, - e1000_phy_vf, -}; - -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 -}; - -enum e1000_1000t_rx_status { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -}; - -enum e1000_rev_polarity { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -}; - -enum e1000_fc_mode { - e1000_fc_none = 0, - e1000_fc_rx_pause, - e1000_fc_tx_pause, - e1000_fc_full, - e1000_fc_default = 0xFF -}; - -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - -enum e1000_serdes_link_state { - e1000_serdes_link_down = 0, - e1000_serdes_link_autoneg_progress, - e1000_serdes_link_autoneg_complete, - e1000_serdes_link_forced_up -}; - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorc; - u64 gotc; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 tor; - u64 tot; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; - u64 cbtmpc; - u64 htdpmc; - u64 cbrdpc; - u64 cbrmpc; - u64 rpthc; - u64 hgptc; - u64 htcbdpc; - u64 hgorc; - u64 hgotc; - u64 lenerrs; - u64 scvpc; - u64 hrmpc; - u64 doosync; -}; - - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; - -/* Host Interface "Rev 1" */ -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; - u8 checksum; -}; - -#define E1000_HI_MAX_DATA_LENGTH 252 -struct e1000_host_command_info { - struct e1000_host_command_header command_header; - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -}; - -/* Host Interface "Rev 2" */ -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -}; - -#include "igb_mac.h" -#include "igb_phy.h" -#include "igb_nvm.h" -#include "igb_manage.h" - -struct e1000_mac_operations { - /* Function pointers for the MAC. */ - s32 (*init_params)(struct e1000_hw *); - s32 (*id_led_init)(struct e1000_hw *); - s32 (*blink_led)(struct e1000_hw *); - s32 (*check_for_link)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *hw); - s32 (*cleanup_led)(struct e1000_hw *); - void (*clear_hw_cntrs)(struct e1000_hw *); - void (*clear_vfta)(struct e1000_hw *); - s32 (*get_bus_info)(struct e1000_hw *); - void (*set_lan_id)(struct e1000_hw *); - s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); - s32 (*led_on)(struct e1000_hw *); - s32 (*led_off)(struct e1000_hw *); - void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); - s32 (*reset_hw)(struct e1000_hw *); - s32 (*init_hw)(struct e1000_hw *); - void (*shutdown_serdes)(struct e1000_hw *); - s32 (*setup_link)(struct e1000_hw *); - s32 (*setup_physical_interface)(struct e1000_hw *); - s32 (*setup_led)(struct e1000_hw *); - void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*mta_set)(struct e1000_hw *, u32); - void (*config_collision_dist)(struct e1000_hw *); - void (*rar_set)(struct e1000_hw *, u8*, u32); - s32 (*read_mac_addr)(struct e1000_hw *); - s32 (*validate_mdi_setting)(struct e1000_hw *); - s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); - s32 (*mng_write_cmd_header)(struct e1000_hw *hw, - struct e1000_host_mng_command_header*); - s32 (*mng_enable_host_if)(struct e1000_hw *); - s32 (*wait_autoneg)(struct e1000_hw *); -}; - -struct e1000_phy_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*check_polarity)(struct e1000_hw *); - s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit)(struct e1000_hw *); -#if 0 - s32 (*force_speed_duplex)(struct e1000_hw *); -#endif - s32 (*get_cfg_done)(struct e1000_hw *hw); -#if 0 - s32 (*get_cable_length)(struct e1000_hw *); -#endif - s32 (*get_info)(struct e1000_hw *); - s32 (*read_reg)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); - void (*release)(struct e1000_hw *); - s32 (*reset)(struct e1000_hw *); - s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); - s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_reg)(struct e1000_hw *, u32, u16); - s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); - void (*power_up)(struct e1000_hw *); - void (*power_down)(struct e1000_hw *); -}; - -struct e1000_nvm_operations { - s32 (*init_params)(struct e1000_hw *); - s32 (*acquire)(struct e1000_hw *); - s32 (*read)(struct e1000_hw *, u16, u16, u16 *); - void (*release)(struct e1000_hw *); - void (*reload)(struct e1000_hw *); - s32 (*update)(struct e1000_hw *); - s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate)(struct e1000_hw *); - s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -}; - -struct e1000_mac_info { - struct e1000_mac_operations ops; - u8 addr[6]; - u8 perm_addr[6]; - - enum e1000_mac_type type; - - u32 collision_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - u32 mc_filter_type; - u32 tx_packet_delta; - u32 txcw; - - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; - u16 mta_reg_count; - u16 uta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ - #define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; - u16 rar_entry_count; - - u8 forced_speed_duplex; - - bool adaptive_ifs; - bool arc_subsystem_valid; - bool asf_firmware_present; - bool autoneg; - bool autoneg_failed; - bool get_link_status; - bool in_ifs_mode; - enum e1000_serdes_link_state serdes_link_state; - bool serdes_has_link; - bool tx_pkt_filtering; -}; - -struct e1000_phy_info { - struct e1000_phy_operations ops; - enum e1000_phy_type type; - - enum e1000_1000t_rx_status local_rx; - enum e1000_1000t_rx_status remote_rx; - enum e1000_ms_type ms_type; - enum e1000_ms_type original_ms_type; - enum e1000_rev_polarity cable_polarity; - enum e1000_smart_speed smart_speed; - - u32 addr; - u32 id; - u32 reset_delay_us; /* in usec */ - u32 revision; - - enum e1000_media_type media_type; - - u16 autoneg_advertised; - u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - - u8 mdix; - - bool disable_polarity_correction; - bool is_mdix; - bool polarity_correction; - bool reset_disable; - bool speed_downgraded; - bool autoneg_wait_to_complete; -}; - -struct e1000_nvm_info { - struct e1000_nvm_operations ops; - enum e1000_nvm_type type; - enum e1000_nvm_override override; - - u32 flash_bank_size; - u32 flash_base_addr; - - u16 word_size; - u16 delay_usec; - u16 address_bits; - u16 opcode_bits; - u16 page_size; -}; - -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_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* FC mode in effect */ - enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ -}; - -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_82575 { - bool sgmii_active; - bool global_device_reset; -}; - -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_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; - struct e1000_mbx_info mbx; - struct e1000_host_mng_dhcp_cookie mng_cookie; - - union { - struct e1000_dev_spec_82575 _82575; - 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; -}; - -#include "igb_82575.h" - -/* These functions must be implemented by drivers */ -s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); -s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); - -#endif /* _IGB_HW_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_mac.c b/roms/ipxe/src/drivers/net/igb/igb_mac.c deleted file mode 100644 index 237c6c752..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_mac.c +++ /dev/null @@ -1,1991 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -static s32 igb_set_default_fc_generic(struct e1000_hw *hw); -static s32 igb_commit_fc_settings_generic(struct e1000_hw *hw); -static s32 igb_poll_fiber_serdes_link_generic(struct e1000_hw *hw); -static s32 igb_validate_mdi_setting_generic(struct e1000_hw *hw); -static void igb_set_lan_id_multi_port_pcie(struct e1000_hw *hw); - -/** - * igb_init_mac_ops_generic - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void igb_init_mac_ops_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - DEBUGFUNC("igb_init_mac_ops_generic"); - - /* General Setup */ - mac->ops.set_lan_id = igb_set_lan_id_multi_port_pcie; - mac->ops.read_mac_addr = igb_read_mac_addr_generic; - mac->ops.config_collision_dist = igb_config_collision_dist_generic; - /* LINK */ - mac->ops.wait_autoneg = igb_wait_autoneg_generic; - /* Management */ -#if 0 - mac->ops.mng_host_if_write = igb_mng_host_if_write_generic; - mac->ops.mng_write_cmd_header = igb_mng_write_cmd_header_generic; - mac->ops.mng_enable_host_if = igb_mng_enable_host_if_generic; -#endif - /* VLAN, MC, etc. */ - mac->ops.rar_set = igb_rar_set_generic; - mac->ops.validate_mdi_setting = igb_validate_mdi_setting_generic; -} - -/** - * igb_get_bus_info_pcie_generic - Get PCIe bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCIe), and PCIe function. - **/ -s32 igb_get_bus_info_pcie_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - - s32 ret_val; - u16 pcie_link_status; - - DEBUGFUNC("igb_get_bus_info_pcie_generic"); - - bus->type = e1000_bus_type_pci_express; - bus->speed = e1000_bus_speed_2500; - - ret_val = igb_read_pcie_cap_reg(hw, - PCIE_LINK_STATUS, - &pcie_link_status); - if (ret_val) - bus->width = e1000_bus_width_unknown; - else - bus->width = (enum e1000_bus_width)((pcie_link_status & - PCIE_LINK_WIDTH_MASK) >> - PCIE_LINK_WIDTH_SHIFT); - - mac->ops.set_lan_id(hw); - - return E1000_SUCCESS; -} - -/** - * igb_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices - * - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading memory-mapped registers - * and swaps the port value if requested. - **/ -static void igb_set_lan_id_multi_port_pcie(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u32 reg; - - /* - * The status register reports the correct function number - * for the device regardless of function swap state. - */ - reg = E1000_READ_REG(hw, E1000_STATUS); - bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; -} - -/** - * igb_set_lan_id_single_port - Set LAN id for a single port device - * @hw: pointer to the HW structure - * - * Sets the LAN function id to zero for a single port device. - **/ -void igb_set_lan_id_single_port(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - - bus->func = 0; -} - -/** - * igb_clear_vfta_generic - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -void igb_clear_vfta_generic(struct e1000_hw *hw) -{ - u32 offset; - - DEBUGFUNC("igb_clear_vfta_generic"); - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); - E1000_WRITE_FLUSH(hw); - } -} - -/** - * igb_write_vfta_generic - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: register offset in VLAN filter table - * @value: register value written to VLAN filter table - * - * Writes value at the given offset in the register array which stores - * the VLAN filter table. - **/ -void igb_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) -{ - DEBUGFUNC("igb_write_vfta_generic"); - - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_init_rx_addrs_generic - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setups the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void igb_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ADDR_LEN] = {0}; - - DEBUGFUNC("igb_init_rx_addrs_generic"); - - /* Setup the receive address */ - DEBUGOUT("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - -/** - * igb_check_alt_mac_addr_generic - Check for alternate MAC addr - * @hw: pointer to the HW structure - * - * Checks the nvm for an alternate MAC address. An alternate MAC address - * can be setup by pre-boot software and must be treated like a permanent - * address and must override the actual permanent MAC address. If an - * alternate MAC address is found it is programmed into RAR0, replacing - * the permanent address that was installed into RAR0 by the Si on reset. - * This function will return SUCCESS unless it encounters an error while - * reading the EEPROM. - **/ -s32 igb_check_alt_mac_addr_generic(struct e1000_hw *hw) -{ - u32 i; - s32 ret_val = E1000_SUCCESS; - u16 offset, nvm_alt_mac_addr_offset, nvm_data; - u8 alt_mac_addr[ETH_ADDR_LEN]; - - DEBUGFUNC("igb_check_alt_mac_addr_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if (nvm_alt_mac_addr_offset == 0xFFFF) { - /* There is no Alternate MAC Address */ - goto out; - } - - if (hw->bus.func == E1000_FUNC_1) - nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; - for (i = 0; i < ETH_ADDR_LEN; i += 2) { - offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - alt_mac_addr[i] = (u8)(nvm_data & 0xFF); - alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); - } - - /* if multicast bit is set, the alternate address will not be used */ - if (alt_mac_addr[0] & 0x01) { - DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); - goto out; - } - - /* - * We have a valid alternate MAC address, and we want to treat it the - * same as the normal permanent MAC address stored by the HW into the - * RAR. Do this by mapping this address into RAR0. - */ - hw->mac.ops.rar_set(hw, alt_mac_addr, 0); - -out: - return ret_val; -} - -/** - * igb_rar_set_generic - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -void igb_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - DEBUGFUNC("igb_rar_set_generic"); - - /* - * HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | - ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - /* - * Some bridges will combine consecutive 32-bit writes into - * a single burst write, which will malfunction on some parts. - * The flushes avoid this. - */ - E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); - E1000_WRITE_FLUSH(hw); - E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_mta_set_generic - Set multicast filter table address - * @hw: pointer to the HW structure - * @hash_value: determines the MTA register and bit to set - * - * The multicast table address is a register array of 32-bit registers. - * The hash_value is used to determine what register the bit is in, the - * current value is read, the new bit is OR'd in and the new value is - * written back into the register. - **/ -void igb_mta_set_generic(struct e1000_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg, mta; - - DEBUGFUNC("igb_mta_set_generic"); - /* - * The MTA is a register array of 32-bit registers. It is - * treated like an array of (32*mta_reg_count) bits. We want to - * set bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The (hw->mac.mta_reg_count - 1) serves as a - * mask to bits 31:5 of the hash value which gives us the - * register we're modifying. The hash bit within that register - * is determined by the lower 5 bits of the hash value. - */ - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); - - mta |= (1 << hash_bit); - - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_update_mc_addr_list_generic - 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 entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void igb_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - DEBUGFUNC("igb_update_mc_addr_list_generic"); - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32) i < mc_addr_count; i++) { - hash_value = igb_hash_mc_addr_generic(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ADDR_LEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_hash_mc_addr_generic - 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 - * igb_mta_set_generic() - **/ -u32 igb_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value, hash_mask; - u8 bit_shift = 0; - - DEBUGFUNC("igb_hash_mc_addr_generic"); - - /* Register count multiplied by bits per register */ - hash_mask = (hw->mac.mta_reg_count * 32) - 1; - - /* - * For a mc_filter_type of 0, 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++; - - /* - * The portion of the address that is used for the hash table - * is determined by the mc_filter_type setting. - * The algorithm is such that there is a total of 8 bits of shifting. - * The bit_shift for a mc_filter_type of 0 represents the number of - * left-shifts where the MSB of mc_addr[5] would still fall within - * the hash_mask. Case 0 does this exactly. Since there are a total - * of 8 bits of shifting, then mc_addr[4] will shift right the - * remaining number of bits. Thus 8 - bit_shift. The rest of the - * cases are a variation of this algorithm...essentially raising the - * number of bits to shift mc_addr[5] left, while still keeping the - * 8-bit shifting total. - * - * For example, given the following Destination MAC Address and an - * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), - * we can see that the bit_shift for case 0 is 4. These are the hash - * values resulting from each mc_filter_type... - * [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - * - * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 - * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 - * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 - * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 - */ - switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; - } - - hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16) mc_addr[5]) << bit_shift))); - - return hash_value; -} - -/** - * igb_clear_hw_cntrs_base_generic - Clear base hardware counters - * @hw: pointer to the HW structure - * - * Clears the base hardware counters by reading the counter registers. - **/ -void igb_clear_hw_cntrs_base_generic(struct e1000_hw *hw) -{ - DEBUGFUNC("igb_clear_hw_cntrs_base_generic"); - - E1000_READ_REG(hw, E1000_CRCERRS); - E1000_READ_REG(hw, E1000_SYMERRS); - E1000_READ_REG(hw, E1000_MPC); - E1000_READ_REG(hw, E1000_SCC); - E1000_READ_REG(hw, E1000_ECOL); - E1000_READ_REG(hw, E1000_MCC); - E1000_READ_REG(hw, E1000_LATECOL); - E1000_READ_REG(hw, E1000_COLC); - E1000_READ_REG(hw, E1000_DC); - E1000_READ_REG(hw, E1000_SEC); - E1000_READ_REG(hw, E1000_RLEC); - E1000_READ_REG(hw, E1000_XONRXC); - E1000_READ_REG(hw, E1000_XONTXC); - E1000_READ_REG(hw, E1000_XOFFRXC); - E1000_READ_REG(hw, E1000_XOFFTXC); - E1000_READ_REG(hw, E1000_FCRUC); - E1000_READ_REG(hw, E1000_GPRC); - E1000_READ_REG(hw, E1000_BPRC); - E1000_READ_REG(hw, E1000_MPRC); - E1000_READ_REG(hw, E1000_GPTC); - E1000_READ_REG(hw, E1000_GORCL); - E1000_READ_REG(hw, E1000_GORCH); - E1000_READ_REG(hw, E1000_GOTCL); - E1000_READ_REG(hw, E1000_GOTCH); - E1000_READ_REG(hw, E1000_RNBC); - E1000_READ_REG(hw, E1000_RUC); - E1000_READ_REG(hw, E1000_RFC); - E1000_READ_REG(hw, E1000_ROC); - E1000_READ_REG(hw, E1000_RJC); - E1000_READ_REG(hw, E1000_TORL); - E1000_READ_REG(hw, E1000_TORH); - E1000_READ_REG(hw, E1000_TOTL); - E1000_READ_REG(hw, E1000_TOTH); - E1000_READ_REG(hw, E1000_TPR); - E1000_READ_REG(hw, E1000_TPT); - E1000_READ_REG(hw, E1000_MPTC); - E1000_READ_REG(hw, E1000_BPTC); -} - -/** - * igb_check_for_copper_link_generic - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -s32 igb_check_for_copper_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - DEBUGFUNC("igb_check_for_copper_link"); - - /* - * We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* - * First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = igb_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) - goto out; /* No link detected */ - - mac->get_link_status = false; - - /* - * Check if there was DownShift, must be checked - * immediately after link-up - */ - igb_check_downshift_generic(hw); - - /* - * If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - /* - * Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - igb_config_collision_dist_generic(hw); - - /* - * Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = igb_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - } -out: - return ret_val; -} - -/** - * igb_check_for_fiber_link_generic - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 igb_check_for_fiber_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_check_for_fiber_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - status = E1000_READ_REG(hw, E1000_STATUS); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = igb_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); - E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - -out: - return ret_val; -} - -/** - * igb_check_for_serdes_link_generic - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 igb_check_for_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_check_for_serdes_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - status = E1000_READ_REG(hw, E1000_STATUS); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - - /* - * If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; - goto out; - } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = igb_config_fc_after_link_up_generic(hw); - if (ret_val) { - DEBUGOUT("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); - E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); - E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { - /* - * If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - usec_delay(10); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - DEBUGOUT("SERDES: Link up - forced.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { - status = E1000_READ_REG(hw, E1000_STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - usec_delay(10); - rxcw = E1000_READ_REG(hw, E1000_RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - DEBUGOUT("SERDES: Link up - autoneg " - "completed sucessfully.\n"); - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - no sync.\n"); - } - } else { - mac->serdes_has_link = false; - DEBUGOUT("SERDES: Link down - autoneg failed\n"); - } - } - -out: - return ret_val; -} - -/** - * igb_setup_link_generic - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -s32 igb_setup_link_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_setup_link_generic"); - - /* - * In the case of the phy reset being blocked, we already have a link. - * We do not need to set it up again. - */ - if (hw->phy.ops.check_reset_block) - if (hw->phy.ops.check_reset_block(hw)) - goto out; - - /* - * If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = igb_set_default_fc_generic(hw); - if (ret_val) - goto out; - } - - /* - * Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - DEBUGOUT1("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); - - /* Call the necessary media_type subroutine to configure the link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - goto out; - - /* - * Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); - E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); - E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); - E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); - - E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); - - ret_val = igb_set_fc_watermarks_generic(hw); - -out: - return ret_val; -} - -/** - * igb_setup_fiber_serdes_link_generic - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. - **/ -s32 igb_setup_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_setup_fiber_serdes_link_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - igb_config_collision_dist_generic(hw); - - ret_val = igb_commit_fc_settings_generic(hw); - if (ret_val) - goto out; - - /* - * Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - DEBUGOUT("Auto-negotiation enabled\n"); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - msec_delay(1); - - /* - * For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. - */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = igb_poll_fiber_serdes_link_generic(hw); - } else { - DEBUGOUT("No signal detected\n"); - } - -out: - return ret_val; -} - -/** - * igb_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 igb_config_collision_dist_generic(struct e1000_hw *hw) -{ - u32 tctl; - - DEBUGFUNC("igb_config_collision_dist_generic"); - - tctl = E1000_READ_REG(hw, E1000_TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - E1000_WRITE_REG(hw, E1000_TCTL, tctl); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_poll_fiber_serdes_link_generic - Poll for link up - * @hw: pointer to the HW structure - * - * Polls for link up by reading the status register, if link fails to come - * up with auto-negotiation, then the link is forced if a signal is detected. - **/ -static s32 igb_poll_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 i, status; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_poll_fiber_serdes_link_generic"); - - /* - * If we have a signal (the cable is plugged in, or assumed true for - * serdes media) then poll for a "Link-Up" indication in the Device - * Status Register. Time-out if a link isn't seen in 500 milliseconds - * seconds (Auto-negotiation should complete in less than 500 - * milliseconds even if the other end is doing it in SW). - */ - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - msec_delay(10); - status = E1000_READ_REG(hw, E1000_STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == FIBER_LINK_UP_LIMIT) { - DEBUGOUT("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = 1; - /* - * AutoNeg failed to achieve a link, so we'll call - * mac->check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = hw->mac.ops.check_for_link(hw); - if (ret_val) { - DEBUGOUT("Error while checking for link\n"); - goto out; - } - mac->autoneg_failed = 0; - } else { - mac->autoneg_failed = 0; - DEBUGOUT("Valid Link Found\n"); - } - -out: - return ret_val; -} - -/** - * igb_commit_fc_settings_generic - Configure flow control - * @hw: pointer to the HW structure - * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. - **/ -static s32 igb_commit_fc_settings_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_commit_fc_settings_generic"); - - /* - * Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric RX - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - break; - } - - E1000_WRITE_REG(hw, E1000_TXCW, txcw); - mac->txcw = txcw; - -out: - return ret_val; -} - -/** - * igb_set_fc_watermarks_generic - Set flow control high/low watermarks - * @hw: pointer to the HW structure - * - * Sets the flow control high/low threshold (watermark) registers. If - * flow control XON frame transmission is enabled, then set XON frame - * transmission as well. - **/ -s32 igb_set_fc_watermarks_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u32 fcrtl = 0, fcrth = 0; - - DEBUGFUNC("igb_set_fc_watermarks_generic"); - - /* - * Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames is not enabled, then these - * registers will be set to 0. - */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* - * We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - fcrtl = hw->fc.low_water; - if (hw->fc.send_xon) - fcrtl |= E1000_FCRTL_XONE; - - fcrth = hw->fc.high_water; - } - E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); - E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); - - return ret_val; -} - -/** - * igb_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -static s32 igb_set_default_fc_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 nvm_data; - - DEBUGFUNC("igb_set_default_fc_generic"); - - /* - * Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); - - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == - NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - -out: - return ret_val; -} - -/** - * igb_force_mac_fc_generic - Force the MAC's flow control settings - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the - * device control register to reflect the adapter settings. TFCE and RFCE - * need to be explicitly set by software when a copper PHY is used because - * autonegotiation is managed by the PHY rather than the MAC. Software must - * also configure these bits when link is forced on a fiber connection. - **/ -s32 igb_force_mac_fc_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_force_mac_fc_generic"); - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - - /* - * Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and Tx flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); - - switch (hw->fc.current_mode) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - -out: - return ret_val; -} - -/** - * igb_config_fc_after_link_up_generic - Configures flow control after link - * @hw: pointer to the HW structure - * - * Checks the status of auto-negotiation after link up to ensure that the - * speed and duplex were not forced. If the link needed to be forced, then - * flow control needs to be forced also. If auto-negotiation is enabled - * and did not fail, then we configure flow control based on our link - * partner. - **/ -s32 igb_config_fc_after_link_up_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; - u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; - u16 speed, duplex; - - DEBUGFUNC("igb_config_fc_after_link_up_generic"); - - /* - * Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) - ret_val = igb_force_mac_fc_generic(hw); - } else { - if (hw->phy.media_type == e1000_media_type_copper) - ret_val = igb_force_mac_fc_generic(hw); - } - - if (ret_val) { - DEBUGOUT("Error forcing flow control settings\n"); - goto out; - } - - /* - * Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* - * Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - goto out; - - if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { - DEBUGOUT("Copper PHY and Auto Neg " - "has not completed.\n"); - goto out; - } - - /* - * The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (Address 4) and the Auto_Negotiation Base - * Page Ability Register (Address 5) to determine how - * flow control was negotiated. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg); - if (ret_val) - goto out; - ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg); - if (ret_val) - goto out; - - /* - * Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | E1000_fc_full - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = " - "RX PAUSE frames only.\r\n"); - } - } - /* - * For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); - } - /* - * For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); - } else { - /* - * Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); - } - - /* - * Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - DEBUGOUT("Error getting link speed and duplex\n"); - goto out; - } - - if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; - - /* - * Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = igb_force_mac_fc_generic(hw); - if (ret_val) { - DEBUGOUT("Error forcing flow control settings\n"); - goto out; - } - } - -out: - return ret_val; -} - -/** - * igb_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Read the status register for the current speed/duplex and store the current - * speed and duplex for copper connections. - **/ -s32 igb_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - u32 status; - - DEBUGFUNC("igb_get_speed_and_duplex_copper_generic"); - - 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; -} - -/** - * igb_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Sets the speed and duplex to gigabit full duplex (the only possible option) - * for fiber/serdes links. - **/ -s32 igb_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw __unused, - u16 *speed, u16 *duplex) -{ - DEBUGFUNC("igb_get_speed_and_duplex_fiber_serdes_generic"); - - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - - return E1000_SUCCESS; -} - -/** - * igb_get_hw_semaphore_generic - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 igb_get_hw_semaphore_generic(struct e1000_hw *hw) -{ - u32 swsm; - s32 ret_val = E1000_SUCCESS; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - DEBUGFUNC("igb_get_hw_semaphore_generic"); - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = E1000_READ_REG(hw, E1000_SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usec_delay(50); - i++; - } - - if (i == timeout) { - DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = E1000_READ_REG(hw, E1000_SWSM); - E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) - break; - - usec_delay(50); - } - - if (i == timeout) { - /* Release semaphores */ - igb_put_hw_semaphore_generic(hw); - DEBUGOUT("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_put_hw_semaphore_generic - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void igb_put_hw_semaphore_generic(struct e1000_hw *hw) -{ - u32 swsm; - - DEBUGFUNC("igb_put_hw_semaphore_generic"); - - swsm = E1000_READ_REG(hw, E1000_SWSM); - - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - - E1000_WRITE_REG(hw, E1000_SWSM, swsm); -} - -/** - * igb_get_auto_rd_done_generic - Check for auto read completion - * @hw: pointer to the HW structure - * - * Check EEPROM for Auto Read done bit. - **/ -s32 igb_get_auto_rd_done_generic(struct e1000_hw *hw) -{ - s32 i = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_get_auto_rd_done_generic"); - - while (i < AUTO_READ_DONE_TIMEOUT) { - if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) - break; - msec_delay(1); - i++; - } - - if (i == AUTO_READ_DONE_TIMEOUT) { - DEBUGOUT("Auto read by HW from NVM has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_valid_led_default_generic - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -s32 igb_valid_led_default_generic(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - DEBUGFUNC("igb_valid_led_default_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - -out: - return ret_val; -} - -/** - * e1000_id_led_init_generic - - * @hw: pointer to the HW structure - * - **/ -s32 igb_id_led_init_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 data, i, temp; - const u16 led_mask = 0x0F; - - DEBUGFUNC("igb_id_led_init_generic"); - - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - goto out; - - mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - -out: - return ret_val; -} - -#if 0 -/** - * igb_setup_led_generic - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -s32 igb_setup_led_generic(struct e1000_hw *hw) -{ - u32 ledctl; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_setup_led_generic"); - - if (hw->mac.ops.setup_led != e1000_setup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - if (hw->phy.media_type == e1000_media_type_fiber) { - ledctl = E1000_READ_REG(hw, E1000_LEDCTL); - hw->mac.ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); - } else if (hw->phy.media_type == e1000_media_type_copper) { - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); - } - -out: - return ret_val; -} - -/** - * igb_cleanup_led_generic - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -s32 igb_cleanup_led_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_cleanup_led_generic"); - - if (hw->mac.ops.cleanup_led != e1000_cleanup_led_generic) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); - -out: - return ret_val; -} - -/** - * igb_blink_led_generic - Blink LED - * @hw: pointer to the HW structure - * - * Blink the LEDs which are set to be on. - **/ -s32 igb_blink_led_generic(struct e1000_hw *hw) -{ - u32 ledctl_blink = 0; - u32 i; - - DEBUGFUNC("igb_blink_led_generic"); - - if (hw->phy.media_type == e1000_media_type_fiber) { - /* always blink LED0 for PCI-E fiber */ - ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); - } else { - /* - * set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); - } - - E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); - - return E1000_SUCCESS; -} - -/** - * igb_led_on_generic - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -s32 igb_led_on_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - DEBUGFUNC("igb_led_on_generic"); - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - break; - case e1000_media_type_copper: - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); - break; - default: - break; - } - - return E1000_SUCCESS; -} - -/** - * igb_led_off_generic - Turn LED off - * @hw: pointer to the HW structure - * - * Turn LED off. - **/ -s32 igb_led_off_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - DEBUGFUNC("igb_led_off_generic"); - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - break; - case e1000_media_type_copper: - E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); - break; - default: - break; - } - - return E1000_SUCCESS; -} -#endif - -/** - * igb_set_pcie_no_snoop_generic - Set PCI-express capabilities - * @hw: pointer to the HW structure - * @no_snoop: bitmap of snoop events - * - * Set the PCI-express register to snoop for events enabled in 'no_snoop'. - **/ -void igb_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) -{ - u32 gcr; - - DEBUGFUNC("igb_set_pcie_no_snoop_generic"); - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - if (no_snoop) { - gcr = E1000_READ_REG(hw, E1000_GCR); - gcr &= ~(PCIE_NO_SNOOP_ALL); - gcr |= no_snoop; - E1000_WRITE_REG(hw, E1000_GCR, gcr); - } -out: - return; -} - -/** - * igb_disable_pcie_master_generic - Disables PCI-express master access - * @hw: pointer to the HW structure - * - * Returns 0 (E1000_SUCCESS) if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused - * the master requests to be disabled. - * - * Disables PCI-Express master access and verifies there are no pending - * requests. - **/ -s32 igb_disable_pcie_master_generic(struct e1000_hw *hw) -{ - u32 ctrl; - s32 timeout = MASTER_DISABLE_TIMEOUT; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_disable_pcie_master_generic"); - - if (hw->bus.type != e1000_bus_type_pci_express) - goto out; - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - - while (timeout) { - if (!(E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE)) - break; - usec_delay(100); - timeout--; - } - - if (!timeout) { - DEBUGOUT("Master requests are pending.\n"); - ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_reset_adaptive_generic - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void igb_reset_adaptive_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("igb_reset_adaptive_generic"); - - if (!mac->adaptive_ifs) { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; - } - - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - E1000_WRITE_REG(hw, E1000_AIT, 0); -out: - return; -} - -/** - * igb_update_adaptive_generic - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void igb_update_adaptive_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - DEBUGFUNC("igb_update_adaptive_generic"); - - if (!mac->adaptive_ifs) { - DEBUGOUT("Not in Adaptive IFS mode!\n"); - goto out; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - E1000_WRITE_REG(hw, E1000_AIT, 0); - } - } -out: - return; -} - -/** - * igb_validate_mdi_setting_generic - Verify MDI/MDIx settings - * @hw: pointer to the HW structure - * - * Verify that when not using auto-negotiation that MDI/MDIx is correctly - * set, which is forced to MDI mode only. - **/ -static s32 igb_validate_mdi_setting_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_validate_mdi_setting_generic"); - - if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { - DEBUGOUT("Invalid MDI setting detected\n"); - hw->phy.mdix = 1; - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register - * @hw: pointer to the HW structure - * @reg: 32bit register offset such as E1000_SCTL - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes an address/data control type register. There are several of these - * and they all have the format address << 8 | data and bit 31 is polled for - * completion. - **/ -s32 igb_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, - u32 offset, u8 data) -{ - u32 i, regvalue = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_write_8bit_ctrl_reg_generic"); - - /* Set up the address and data */ - regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT); - E1000_WRITE_REG(hw, reg, regvalue); - - /* Poll the ready bit to see if the MDI read completed */ - for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { - usec_delay(5); - regvalue = E1000_READ_REG(hw, reg); - if (regvalue & E1000_GEN_CTL_READY) - break; - } - if (!(regvalue & E1000_GEN_CTL_READY)) { - DEBUGOUT1("Reg %08x did not indicate ready\n", reg); - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} diff --git a/roms/ipxe/src/drivers/net/igb/igb_mac.h b/roms/ipxe/src/drivers/net/igb/igb_mac.h deleted file mode 100644 index 7639e24e4..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_mac.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_MAC_H_ -#define _IGB_MAC_H_ - -/* - * Functions that should not be called directly from drivers but can be used - * by other files in this 'shared code' - */ -void igb_init_mac_ops_generic(struct e1000_hw *hw); -s32 igb_blink_led_generic(struct e1000_hw *hw); -s32 igb_check_for_copper_link_generic(struct e1000_hw *hw); -s32 igb_check_for_fiber_link_generic(struct e1000_hw *hw); -s32 igb_check_for_serdes_link_generic(struct e1000_hw *hw); -s32 igb_cleanup_led_generic(struct e1000_hw *hw); -s32 igb_config_fc_after_link_up_generic(struct e1000_hw *hw); -s32 igb_disable_pcie_master_generic(struct e1000_hw *hw); -s32 igb_force_mac_fc_generic(struct e1000_hw *hw); -s32 igb_get_auto_rd_done_generic(struct e1000_hw *hw); -s32 igb_get_bus_info_pcie_generic(struct e1000_hw *hw); -void igb_set_lan_id_single_port(struct e1000_hw *hw); -s32 igb_get_hw_semaphore_generic(struct e1000_hw *hw); -s32 igb_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 igb_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -s32 igb_id_led_init_generic(struct e1000_hw *hw); -s32 igb_led_on_generic(struct e1000_hw *hw); -s32 igb_led_off_generic(struct e1000_hw *hw); -void igb_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 igb_set_fc_watermarks_generic(struct e1000_hw *hw); -s32 igb_setup_fiber_serdes_link_generic(struct e1000_hw *hw); -s32 igb_setup_led_generic(struct e1000_hw *hw); -s32 igb_setup_link_generic(struct e1000_hw *hw); -s32 igb_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, - u32 offset, u8 data); - -u32 igb_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); - -void igb_clear_hw_cntrs_base_generic(struct e1000_hw *hw); -void igb_clear_vfta_generic(struct e1000_hw *hw); -void igb_config_collision_dist_generic(struct e1000_hw *hw); -void igb_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); -void igb_mta_set_generic(struct e1000_hw *hw, u32 hash_value); -void igb_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); -void igb_put_hw_semaphore_generic(struct e1000_hw *hw); -void igb_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); -s32 igb_check_alt_mac_addr_generic(struct e1000_hw *hw); -void igb_reset_adaptive_generic(struct e1000_hw *hw); -void igb_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); -void igb_update_adaptive_generic(struct e1000_hw *hw); -void igb_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); - -#endif /* _IGB_MAC_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_main.c b/roms/ipxe/src/drivers/net/igb/igb_main.c deleted file mode 100644 index 9295c2c8c..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_main.c +++ /dev/null @@ -1,1010 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 Intel Corporation. - - Portions Copyright(c) 2010 Marty Connor - Portions Copyright(c) 2010 Entity Cyber, Inc. - - 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 - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -/* Low-level support routines */ - -/** - * igb_read_pcie_cap_reg - retrieve PCIe capability register contents - * @hw: address of board private structure - * @reg: PCIe capability register requested - * @value: where to store requested value - **/ -int32_t igb_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) -{ - struct igb_adapter *adapter = hw->back; - uint16_t cap_offset; - -#define PCI_CAP_ID_EXP 0x10 /* PCI Express */ - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_read_config_word(adapter->pdev, cap_offset + reg, value); - - return E1000_SUCCESS; -} - -/** - * igb_write_pcie_cap_reg - write value to PCIe capability register - * @hw: address of board private structure - * @reg: PCIe capability register to write to - * @value: value to store in given register - **/ -int32_t igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) -{ - struct igb_adapter *adapter = hw->back; - u16 cap_offset; - - cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (!cap_offset) - return -E1000_ERR_CONFIG; - - pci_write_config_word(adapter->pdev, cap_offset + reg, *value); - - return E1000_SUCCESS; -} - -/** - * igb_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static void igb_irq_disable(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - E1000_WRITE_REG(hw, E1000_IAM, 0); - E1000_WRITE_REG(hw, E1000_IMC, ~0); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ -static void igb_irq_enable(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); - E1000_WRITE_REG(hw, E1000_IAM, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(hw); -} - -/** - * igb_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 igb_get_hw_control(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - - /* Let firmware know the driver has taken over */ - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - E1000_WRITE_REG(hw, E1000_CTRL_EXT, - ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); -} - -/** - * igb_reset - put adapter in known initial state - * @adapter: board private structure - **/ -void igb_reset(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - struct e1000_mac_info *mac = &hw->mac; - struct e1000_fc_info *fc = &hw->fc; - u32 pba = 0; - u16 hwm; - - /* Repartition Pba for greater than 9k mtu - * To take effect CTRL.RST is required. - */ - switch (mac->type) { - case e1000_82576: - pba = E1000_READ_REG(hw, E1000_RXPBS); - pba &= E1000_RXPBS_SIZE_MASK_82576; - break; - case e1000_82575: - default: - pba = E1000_PBA_34K; - break; - } - - /* flow control settings */ - /* The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, or - * - the full Rx FIFO size minus one full frame */ -#define min(a,b) (((a)<(b))?(a):(b)) - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - 2 * adapter->max_frame_size)); - - if (mac->type < e1000_82576) { - fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; - } else { - fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ - fc->low_water = fc->high_water - 16; - } - fc->pause_time = 0xFFFF; - fc->send_xon = 1; - fc->current_mode = fc->requested_mode; - - /* Allow time for pending master requests to run */ - igb_reset_hw(hw); - E1000_WRITE_REG(hw, E1000_WUC, 0); - - if (igb_init_hw(hw)) { - DBG ("Hardware Error\n"); - } - - igb_get_phy_info(hw); -} - -/** - * igb_sw_init - Initialize general software structures (struct igb_adapter) - * @adapter: board private structure to initialize - **/ -int igb_sw_init(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct pci_device *pdev = adapter->pdev; - - /* 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; - - /* Initialize the hardware-specific values */ - if (igb_setup_init_funcs(hw, TRUE)) { - DBG ("Hardware Initialization Failure\n"); - return -EIO; - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - igb_irq_disable(adapter); - - return 0; -} - -/* TX support routines */ - -/** - * igb_setup_tx_resources - allocate Tx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int igb_setup_tx_resources ( struct igb_adapter *adapter ) -{ - DBG ( "igb_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; -} - -/** - * igb_process_tx_packets - process transmitted packets - * - * @v netdev network interface device structure - **/ -static void igb_process_tx_packets ( struct net_device *netdev ) -{ - struct igb_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t tx_status; - struct e1000_tx_desc *tx_curr_desc; - - /* Check status of transmitted packets - */ - DBG ( "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->upper.data; - - 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 ); - - if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | - E1000_TXD_STAT_TU ) ) { - netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL ); - DBG ( "Error transmitting packet, tx_status: %#08x\n", - tx_status ); - } else { - 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; - } -} - -static void igb_free_tx_resources ( struct igb_adapter *adapter ) -{ - DBG ( "igb_free_tx_resources\n" ); - - free_dma ( adapter->tx_base, adapter->tx_ring_size ); -} - -/** - * igb_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void igb_configure_tx ( struct igb_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl; - - DBG ( "igb_configure_tx\n" ); - - /* disable transmits while setting up the descriptors */ - tctl = E1000_READ_REG ( hw, E1000_TCTL ); - E1000_WRITE_REG ( hw, E1000_TCTL, tctl & ~E1000_TCTL_EN ); - E1000_WRITE_FLUSH(hw); - mdelay(10); - - E1000_WRITE_REG ( hw, E1000_TDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDBAL(0), virt_to_bus ( adapter->tx_base ) ); - E1000_WRITE_REG ( hw, E1000_TDLEN(0), adapter->tx_ring_size ); - - DBG ( "E1000_TDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_TDBAL(0) ) ); - DBG ( "E1000_TDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_TDLEN(0) ) ); - - /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG ( hw, E1000_TDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_TDT(0), 0 ); - - adapter->tx_head = 0; - adapter->tx_tail = 0; - adapter->tx_fill_ctr = 0; - - txdctl = E1000_READ_REG ( hw, E1000_TXDCTL(0) ); - txdctl |= E1000_TXDCTL_QUEUE_ENABLE; - E1000_WRITE_REG ( hw, E1000_TXDCTL(0), txdctl ); - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* enable Report Status bit */ - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - /* Program the Transmit Control Register */ - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - igb_config_collision_dist(hw); - - /* Enable transmits */ - tctl |= E1000_TCTL_EN; - E1000_WRITE_REG(hw, E1000_TCTL, tctl); - E1000_WRITE_FLUSH(hw); -} - -/* RX support routines */ - -static void igb_free_rx_resources ( struct igb_adapter *adapter ) -{ - int i; - - DBG ( "igb_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] ); - } -} - -/** - * igb_refill_rx_ring - allocate Rx io_buffers - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int igb_refill_rx_ring ( struct igb_adapter *adapter ) -{ - int i, rx_curr; - int rc = 0; - struct e1000_rx_desc *rx_curr_desc; - struct e1000_hw *hw = &adapter->hw; - struct io_buffer *iob; - - DBGP ("igb_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->status & 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; - - if ( ! iob ) { - DBG ( "alloc_iob failed\n" ); - rc = -ENOMEM; - break; - } else { - rx_curr_desc->buffer_addr = virt_to_bus ( iob->data ); - - E1000_WRITE_REG ( hw, E1000_RDT(0), rx_curr ); - } - } - return rc; -} - -/** - * igb_setup_rx_resources - allocate Rx resources (Descriptors) - * - * @v adapter e1000 private structure - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int igb_setup_rx_resources ( struct igb_adapter *adapter ) -{ - int i, rc = 0; - - DBGP ( "igb_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++ ) { - /* let igb_refill_rx_ring() io_buffer allocations */ - adapter->rx_iobuf[i] = NULL; - } - - /* allocate io_buffers */ - rc = igb_refill_rx_ring ( adapter ); - if ( rc < 0 ) - igb_free_rx_resources ( adapter ); - - return rc; -} - -/** - * igb_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void igb_configure_rx ( struct igb_adapter *adapter ) -{ - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl, rxdctl, rxcsum, mrqc; - - DBGP ( "igb_configure_rx\n" ); - - /* disable receives while setting up the descriptors */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - E1000_WRITE_FLUSH(hw); - mdelay(10); - - adapter->rx_curr = 0; - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring */ - - E1000_WRITE_REG ( hw, E1000_RDBAL(0), virt_to_bus ( adapter->rx_base ) ); - E1000_WRITE_REG ( hw, E1000_RDBAH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDLEN(0), adapter->rx_ring_size ); - - E1000_WRITE_REG ( hw, E1000_RDH(0), 0 ); - E1000_WRITE_REG ( hw, E1000_RDT(0), 0 ); - - DBG ( "E1000_RDBAL(0): %#08x\n", E1000_READ_REG ( hw, E1000_RDBAL(0) ) ); - DBG ( "E1000_RDLEN(0): %d\n", E1000_READ_REG ( hw, E1000_RDLEN(0) ) ); - DBG ( "E1000_RCTL: %#08x\n", E1000_READ_REG ( hw, E1000_RCTL ) ); - - rxdctl = E1000_READ_REG ( hw, E1000_RXDCTL(0) ); - rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; - rxdctl &= 0xFFF00000; - rxdctl |= IGB_RX_PTHRESH; - rxdctl |= IGB_RX_HTHRESH << 8; - rxdctl |= IGB_RX_WTHRESH << 16; - E1000_WRITE_REG ( hw, E1000_RXDCTL(0), rxdctl ); - E1000_WRITE_FLUSH ( hw ); - - rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); - rxcsum &= ~( E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE ); - E1000_WRITE_REG ( hw, E1000_RXCSUM, 0 ); - - /* The initial value for MRQC disables multiple receive - * queues, however this setting is not recommended. - * - Intel® 82576 Gigabit Ethernet Controller Datasheet r2.41 - * Section 8.10.9 Multiple Queues Command Register - MRQC - */ - mrqc = E1000_MRQC_ENABLE_VMDQ; - E1000_WRITE_REG ( hw, E1000_MRQC, mrqc ); - - /* Turn off loopback modes */ - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - - /* set maximum packet size */ - rctl |= E1000_RCTL_SZ_2048; - - /* Broadcast enable, multicast promisc, unicast promisc */ - rctl |= E1000_RCTL_BAM | E1000_RCTL_MPE | E1000_RCTL_UPE; - - /* Store bad packets */ - rctl |= E1000_RCTL_SBP; - - /* enable LPE to prevent packets larger than max_frame_size */ - rctl |= E1000_RCTL_LPE; - - /* enable stripping of CRC. */ - rctl |= E1000_RCTL_SECRC; - - /* enable receive control register */ - rctl |= E1000_RCTL_EN; - E1000_WRITE_REG(hw, E1000_RCTL, rctl); - E1000_WRITE_FLUSH(hw); - - /* On the 82576, RDT([0]) must not be "bumped" before - * the enable bit of RXDCTL([0]) is set. - * - Intel® 82576 Gigabit Ethernet Controller Datasheet r2.41 - * Section 4.5.9 receive Initialization - * - * By observation I have found this to occur when the enable bit of - * RCTL is set. The datasheet recommends polling for this bit, - * however as I see no evidence of this in the Linux igb driver - * I have omitted that step. - * - Simon Horman, May 2009 - */ - E1000_WRITE_REG ( hw, E1000_RDT(0), NUM_RX_DESC - 1 ); - - DBG ( "RDBAH: %#08x\n", E1000_READ_REG ( hw, E1000_RDBAH(0) ) ); - DBG ( "RDBAL: %#08x\n", E1000_READ_REG ( hw, E1000_RDBAL(0) ) ); - DBG ( "RDLEN: %d\n", E1000_READ_REG ( hw, E1000_RDLEN(0) ) ); - DBG ( "RCTL: %#08x\n", E1000_READ_REG ( hw, E1000_RCTL ) ); -} - -/** - * igb_process_rx_packets - process received packets - * - * @v netdev network interface device structure - **/ -static void igb_process_rx_packets ( struct net_device *netdev ) -{ - struct igb_adapter *adapter = netdev_priv ( netdev ); - uint32_t i; - uint32_t rx_status; - uint32_t rx_len; - uint32_t rx_err; - struct e1000_rx_desc *rx_curr_desc; - - DBGP ( "igb_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->status; - - DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status ); - - if ( ! ( rx_status & E1000_RXD_STAT_DD ) ) - break; - - if ( adapter->rx_iobuf[i] == NULL ) - break; - - DBG ( "E1000_RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RCTL ) ); - - rx_len = rx_curr_desc->length; - - DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n", - i, rx_status, rx_len ); - - rx_err = rx_curr_desc->errors; - - iob_put ( adapter->rx_iobuf[i], rx_len ); - - if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) { - - netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL ); - DBG ( "igb_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; - } -} - -/** Functions that implement the iPXE driver API **/ - -/** - * igb_close - Disables a network interface - * - * @v netdev network interface device structure - * - **/ -static void igb_close ( struct net_device *netdev ) -{ - struct igb_adapter *adapter = netdev_priv ( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t rctl; - - DBGP ( "igb_close\n" ); - - /* Disable and acknowledge interrupts */ - igb_irq_disable ( adapter ); - E1000_READ_REG ( hw, E1000_ICR ); - - /* disable receives */ - rctl = E1000_READ_REG ( hw, E1000_RCTL ); - E1000_WRITE_REG ( hw, E1000_RCTL, rctl & ~E1000_RCTL_EN ); - E1000_WRITE_FLUSH(hw); - - igb_reset ( adapter ); - - igb_free_tx_resources ( adapter ); - igb_free_rx_resources ( adapter ); -} - -/** - * igb_transmit - Transmit a packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * - * @ret rc Returns 0 on success, negative on failure - */ -static int igb_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) -{ - struct igb_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - uint32_t tx_curr = adapter->tx_tail; - struct e1000_tx_desc *tx_curr_desc; - - DBGP ("igb_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->buffer_addr = virt_to_bus ( iobuf->data ); - tx_curr_desc->upper.data = 0; - tx_curr_desc->lower.data = adapter->txd_cmd | iob_len ( iobuf ); - - 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 - */ - E1000_WRITE_REG ( hw, E1000_TDT(0), adapter->tx_tail ); - E1000_WRITE_FLUSH(hw); - - return 0; -} - -/** - * igb_poll - Poll for received packets - * - * @v netdev Network device - */ -static void igb_poll ( struct net_device *netdev ) -{ - struct igb_adapter *adapter = netdev_priv( netdev ); - struct e1000_hw *hw = &adapter->hw; - - uint32_t icr; - - DBGP ( "igb_poll\n" ); - - /* Acknowledge interrupts */ - icr = E1000_READ_REG ( hw, E1000_ICR ); - if ( ! icr ) - return; - - DBG ( "igb_poll: intr_status = %#08x\n", icr ); - - igb_process_tx_packets ( netdev ); - - igb_process_rx_packets ( netdev ); - - igb_refill_rx_ring(adapter); -} - -/** - * igb_irq - enable or Disable interrupts - * - * @v adapter e1000 adapter - * @v action requested interrupt action - **/ -static void igb_irq ( struct net_device *netdev, int enable ) -{ - struct igb_adapter *adapter = netdev_priv ( netdev ); - - DBGP ( "igb_irq\n" ); - - if ( enable ) { - igb_irq_enable ( adapter ); - } else { - igb_irq_disable ( adapter ); - } -} - -static struct net_device_operations igb_operations; - -/** - * igb_probe - Initial configuration of NIC - * - * @v pci PCI device - * @v id PCI IDs - * - * @ret rc Return status code - **/ -int igb_probe ( struct pci_device *pdev ) -{ - int i, err; - struct net_device *netdev; - struct igb_adapter *adapter; - unsigned long mmio_start, mmio_len; - struct e1000_hw *hw; - - DBGP ( "igb_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 igb_adapter ) ); - if ( ! netdev ) { - DBG ( "err_alloc_etherdev\n" ); - goto err_alloc_etherdev; - } - - /* Associate igb-specific network operations operations with - * generic network device layer */ - netdev_init ( netdev, &igb_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 = igb_sw_init ( adapter ); - if (err) { - DBG ( "err_sw_init\n" ); - goto err_sw_init; - } - - igb_get_bus_info(hw); - - /* Copper options */ - if (adapter->hw.phy.media_type == e1000_media_type_copper) { - adapter->hw.phy.mdix = AUTO_ALL_MODES; - adapter->hw.phy.disable_polarity_correction = 0; - adapter->hw.phy.ms_type = e1000_ms_hw_default; - } - - DBG ( "adapter->hw.mac.type: %#08x\n", adapter->hw.mac.type ); - - /* Force auto-negotiation */ - adapter->hw.mac.autoneg = 1; - adapter->fc_autoneg = 1; - adapter->hw.phy.autoneg_wait_to_complete = true; - adapter->hw.mac.adaptive_ifs = true; - adapter->hw.fc.requested_mode = e1000_fc_default; - adapter->hw.fc.current_mode = e1000_fc_default; - - igb_validate_mdi_setting(hw); - - /* - * before reading the NVM, reset the controller to - * put the device in a known good starting state - */ - igb_reset_hw(hw); - - /* - * systems with ASPM and others may see the checksum fail on the first - * attempt. Let's give it a few tries - */ - for (i = 0;; i++) { - if (igb_validate_nvm_checksum(&adapter->hw) >= 0) - break; - if (i == 2) { - err = -EIO; - DBG ( "The NVM Checksum Is Not Valid\n" ); - DBG ( "err_eeprom\n" ); - goto err_eeprom; - } - } - - /* copy the MAC address out of the EEPROM */ - if ( igb_read_mac_addr ( &adapter->hw ) ) { - DBG ( "EEPROM Read Error\n" ); - } - - memcpy ( netdev->hw_addr, adapter->hw.mac.perm_addr, ETH_ALEN ); - - /* reset the hardware with the new settings */ - igb_reset ( adapter ); - - /* let the f/w know that the h/w is now under the control of the - * driver. */ - igb_get_hw_control(adapter); - - if ( ( err = register_netdev ( netdev ) ) != 0) { - DBG ( "err_register\n" ); - goto err_register; - } - - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); - - for (i = 0; i < 6; i++) { - DBG ("%02x%s", netdev->ll_addr[i], i == 5 ? "\n" : ":"); - } - - DBG ( "igb_probe succeeded!\n" ); - - /* No errors, return success */ - return 0; - -/* Error return paths */ -err_register: -err_eeprom: -err_sw_init: - iounmap ( adapter->hw.hw_addr ); -err_ioremap: - netdev_put ( netdev ); -err_alloc_etherdev: - return err; -} - -/** - * igb_remove - Device Removal Routine - * - * @v pdev PCI device information struct - * - **/ -void igb_remove ( struct pci_device *pdev ) -{ - struct net_device *netdev = pci_get_drvdata ( pdev ); - struct igb_adapter *adapter = netdev_priv ( netdev ); - - DBGP ( "igb_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 ); - igb_reset ( adapter ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** - * igb_open - Called when a network interface is made active - * - * @v netdev network interface device structure - * @ret rc Return status code, 0 on success, negative value on failure - * - **/ -static int igb_open ( struct net_device *netdev ) -{ - struct igb_adapter *adapter = netdev_priv(netdev); - int err; - - DBGP ( "igb_open\n" ); - - /* allocate transmit descriptors */ - err = igb_setup_tx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up TX resources!\n" ); - goto err_setup_tx; - } - - /* allocate receive descriptors */ - err = igb_setup_rx_resources ( adapter ); - if ( err ) { - DBG ( "Error setting up RX resources!\n" ); - goto err_setup_rx; - } - - igb_configure_tx ( adapter ); - - igb_configure_rx ( adapter ); - - DBG ( "E1000_RXDCTL(0): %#08x\n", E1000_READ_REG ( &adapter->hw, E1000_RXDCTL(0) ) ); - - return 0; - -err_setup_rx: - DBG ( "err_setup_rx\n" ); - igb_free_tx_resources ( adapter ); -err_setup_tx: - DBG ( "err_setup_tx\n" ); - igb_reset ( adapter ); - - return err; -} - -/** igb net device operations */ -static struct net_device_operations igb_operations = { - .open = igb_open, - .close = igb_close, - .transmit = igb_transmit, - .poll = igb_poll, - .irq = igb_irq, -}; diff --git a/roms/ipxe/src/drivers/net/igb/igb_manage.c b/roms/ipxe/src/drivers/net/igb/igb_manage.c deleted file mode 100644 index b29d4c4a5..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_manage.c +++ /dev/null @@ -1,388 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -#if 0 - -static u8 e1000_calculate_checksum(u8 *buffer, u32 length); - -/** - * e1000_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - DEBUGFUNC("igb_calculate_checksum"); - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8) (0 - sum); -} - -/** - * e1000_mng_enable_host_if_generic - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) -{ - u32 hicr; - s32 ret_val = E1000_SUCCESS; - u8 i; - - DEBUGFUNC("igb_mng_enable_host_if_generic"); - - /* Check that the host interface is enabled. */ - hicr = E1000_READ_REG(hw, E1000_HICR); - if ((hicr & E1000_HICR_EN) == 0) { - DEBUGOUT("E1000_HOST_EN bit disabled.\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = E1000_READ_REG(hw, E1000_HICR); - if (!(hicr & E1000_HICR_C)) - break; - msec_delay_irq(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - DEBUGOUT("Previous command timeout failed .\n"); - ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; - goto out; - } - -out: - return ret_val; -} - -/** - * e1000_check_mng_mode_generic - Generic check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm; - - DEBUGFUNC("igb_check_mng_mode_generic"); - - fwsm = E1000_READ_REG(hw, E1000_FWSM); - - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - bool tx_filter = true; - - DEBUGFUNC("igb_enable_tx_pkt_filtering_generic"); - - /* No manageability, no filtering */ - if (!hw->mac.ops.check_mng_mode(hw)) { - tx_filter = false; - goto out; - } - - /* - * If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val != E1000_SUCCESS) { - tx_filter = false; - goto out; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) { - *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, - E1000_HOST_IF, - offset + i); - } - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if (hdr_csum != csum) - goto out; - if (hdr->signature != E1000_IAMT_SIGNATURE) - goto out; - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - tx_filter = false; - -out: - hw->mac.tx_pkt_filtering = tx_filter; - return tx_filter; -} - -/** - * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, - u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - DEBUGFUNC("igb_mng_write_dhcp_info_generic"); - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); - if (ret_val) - goto out; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - goto out; - - /* Write the manageability command header */ - ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); - if (ret_val) - goto out; - - /* Tell the ARC a new command is pending. */ - hicr = E1000_READ_REG(hw, E1000_HICR); - E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); - -out: - return ret_val; -} - -/** - * e1000_mng_write_cmd_header_generic - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - DEBUGFUNC("igb_mng_write_cmd_header_generic"); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, - *((u32 *) hdr + i)); - E1000_WRITE_FLUSH(hw); - } - - return E1000_SUCCESS; -} - -/** - * e1000_mng_host_if_write_generic - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - s32 ret_val = E1000_SUCCESS; - u16 remaining, i, j, prev_bytes; - - DEBUGFUNC("igb_mng_host_if_write_generic"); - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { - ret_val = -E1000_ERR_PARAM; - goto out; - } - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* - * The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, - data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); - } - -out: - return ret_val; -} - -/** - * e1000_enable_mng_pass_thru - Enable processing of ARP's - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to allow ARPs to be processed by the host. - **/ -bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - bool ret_val = false; - - DEBUGFUNC("igb_enable_mng_pass_thru"); - - if (!hw->mac.asf_firmware_present) - goto out; - - manc = E1000_READ_REG(hw, E1000_MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - goto out; - - if (hw->mac.arc_subsystem_valid) { - fwsm = E1000_READ_REG(hw, E1000_FWSM); - factps = E1000_READ_REG(hw, E1000_FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { - ret_val = true; - goto out; - } - } else { - if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - ret_val = true; - goto out; - } - } - -out: - return ret_val; -} - -#endif diff --git a/roms/ipxe/src/drivers/net/igb/igb_manage.h b/roms/ipxe/src/drivers/net/igb/igb_manage.h deleted file mode 100644 index ff70d8c9e..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_manage.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_MANAGE_H_ -#define _IGB_MANAGE_H_ - -bool e1000_check_mng_mode_generic(struct e1000_hw *hw); -bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); -s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); -s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum); -s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr); -s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, - u8 *buffer, u16 length); -bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); - -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -#define E1000_FWSM_MODE_MASK 0xE -#define E1000_FWSM_MODE_SHIFT 1 - -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 - -#define E1000_VFTA_ENTRY_SHIFT 5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ -#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ -#define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ - -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 -#define E1000_HICR_SV 0x04 /* Status Validity */ -#define E1000_HICR_FW_RESET_ENABLE 0x40 -#define E1000_HICR_FW_RESET 0x80 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - -#endif /* _IGB_MANAGE_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_nvm.c b/roms/ipxe/src/drivers/net/igb/igb_nvm.c deleted file mode 100644 index 1bad567cf..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_nvm.c +++ /dev/null @@ -1,627 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -static void igb_stop_nvm(struct e1000_hw *hw); -static void igb_reload_nvm_generic(struct e1000_hw *hw); - -/** - * igb_init_nvm_ops_generic - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Setups up the function pointers to no-op functions - **/ -void igb_init_nvm_ops_generic(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - DEBUGFUNC("igb_init_nvm_ops_generic"); - - /* Initialize function pointers */ - nvm->ops.reload = igb_reload_nvm_generic; -} - -/** - * igb_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void igb_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - E1000_WRITE_REG(hw, E1000_EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->nvm.delay_usec); -} - -/** - * igb_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void igb_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - E1000_WRITE_REG(hw, E1000_EECD, *eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(hw->nvm.delay_usec); -} - -/** - * igb_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void igb_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - u32 mask; - - DEBUGFUNC("igb_shift_out_eec_bits"); - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - - usec_delay(nvm->delay_usec); - - igb_raise_eec_clk(hw, &eecd); - igb_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - E1000_WRITE_REG(hw, E1000_EECD, eecd); -} - -/** - * igb_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 igb_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - DEBUGFUNC("igb_shift_in_eec_bits"); - - eecd = E1000_READ_REG(hw, E1000_EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - igb_raise_eec_clk(hw, &eecd); - - eecd = E1000_READ_REG(hw, E1000_EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - igb_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * igb_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 igb_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - s32 ret_val = -E1000_ERR_NVM; - - DEBUGFUNC("igb_poll_eerd_eewr_done"); - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = E1000_READ_REG(hw, E1000_EERD); - else - reg = E1000_READ_REG(hw, E1000_EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) { - ret_val = E1000_SUCCESS; - break; - } - - usec_delay(5); - } - - return ret_val; -} - -/** - * igb_acquire_nvm_generic - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 igb_acquire_nvm_generic(struct e1000_hw *hw) -{ - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_acquire_nvm_generic"); - - E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); - eecd = E1000_READ_REG(hw, E1000_EECD); - - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - usec_delay(5); - eecd = E1000_READ_REG(hw, E1000_EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - DEBUGOUT("Could not acquire NVM grant\n"); - ret_val = -E1000_ERR_NVM; - } - - return ret_val; -} - -/** - * igb_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void igb_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - - DEBUGFUNC("igb_standby_nvm"); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - E1000_WRITE_REG(hw, E1000_EECD, eecd); - E1000_WRITE_FLUSH(hw); - usec_delay(nvm->delay_usec); - } -} - -/** - * igb_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -static void igb_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - DEBUGFUNC("igb_stop_nvm"); - - eecd = E1000_READ_REG(hw, E1000_EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - igb_lower_eec_clk(hw, &eecd); - } -} - -/** - * igb_release_nvm_generic - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void igb_release_nvm_generic(struct e1000_hw *hw) -{ - u32 eecd; - - DEBUGFUNC("igb_release_nvm_generic"); - - igb_stop_nvm(hw); - - eecd = E1000_READ_REG(hw, E1000_EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, E1000_EECD, eecd); -} - -/** - * igb_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 igb_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = E1000_READ_REG(hw, E1000_EECD); - s32 ret_val = E1000_SUCCESS; - u16 timeout = 0; - u8 spi_stat_reg; - - DEBUGFUNC("igb_ready_nvm_eeprom"); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, E1000_EECD, eecd); - usec_delay(1); - timeout = NVM_MAX_RETRY_SPI; - - /* - * Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - igb_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)igb_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - usec_delay(5); - igb_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - DEBUGOUT("SPI NVM Status error\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - } - -out: - return ret_val; -} - -/** - * igb_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_read_nvm_eerd"); - - /* - * A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - for (i = 0; i < words; i++) { - eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - E1000_WRITE_REG(hw, E1000_EERD, eerd); - ret_val = igb_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) - break; - - data[i] = (E1000_READ_REG(hw, E1000_EERD) >> - E1000_NVM_RW_REG_DATA); - } - -out: - return ret_val; -} - -/** - * igb_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 widx = 0; - - DEBUGFUNC("igb_write_nvm_spi"); - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = igb_ready_nvm_eeprom(hw); - if (ret_val) - goto release; - - igb_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - igb_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - igb_standby_nvm(hw); - - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - igb_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - igb_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - igb_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - igb_standby_nvm(hw); - break; - } - } - } - - msec_delay(10); -release: - nvm->ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_read_pba_num_generic - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 igb_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) -{ - s32 ret_val; - u16 nvm_data; - - DEBUGFUNC("igb_read_pba_num_generic"); - - ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - *pba_num = (u32)(nvm_data << 16); - - ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - *pba_num |= nvm_data; - -out: - return ret_val; -} - -/** - * igb_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 igb_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = E1000_READ_REG(hw, E1000_RAH(0)); - rar_low = E1000_READ_REG(hw, E1000_RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); - - for (i = 0; i < ETH_ADDR_LEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return E1000_SUCCESS; -} - -/** - * igb_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 igb_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 checksum = 0; - u16 i, nvm_data; - - DEBUGFUNC("igb_validate_nvm_checksum_generic"); - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error\n"); - goto out; - } - checksum += nvm_data; - } - - if (checksum != (u16) NVM_SUM) { - DEBUGOUT("NVM Checksum Invalid\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 igb_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - DEBUGFUNC("igb_update_nvm_checksum"); - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); - if (ret_val) { - DEBUGOUT("NVM Read Error while updating checksum.\n"); - goto out; - } - checksum += nvm_data; - } - checksum = (u16) NVM_SUM - checksum; - ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) { - DEBUGOUT("NVM Write Error while updating checksum.\n"); - } -out: - return ret_val; -} - -/** - * igb_reload_nvm_generic - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -static void igb_reload_nvm_generic(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - DEBUGFUNC("igb_reload_nvm_generic"); - - usec_delay(10); - ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); -} - diff --git a/roms/ipxe/src/drivers/net/igb/igb_nvm.h b/roms/ipxe/src/drivers/net/igb/igb_nvm.h deleted file mode 100644 index 6b54d44ce..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_nvm.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_NVM_H_ -#define _IGB_NVM_H_ - -void igb_init_nvm_ops_generic(struct e1000_hw *hw); -s32 igb_acquire_nvm_generic(struct e1000_hw *hw); - -s32 igb_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -s32 igb_read_mac_addr_generic(struct e1000_hw *hw); -s32 igb_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); -s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 igb_valid_led_default_generic(struct e1000_hw *hw, u16 *data); -s32 igb_validate_nvm_checksum_generic(struct e1000_hw *hw); -s32 igb_write_nvm_eewr(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -s32 igb_update_nvm_checksum_generic(struct e1000_hw *hw); -void igb_release_nvm_generic(struct e1000_hw *hw); - -#define E1000_STM_OPCODE 0xDB00 - -#endif /* _IGB_NVM_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_osdep.h b/roms/ipxe/src/drivers/net/igb/igb_osdep.h deleted file mode 100644 index 167b0f85c..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_osdep.h +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -/* glue for the OS independent part of e1000 - * includes register access macros - */ - -#ifndef _IGB_OSDEP_H_ -#define _IGB_OSDEP_H_ - -/* Begin OS Dependencies */ - -#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 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) - -/* End OS Dependencies */ - -#define PCI_COMMAND_REGISTER PCI_COMMAND -#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE -#define ETH_ADDR_LEN ETH_ALEN - -#ifdef __BIG_ENDIAN -#define E1000_BIG_ENDIAN __BIG_ENDIAN -#endif - - -#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_REGISTER(a, reg) (reg) - -#define E1000_WRITE_REG(a, reg, value) do { \ - writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg))); } while (0) - -#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg))) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) do { \ - writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))); } while (0); - -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + E1000_REGISTER(a, 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 + E1000_REGISTER(a, reg) + ((offset) << 1)))) - -#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ - readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))) - -#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ - writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))) - -#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ - readb((a)->hw_addr + E1000_REGISTER(a, 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 /* _IGB_OSDEP_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_phy.c b/roms/ipxe/src/drivers/net/igb/igb_phy.c deleted file mode 100644 index 16664fd1f..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_phy.c +++ /dev/null @@ -1,2470 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#include "igb.h" - -static s32 igb_phy_setup_autoneg(struct e1000_hw *hw); - -#if 0 -/* Cable length tables */ -static const u16 e1000_m88_cable_length_table[] = - { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_m88_cable_length_table) / \ - sizeof(e1000_m88_cable_length_table[0])) - -static const u16 e1000_igp_2_cable_length_table[] = - { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, - 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, - 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, - 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, - 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, - 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, - 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, - 104, 109, 114, 118, 121, 124}; -#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ - (sizeof(e1000_igp_2_cable_length_table) / \ - sizeof(e1000_igp_2_cable_length_table[0])) -#endif - -/** - * igb_check_reset_block_generic - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Read the PHY management control register and check whether a PHY reset - * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise - * return E1000_BLK_PHY_RESET (12). - **/ -s32 igb_check_reset_block_generic(struct e1000_hw *hw) -{ - u32 manc; - - DEBUGFUNC("igb_check_reset_block"); - - manc = E1000_READ_REG(hw, E1000_MANC); - - return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? - E1000_BLK_PHY_RESET : E1000_SUCCESS; -} - -/** - * igb_get_phy_id - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -s32 igb_get_phy_id(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_id; - - DEBUGFUNC("igb_get_phy_id"); - - if (!(phy->ops.read_reg)) - goto out; - - ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); - if (ret_val) - goto out; - - phy->id = (u32)(phy_id << 16); - usec_delay(20); - ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); - if (ret_val) - goto out; - - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - -out: - return ret_val; -} - -/** - * igb_phy_reset_dsp_generic - Reset PHY DSP - * @hw: pointer to the HW structure - * - * Reset the digital signal processor. - **/ -s32 igb_phy_reset_dsp_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_phy_reset_dsp_generic"); - - if (!(hw->phy.ops.write_reg)) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); - if (ret_val) - goto out; - - ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); - -out: - return ret_val; -} - -/** - * igb_read_phy_reg_mdic - Read MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the MDI control register in the PHY at offset and stores the - * information read to data. - **/ -s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_read_phy_reg_mdic"); - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - E1000_WRITE_REG(hw, E1000_MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, E1000_MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Read did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - *data = (u16) mdic; - -out: - return ret_val; -} - -/** - * igb_write_phy_reg_mdic - Write MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write to register at offset - * - * Writes data to MDI control register in the PHY at offset. - **/ -s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_write_phy_reg_mdic"); - - /* - * Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = (((u32)data) | - (offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - E1000_WRITE_REG(hw, E1000_MDIC, mdic); - - /* - * Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - usec_delay(50); - mdic = E1000_READ_REG(hw, E1000_MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - DEBUGOUT("MDI Write did not complete\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - if (mdic & E1000_MDIC_ERROR) { - DEBUGOUT("MDI Error\n"); - ret_val = -E1000_ERR_PHY; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_read_phy_reg_i2c - Read PHY register using i2c - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the i2c interface and stores the - * retrieved information in data. - **/ -s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, i2ccmd = 0; - - DEBUGFUNC("igb_read_phy_reg_i2c"); - - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD - * register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | - (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | - (E1000_I2CCMD_OPCODE_READ)); - - E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); - - /* Poll the ready bit to see if the I2C read completed */ - for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { - usec_delay(50); - i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); - if (i2ccmd & E1000_I2CCMD_READY) - break; - } - if (!(i2ccmd & E1000_I2CCMD_READY)) { - DEBUGOUT("I2CCMD Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (i2ccmd & E1000_I2CCMD_ERROR) { - DEBUGOUT("I2CCMD Error bit set\n"); - return -E1000_ERR_PHY; - } - - /* Need to byte-swap the 16-bit value. */ - *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); - - return E1000_SUCCESS; -} - -/** - * igb_write_phy_reg_i2c - Write PHY register using i2c - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset using the i2c interface. - **/ -s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, i2ccmd = 0; - u16 phy_data_swapped; - - DEBUGFUNC("igb_write_phy_reg_i2c"); - - /* Swap the data bytes for the I2C interface */ - phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); - - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD - * register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | - (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | - E1000_I2CCMD_OPCODE_WRITE | - phy_data_swapped); - - E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); - - /* Poll the ready bit to see if the I2C read completed */ - for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { - usec_delay(50); - i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); - if (i2ccmd & E1000_I2CCMD_READY) - break; - } - if (!(i2ccmd & E1000_I2CCMD_READY)) { - DEBUGOUT("I2CCMD Write did not complete\n"); - return -E1000_ERR_PHY; - } - if (i2ccmd & E1000_I2CCMD_ERROR) { - DEBUGOUT("I2CCMD Error bit set\n"); - return -E1000_ERR_PHY; - } - - return E1000_SUCCESS; -} - -/** - * igb_read_phy_reg_m88 - Read m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 igb_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_read_phy_reg_m88"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = igb_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_write_phy_reg_m88 - Write m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 igb_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_write_phy_reg_m88"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * __igb_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -static s32 __igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("__igb_read_phy_reg_igp"); - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = igb_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) - goto release; - } - - ret_val = igb_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - if (!locked) - hw->phy.ops.release(hw); -out: - return ret_val; -} -/** - * igb_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores the - * retrieved information in data. - * Release the acquired semaphore before exiting. - **/ -s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __igb_read_phy_reg_igp(hw, offset, data, false); -} - -/** - * igb_read_phy_reg_igp_locked - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 igb_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __igb_read_phy_reg_igp(hw, offset, data, true); -} - -/** - * igb_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_write_phy_reg_igp"); - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = igb_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (ret_val) - goto release; - } - - ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __igb_write_phy_reg_igp(hw, offset, data, false); -} - -/** - * igb_write_phy_reg_igp_locked - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. - * Assumes semaphore already acquired. - **/ -s32 igb_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __igb_write_phy_reg_igp(hw, offset, data, true); -} - -/** - * __igb_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then reads the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release any acquired semaphores before exiting. - **/ -static s32 __igb_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("__igb_read_kmrn_reg"); - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); - - usec_delay(2); - - kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_read_kmrn_reg_generic - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset using the - * kumeran interface. The information retrieved is stored in data. - * Release the acquired semaphore before exiting. - **/ -s32 igb_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __igb_read_kmrn_reg(hw, offset, data, false); -} - -/** - * igb_read_kmrn_reg_locked - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the kumeran interface. The - * information retrieved is stored in data. - * Assumes semaphore already acquired. - **/ -s32 igb_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __igb_read_kmrn_reg(hw, offset, data, true); -} - -/** - * __igb_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then write the data to PHY register - * at the offset using the kumeran interface. Release any acquired semaphores - * before exiting. - **/ -static s32 __igb_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - u32 kmrnctrlsta; - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("igb_write_kmrn_reg_generic"); - - if (!locked) { - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); - - usec_delay(2); - - if (!locked) - hw->phy.ops.release(hw); - -out: - return ret_val; -} - -/** - * igb_write_kmrn_reg_generic - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to the PHY register at the offset - * using the kumeran interface. Release the acquired semaphore before exiting. - **/ -s32 igb_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __igb_write_kmrn_reg(hw, offset, data, false); -} - -/** - * igb_write_kmrn_reg_locked - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Write the data to PHY register at the offset using the kumeran interface. - * Assumes semaphore already acquired. - **/ -s32 igb_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __igb_write_kmrn_reg(hw, offset, data, true); -} - -/** - * igb_copper_link_setup_m88 - Setup m88 PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock - * and downshift values are set also. - **/ -s32 igb_copper_link_setup_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - DEBUGFUNC("igb_copper_link_setup_m88"); - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* - * Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* - * Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - if (phy->revision < E1000_REVISION_4) { - /* - * Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((phy->revision == E1000_REVISION_2) && - (phy->id == M88E1111_I_PHY_ID)) { - /* 82573L PHY - set the downshift counter to 5x. */ - phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - } - ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - goto out; - } - - /* Commit the changes. */ - ret_val = phy->ops.commit(hw); - if (ret_val) { - DEBUGOUT("Error committing the PHY changes\n"); - goto out; - } - -out: - return ret_val; -} - -/** - * igb_copper_link_setup_igp - Setup igp PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for - * igp PHY's. - **/ -s32 igb_copper_link_setup_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("igb_copper_link_setup_igp"); - - if (phy->reset_disable) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = hw->phy.ops.reset(hw); - if (ret_val) { - DEBUGOUT("Error resetting the PHY.\n"); - goto out; - } - - /* - * Wait 100ms for MAC to configure PHY from NVM settings, to avoid - * timeout issues when LFS is enabled. - */ - msec_delay(100); - - /* - * The NVM settings will configure LPLU in D3 for - * non-IGP1 PHYs. - */ - if (phy->type == e1000_phy_igp) { - /* disable lplu d3 during driver init */ - ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); - if (ret_val) { - DEBUGOUT("Error Disabling LPLU D3\n"); - goto out; - } - } - - /* disable lplu d0 during driver init */ - if (hw->phy.ops.set_d0_lplu_state) { - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); - if (ret_val) { - DEBUGOUT("Error Disabling LPLU D0\n"); - goto out; - } - } - /* Configure mdi-mdix settings */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (phy->mdix) { - case 1: - data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); - if (ret_val) - goto out; - - /* set auto-master slave resolution settings */ - if (hw->mac.autoneg) { - /* - * when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - - /* Set auto Master/Slave resolution process */ - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - data &= ~CR_1000T_MS_ENABLE; - ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); - if (ret_val) - goto out; - - /* load defaults for future use */ - phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? - ((data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : - e1000_ms_auto; - - switch (phy->ms_type) { - case e1000_ms_force_master: - data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - data |= CR_1000T_MS_ENABLE; - data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * igb_copper_link_autoneg - Setup/Enable autoneg for copper link - * @hw: pointer to the HW structure - * - * Performs initial bounds checking on autoneg advertisement parameter, then - * configure to advertise the full capability. Setup the PHY to autoneg - * and restart the negotiation process between the link partner. If - * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. - **/ -s32 igb_copper_link_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_ctrl; - - DEBUGFUNC("igb_copper_link_autoneg"); - - /* - * Perform some bounds checking on the autoneg advertisement - * parameter. - */ - phy->autoneg_advertised &= phy->autoneg_mask; - - /* - * If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (phy->autoneg_advertised == 0) - phy->autoneg_advertised = phy->autoneg_mask; - - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = igb_phy_setup_autoneg(hw); - if (ret_val) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - goto out; - } - DEBUGOUT("Restarting Auto-Neg\n"); - - /* - * Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - /* - * Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (phy->autoneg_wait_to_complete) { - ret_val = hw->mac.ops.wait_autoneg(hw); - if (ret_val) { - DEBUGOUT("Error while waiting for " - "autoneg to complete\n"); - goto out; - } - } - - hw->mac.get_link_status = true; - -out: - return ret_val; -} - -/** - * igb_phy_setup_autoneg - Configure PHY for auto-negotiation - * @hw: pointer to the HW structure - * - * Reads the MII auto-neg advertisement register and/or the 1000T control - * register and if the PHY is already setup for auto-negotiation, then - * return successful. Otherwise, setup advertisement and flow control to - * the appropriate values for the wanted auto-negotiation. - **/ -static s32 igb_phy_setup_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg = 0; - - DEBUGFUNC("igb_phy_setup_autoneg"); - - phy->autoneg_advertised &= phy->autoneg_mask; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if (ret_val) - goto out; - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, - &mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - - /* - * Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* - * 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 &= ~(NWAY_AR_100TX_FD_CAPS | - NWAY_AR_100TX_HD_CAPS | - NWAY_AR_10T_FD_CAPS | - NWAY_AR_10T_HD_CAPS); - mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); - - DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_HALF) { - DEBUGOUT("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_FULL) { - DEBUGOUT("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_HALF) { - DEBUGOUT("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_FULL) { - DEBUGOUT("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) { - DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); - } - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { - DEBUGOUT("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* - * Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- - * negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* - * Flow control (Rx & Tx) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled, and Tx Flow control is - * disabled, by a software over-ride. - * - * Since there really isn't a way to advertise that we are - * capable of Rx Pause ONLY, we will advertise that we - * support both symmetric and asymmetric Rx PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if (ret_val) - goto out; - - DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - ret_val = phy->ops.write_reg(hw, - PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - if (ret_val) - goto out; - } - -out: - return ret_val; -} - -/** - * igb_setup_copper_link_generic - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -s32 igb_setup_copper_link_generic(struct e1000_hw *hw) -{ - s32 ret_val; - bool link; - - DEBUGFUNC("igb_setup_copper_link_generic"); - - if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = igb_copper_link_autoneg(hw); - if (ret_val) - goto out; - } else { -#if 0 - /* - * PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - goto out; - } -#endif - } - - /* - * Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = igb_phy_has_link_generic(hw, - COPPER_LINK_UP_LIMIT, - 10, - &link); - if (ret_val) - goto out; - - if (link) { - DEBUGOUT("Valid link established!!!\n"); - igb_config_collision_dist_generic(hw); - ret_val = igb_config_fc_after_link_up_generic(hw); - } else { - DEBUGOUT("Unable to establish link!!!\n"); - } - -out: - return ret_val; -} - -#if 0 -/** - * igb_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("igb_phy_force_speed_duplex_igp"); - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - igb_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* - * Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - goto out; - - DEBUGOUT1("IGP PSCR: %X\n", phy_data); - - usec_delay(1); - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); - - ret_val = igb_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Link taking longer than expected.\n"); - } - /* Try once more */ - ret_val = igb_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} -#endif - -#if 0 -/** - * igb_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Resets the PHY to commit the - * changes. If time expires while waiting for link up, we reset the DSP. - * After reset, TX_CLK and CRS on Tx must be set. Return successful upon - * successful completion, else return corresponding error code. - **/ -s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("igb_phy_force_speed_duplex_m88"); - - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); - if (ret_val) - goto out; - - igb_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); - if (ret_val) - goto out; - - /* Reset the phy to commit changes. */ - ret_val = hw->phy.ops.commit(hw); - if (ret_val) - goto out; - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); - - ret_val = igb_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - - if (!link) { - /* - * We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = phy->ops.write_reg(hw, - M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - goto out; - ret_val = igb_phy_reset_dsp_generic(hw); - if (ret_val) - goto out; - } - - /* Try once more */ - ret_val = igb_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - goto out; - } - - ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - /* - * Resetting the phy means we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock from - * the reset value of 2.5MHz. - */ - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; - - /* - * In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - -out: - return ret_val; -} -#endif - -#if 0 -/** - * igb_phy_force_speed_duplex_ife - Force PHY speed & duplex - * @hw: pointer to the HW structure - * - * Forces the speed and duplex settings of the PHY. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -s32 igb_phy_force_speed_duplex_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - DEBUGFUNC("igb_phy_force_speed_duplex_ife"); - - if (phy->type != e1000_phy_ife) { - ret_val = igb_phy_force_speed_duplex_igp(hw); - goto out; - } - - ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); - if (ret_val) - goto out; - - igb_phy_force_speed_duplex_setup(hw, &data); - - ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); - if (ret_val) - goto out; - - /* Disable MDI-X support for 10/100 */ - ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - goto out; - - data &= ~IFE_PMC_AUTO_MDIX; - data &= ~IFE_PMC_FORCE_MDIX; - - ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); - if (ret_val) - goto out; - - DEBUGOUT1("IFE PMC: %X\n", data); - - usec_delay(1); - - if (phy->autoneg_wait_to_complete) { - DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); - - ret_val = igb_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Link taking longer than expected.\n"); - } - /* Try once more */ - ret_val = igb_phy_has_link_generic(hw, - PHY_FORCE_LIMIT, - 100000, - &link); - if (ret_val) - goto out; - } - -out: - return ret_val; -} -#endif - -#if 0 -/** - * igb_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex - * @hw: pointer to the HW structure - * @phy_ctrl: pointer to current value of PHY_CONTROL - * - * Forces speed and duplex on the PHY by doing the following: disable flow - * control, force speed/duplex on the MAC, disable auto speed detection, - * disable auto-negotiation, configure duplex, configure speed, configure - * the collision distance, write configuration to CTRL register. The - * caller must write to the PHY_CONTROL register for these settings to - * take affect. - **/ -void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - - DEBUGFUNC("igb_phy_force_speed_duplex_setup"); - - /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; - - /* Force speed/duplex on the mac */ - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~E1000_CTRL_SPD_SEL; - - /* Disable Auto Speed Detection */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Disable autoneg on the phy */ - *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; - - /* Forcing Full or Half Duplex? */ - if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { - ctrl &= ~E1000_CTRL_FD; - *phy_ctrl &= ~MII_CR_FULL_DUPLEX; - DEBUGOUT("Half Duplex\n"); - } else { - ctrl |= E1000_CTRL_FD; - *phy_ctrl |= MII_CR_FULL_DUPLEX; - DEBUGOUT("Full Duplex\n"); - } - - /* Forcing 10mb or 100mb? */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { - ctrl |= E1000_CTRL_SPD_100; - *phy_ctrl |= MII_CR_SPEED_100; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - DEBUGOUT("Forcing 100mb\n"); - } else { - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl |= MII_CR_SPEED_10; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - DEBUGOUT("Forcing 10mb\n"); - } - - igb_config_collision_dist_generic(hw); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); -} -#endif - -/** - * igb_set_d3_lplu_state_generic - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -s32 igb_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 data; - - DEBUGFUNC("igb_set_d3_lplu_state_generic"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - goto out; - - if (!active) { - data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = phy->ops.read_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - goto out; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP02E1000_PM_D3_LPLU; - ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, - data); - if (ret_val) - goto out; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - goto out; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - } - -out: - return ret_val; -} - -/** - * igb_check_downshift_generic - Checks whether a downshift in speed occurred - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns 1 - * - * A downshift is detected by querying the PHY link health. - **/ -s32 igb_check_downshift_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - DEBUGFUNC("igb_check_downshift_generic"); - - switch (phy->type) { - case e1000_phy_m88: - case e1000_phy_gg82563: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; - break; - case e1000_phy_igp_2: - case e1000_phy_igp: - case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; - break; - default: - /* speed downshift not supported */ - phy->speed_downgraded = false; - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = phy->ops.read_reg(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = (phy_data & mask) ? true : false; - -out: - return ret_val; -} - -/** - * igb_check_polarity_m88 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 igb_check_polarity_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - DEBUGFUNC("igb_check_polarity_m88"); - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); - - if (!ret_val) - phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * igb_check_polarity_igp - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY port status register, and the - * current speed (since there is no polarity at 100Mbps). - **/ -s32 igb_check_polarity_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data, offset, mask; - - DEBUGFUNC("igb_check_polarity_igp"); - - /* - * Polarity is determined based on the speed of - * our connection. - */ - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; - } else { - /* - * This really only applies to 10Mbps since - * there is no polarity for 100Mbps (always 0). - */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; - } - - ret_val = phy->ops.read_reg(hw, offset, &data); - - if (!ret_val) - phy->cable_polarity = (data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - -out: - return ret_val; -} - -/** - * igb_check_polarity_ife - Check cable polarity for IFE PHY - * @hw: pointer to the HW structure - * - * Polarity is determined on the polarity reversal feature being enabled. - **/ -s32 igb_check_polarity_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - DEBUGFUNC("igb_check_polarity_ife"); - - /* - * Polarity is determined based on the reversal feature being enabled. - */ - if (phy->polarity_correction) { - offset = IFE_PHY_EXTENDED_STATUS_CONTROL; - mask = IFE_PESC_POLARITY_REVERSED; - } else { - offset = IFE_PHY_SPECIAL_CONTROL; - mask = IFE_PSC_FORCE_POLARITY; - } - - ret_val = phy->ops.read_reg(hw, offset, &phy_data); - - if (!ret_val) - phy->cable_polarity = (phy_data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal; - - return ret_val; -} - -/** - * igb_wait_autoneg_generic - Wait for auto-neg completion - * @hw: pointer to the HW structure - * - * Waits for auto-negotiation to complete or for the auto-negotiation time - * limit to expire, which ever happens first. - **/ -s32 igb_wait_autoneg_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - DEBUGFUNC("igb_wait_autoneg_generic"); - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ - for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_AUTONEG_COMPLETE) - break; - msec_delay(100); - } - - /* - * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation - * has completed. - */ - return ret_val; -} - -/** - * igb_phy_has_link_generic - Polls PHY for link - * @hw: pointer to the HW structure - * @iterations: number of times to poll for link - * @usec_interval: delay between polling attempts - * @success: pointer to whether polling was successful or not - * - * Polls the PHY status register for link, 'iterations' number of times. - **/ -s32 igb_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success) -{ - s32 ret_val = E1000_SUCCESS; - u16 i, phy_status; - - DEBUGFUNC("igb_phy_has_link_generic"); - - if (!(hw->phy.ops.read_reg)) - return E1000_SUCCESS; - - for (i = 0; i < iterations; i++) { - /* - * Some PHYs require the PHY_STATUS register to be read - * twice due to the link bit being sticky. No harm doing - * it across the board. - */ - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) { - /* - * If the first read fails, another entity may have - * ownership of the resources, wait and try again to - * see if they have relinquished the resources yet. - */ - usec_delay(usec_interval); - } - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); - if (ret_val) - break; - if (phy_status & MII_SR_LINK_STATUS) - break; - if (usec_interval >= 1000) - msec_delay_irq(usec_interval/1000); - else - usec_delay(usec_interval); - } - - *success = (i < iterations) ? true : false; - - return ret_val; -} - -#if 0 -/** - * igb_get_cable_length_m88 - Determine cable length for m88 PHY - * @hw: pointer to the HW structure - * - * Reads the PHY specific status register to retrieve the cable length - * information. The cable length is determined by averaging the minimum and - * maximum values to get the "average" cable length. The m88 PHY has four - * possible cable length values, which are: - * Register Value Cable Length - * 0 < 50 meters - * 1 50 - 80 meters - * 2 80 - 110 meters - * 3 110 - 140 meters - * 4 > 140 meters - **/ -s32 igb_get_cable_length_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - DEBUGFUNC("igb_get_cable_length_m88"); - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT; - if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} - -/** - * igb_get_cable_length_igp_2 - Determine cable length for igp2 PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -s32 igb_get_cable_length_igp_2(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u16 phy_data, i, agc_value = 0; - u16 cur_agc_index, max_agc_index = 0; - u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = - {IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D}; - - DEBUGFUNC("igb_get_cable_length_igp_2"); - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); - if (ret_val) - goto out; - - /* - * Getting bits 15:9, which represent the combination of - * coarse and fine gain values. The result is a number - * that can be put into the lookup table to obtain the - * approximate cable length. - */ - cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK; - - /* Array index bound check. */ - if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || - (cur_agc_index == 0)) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - /* Remove min & max AGC values from calculation. */ - if (e1000_igp_2_cable_length_table[min_agc_index] > - e1000_igp_2_cable_length_table[cur_agc_index]) - min_agc_index = cur_agc_index; - if (e1000_igp_2_cable_length_table[max_agc_index] < - e1000_igp_2_cable_length_table[cur_agc_index]) - max_agc_index = cur_agc_index; - - agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; - } - - agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + - e1000_igp_2_cable_length_table[max_agc_index]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* Calculate cable length with the error range of +/- 10 meters. */ - phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0; - phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - -out: - return ret_val; -} -#endif - -/** - * igb_get_phy_info_m88 - Retrieve PHY information - * @hw: pointer to the HW structure - * - * Valid for only copper links. Read the PHY status register (sticky read) - * to verify that link is up. Read the PHY special control register to - * determine the polarity and 10base-T extended distance. Read the PHY - * special status register to determine MDI/MDIx and current speed. If - * speed is 1000, then determine cable length, local and remote receiver. - **/ -s32 igb_get_phy_info_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - DEBUGFUNC("igb_get_phy_info_m88"); - - if (phy->media_type != e1000_media_type_copper) { - DEBUGOUT("Phy info is only valid for copper media\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = igb_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; - - phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) - ? true : false; - - ret_val = igb_check_polarity_m88(hw); - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { -#if 0 - ret_val = hw->phy.ops.get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; -#if 0 - ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - goto out; - - phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; -#endif - } else { - /* Set values to "undefined" */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - -out: - return ret_val; -} - -/** - * igb_get_phy_info_igp - Retrieve igp PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 igb_get_phy_info_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - DEBUGFUNC("igb_get_phy_info_igp"); - - ret_val = igb_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - goto out; - - if (!link) { - DEBUGOUT("Phy info is only valid if link is up\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - phy->polarity_correction = true; - - ret_val = igb_check_polarity_igp(hw); - if (ret_val) - goto out; - - ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - goto out; - - phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { -#if 0 - ret_val = phy->ops.get_cable_length(hw); -#endif - ret_val = -E1000_ERR_CONFIG; - if (ret_val) - goto out; -#if 0 - ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); - if (ret_val) - goto out; - - phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) - ? e1000_1000t_rx_status_ok - : e1000_1000t_rx_status_not_ok; -#endif - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - -out: - return ret_val; -} - -/** - * igb_phy_sw_reset_generic - PHY software reset - * @hw: pointer to the HW structure - * - * Does a software reset of the PHY by reading the PHY control register and - * setting/write the control register reset bit to the PHY. - **/ -s32 igb_phy_sw_reset_generic(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - u16 phy_ctrl; - - DEBUGFUNC("igb_phy_sw_reset_generic"); - - if (!(hw->phy.ops.read_reg)) - goto out; - - ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); - if (ret_val) - goto out; - - phy_ctrl |= MII_CR_RESET; - ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); - if (ret_val) - goto out; - - usec_delay(1); - -out: - return ret_val; -} - -/** - * igb_phy_hw_reset_generic - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -s32 igb_phy_hw_reset_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; - u32 ctrl; - - DEBUGFUNC("igb_phy_hw_reset_generic"); - - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) { - ret_val = E1000_SUCCESS; - goto out; - } - - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - - ctrl = E1000_READ_REG(hw, E1000_CTRL); - E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(hw); - - usec_delay(phy->reset_delay_us); - - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - - usec_delay(150); - - phy->ops.release(hw); - - ret_val = phy->ops.get_cfg_done(hw); - -out: - return ret_val; -} - -/** - * igb_get_cfg_done_generic - Generic configuration done - * @hw: pointer to the HW structure - * - * Generic function to wait 10 milli-seconds for configuration to complete - * and return success. - **/ -s32 igb_get_cfg_done_generic(struct e1000_hw *hw __unused) -{ - DEBUGFUNC("igb_get_cfg_done_generic"); - - msec_delay_irq(10); - - return E1000_SUCCESS; -} - -/** - * igb_phy_init_script_igp3 - Inits the IGP3 PHY - * @hw: pointer to the HW structure - * - * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. - **/ -s32 igb_phy_init_script_igp3(struct e1000_hw *hw) -{ - DEBUGOUT("Running IGP 3 PHY init script\n"); - - /* PHY init IGP 3 */ - /* Enable rise/fall, 10-mode work in class-A */ - hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); - /* Remove all caps from Replica path filter */ - hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); - /* Bias trimming for ADC, AFE and Driver (Default) */ - hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); - /* Increase Hybrid poly bias */ - hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Gig mode */ - hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); - /* Disable trimming (TTT) */ - hw->phy.ops.write_reg(hw, 0x2011, 0x0000); - /* Poly DC correction to 94.6% + 2% for all channels */ - hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); - /* ABS DC correction to 95.9% */ - hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); - /* BG temp curve trim */ - hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); - /* Increasing ADC OPAMP stage 1 currents to max */ - hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); - /* Force 1000 ( required for enabling PHY regs configuration) */ - hw->phy.ops.write_reg(hw, 0x0000, 0x0140); - /* Set upd_freq to 6 */ - hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); - /* Disable NPDFE */ - hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); - /* Disable adaptive fixed FFE (Default) */ - hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); - /* Enable FFE hysteresis */ - hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); - /* Fixed FFE for short cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); - /* Fixed FFE for medium cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); - /* Fixed FFE for long cable lengths */ - hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); - /* Enable Adaptive Clip Threshold */ - hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); - /* AHT reset limit to 1 */ - hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); - /* Set AHT master delay to 127 msec */ - hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); - /* Set scan bits for AHT */ - hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); - /* Set AHT Preset bits */ - hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); - /* Change integ_factor of channel A to 3 */ - hw->phy.ops.write_reg(hw, 0x1895, 0x0003); - /* Change prop_factor of channels BCD to 8 */ - hw->phy.ops.write_reg(hw, 0x1796, 0x0008); - /* Change cg_icount + enable integbp for channels BCD */ - hw->phy.ops.write_reg(hw, 0x1798, 0xD008); - /* - * Change cg_icount + enable integbp + change prop_factor_master - * to 8 for channel A - */ - hw->phy.ops.write_reg(hw, 0x1898, 0xD918); - /* Disable AHT in Slave mode on channel A */ - hw->phy.ops.write_reg(hw, 0x187A, 0x0800); - /* - * Enable LPLU and disable AN to 1000 in non-D0a states, - * Enable SPD+B2B - */ - hw->phy.ops.write_reg(hw, 0x0019, 0x008D); - /* Enable restart AN on an1000_dis change */ - hw->phy.ops.write_reg(hw, 0x001B, 0x2080); - /* Enable wh_fifo read clock in 10/100 modes */ - hw->phy.ops.write_reg(hw, 0x0014, 0x0045); - /* Restart AN, Speed selection is 1000 */ - hw->phy.ops.write_reg(hw, 0x0000, 0x1340); - - return E1000_SUCCESS; -} - -/** - * igb_get_phy_type_from_id - Get PHY type from id - * @phy_id: phy_id read from the phy - * - * Returns the phy type from the id. - **/ -enum e1000_phy_type igb_get_phy_type_from_id(u32 phy_id) -{ - enum e1000_phy_type phy_type = e1000_phy_unknown; - - switch (phy_id) { - case M88E1000_I_PHY_ID: - case M88E1000_E_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1011_I_PHY_ID: - phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ - phy_type = e1000_phy_igp_2; - break; - case GG82563_E_PHY_ID: - phy_type = e1000_phy_gg82563; - break; - case IGP03E1000_E_PHY_ID: - phy_type = e1000_phy_igp_3; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy_type = e1000_phy_ife; - break; - default: - phy_type = e1000_phy_unknown; - break; - } - return phy_type; -} - -/** - * igb_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * addresses. It tests each by reading the PHY ID registers and - * checking for a match. - **/ -s32 igb_determine_phy_address(struct e1000_hw *hw) -{ - s32 ret_val = -E1000_ERR_PHY_TYPE; - u32 phy_addr = 0; - u32 i; - enum e1000_phy_type phy_type = e1000_phy_unknown; - - hw->phy.id = phy_type; - - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - i = 0; - - do { - igb_get_phy_id(hw); - phy_type = igb_get_phy_type_from_id(hw->phy.id); - - /* - * If phy_type is valid, break - we found our - * PHY address - */ - if (phy_type != e1000_phy_unknown) { - ret_val = E1000_SUCCESS; - goto out; - } - msec_delay(1); - i++; - } while (i < 10); - } - -out: - return ret_val; -} - -/** - * igb_power_up_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void igb_power_up_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); - mii_reg &= ~MII_CR_POWER_DOWN; - hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); -} - -/** - * igb_power_down_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void igb_power_down_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); - mii_reg |= MII_CR_POWER_DOWN; - hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); - msec_delay(1); -} diff --git a/roms/ipxe/src/drivers/net/igb/igb_phy.h b/roms/ipxe/src/drivers/net/igb/igb_phy.h deleted file mode 100644 index 8e6bc9917..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_phy.h +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_PHY_H_ -#define _IGB_PHY_H_ - -void igb_init_phy_ops_generic(struct e1000_hw *hw); -s32 igb_check_downshift_generic(struct e1000_hw *hw); -s32 igb_check_polarity_m88(struct e1000_hw *hw); -s32 igb_check_polarity_igp(struct e1000_hw *hw); -s32 igb_check_polarity_ife(struct e1000_hw *hw); -s32 igb_check_reset_block_generic(struct e1000_hw *hw); -s32 igb_copper_link_autoneg(struct e1000_hw *hw); -s32 igb_copper_link_setup_igp(struct e1000_hw *hw); -s32 igb_copper_link_setup_m88(struct e1000_hw *hw); -#if 0 -s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw); -s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw); -s32 igb_phy_force_speed_duplex_ife(struct e1000_hw *hw); -#endif -#if 0 -s32 igb_get_cable_length_m88(struct e1000_hw *hw); -s32 igb_get_cable_length_igp_2(struct e1000_hw *hw); -#endif -s32 igb_get_cfg_done_generic(struct e1000_hw *hw); -s32 igb_get_phy_id(struct e1000_hw *hw); -s32 igb_get_phy_info_igp(struct e1000_hw *hw); -s32 igb_get_phy_info_m88(struct e1000_hw *hw); -s32 igb_phy_sw_reset_generic(struct e1000_hw *hw); -#if 0 -void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -#endif -s32 igb_phy_hw_reset_generic(struct e1000_hw *hw); -s32 igb_phy_reset_dsp_generic(struct e1000_hw *hw); -s32 igb_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); -s32 igb_setup_copper_link_generic(struct e1000_hw *hw); -s32 igb_wait_autoneg_generic(struct e1000_hw *hw); -s32 igb_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_phy_reset_dsp(struct e1000_hw *hw); -s32 igb_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -s32 igb_phy_init_script_igp3(struct e1000_hw *hw); -enum e1000_phy_type igb_get_phy_type_from_id(u32 phy_id); -s32 igb_determine_phy_address(struct e1000_hw *hw); -void igb_power_up_phy_copper(struct e1000_hw *hw); -void igb_power_down_phy_copper(struct e1000_hw *hw); -s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); -s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); -s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); - -#define E1000_MAX_PHY_ADDR 4 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -#define IGP_PAGE_SHIFT 5 -#define PHY_REG_MASK 0x1F - -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ - -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 - -/* Enable flexible speed on link-up */ -#define IGP01E1000_GMII_FLEX_SPD 0x0010 -#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ - -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 - -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 - -#define IGP02E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F -#define IGP02E1000_AGC_RANGE 15 - -#define IGP03E1000_PHY_MISC_CTRL 0x1B -#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ - -#define E1000_CABLE_LENGTH_UNDEFINED 0xFF - -#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KMRNCTRLSTA_REN 0x00200000 -#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ -#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ -#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ - -/* IFE PHY Extended Status Control */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 - -/* IFE PHY Special Control */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -#define IFE_PSC_FORCE_POLARITY 0x0020 -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 - -/* IFE PHY Special Control and LED Control */ -#define IFE_PSCL_PROBE_MODE 0x0020 -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -/* IFE PHY MDIX Control */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */ - -#endif /* _IGB_PHY_H_ */ diff --git a/roms/ipxe/src/drivers/net/igb/igb_regs.h b/roms/ipxe/src/drivers/net/igb/igb_regs.h deleted file mode 100644 index e549675b2..000000000 --- a/roms/ipxe/src/drivers/net/igb/igb_regs.h +++ /dev/null @@ -1,486 +0,0 @@ -/******************************************************************************* - - Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2009 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: - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _IGB_REGS_H_ -#define _IGB_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_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ -#define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) -#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_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ -#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ -#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ -#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_TCPTIMER 0x0104C /* TCP Timer - RW */ -#define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ -#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ -#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ -#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */ -#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ -#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - 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_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ -#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ -#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_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ - (0x0C014 + ((_n) * 0x40))) -#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) -#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_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \ - (0x0C030 + ((_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_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ - (0x0E014 + ((_n) * 0x40))) -#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) -#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_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ - (0x0E038 + ((_n) * 0x40))) -#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ - (0x0E03C + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) -#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_PBSLAC 0x03100 /* Packet Buffer Slave Access Control */ -#define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Packet Buffer DWORD (_n) */ -#define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ -#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_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ -#define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ -#define E1000_DTXMXSZRQ 0x03540 /* DMA Tx Max Total Allow Size Requests - 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_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */ -#define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */ -#define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */ -#define E1000_LSECTXOCTE 0x0430C /* LinkSec Encrypted Tx Octets Count - OutOctetsEncrypted */ -#define E1000_LSECTXOCTP 0x04310 /* LinkSec Protected Tx Octets Count - OutOctetsProtected */ -#define E1000_LSECRXUT 0x04314 /* LinkSec Untagged non-Strict Rx Packet Count - InPktsUntagged/InPktsNoTag */ -#define E1000_LSECRXOCTD 0x0431C /* LinkSec Rx Octets Decrypted Count - InOctetsDecrypted */ -#define E1000_LSECRXOCTV 0x04320 /* LinkSec Rx Octets Validated - InOctetsValidated */ -#define E1000_LSECRXBAD 0x04324 /* LinkSec Rx Bad Tag - InPktsBadTag */ -#define E1000_LSECRXNOSCI 0x04328 /* LinkSec Rx Packet No SCI Count - InPktsNoSci */ -#define E1000_LSECRXUNSCI 0x0432C /* LinkSec Rx Packet Unknown SCI Count - InPktsUnknownSci */ -#define E1000_LSECRXUNCH 0x04330 /* LinkSec Rx Unchecked Packets Count - InPktsUnchecked */ -#define E1000_LSECRXDELAY 0x04340 /* LinkSec Rx Delayed Packet Count - InPktsDelayed */ -#define E1000_LSECRXLATE 0x04350 /* LinkSec Rx Late Packets Count - InPktsLate */ -#define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* LinkSec Rx Packet OK Count - InPktsOk */ -#define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* LinkSec Rx Invalid Count - InPktsInvalid */ -#define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* LinkSec Rx Not Valid Count - InPktsNotValid */ -#define E1000_LSECRXUNSA 0x043C0 /* LinkSec Rx Unused SA Count - InPktsUnusedSa */ -#define E1000_LSECRXNUSA 0x043D0 /* LinkSec Rx Not Using SA Count - InPktsNotUsingSa */ -#define E1000_LSECTXCAP 0x0B000 /* LinkSec Tx Capabilities Register - RO */ -#define E1000_LSECRXCAP 0x0B300 /* LinkSec Rx Capabilities Register - RO */ -#define E1000_LSECTXCTRL 0x0B004 /* LinkSec Tx Control - RW */ -#define E1000_LSECRXCTRL 0x0B304 /* LinkSec Rx Control - RW */ -#define E1000_LSECTXSCL 0x0B008 /* LinkSec Tx SCI Low - RW */ -#define E1000_LSECTXSCH 0x0B00C /* LinkSec Tx SCI High - RW */ -#define E1000_LSECTXSA 0x0B010 /* LinkSec Tx SA0 - RW */ -#define E1000_LSECTXPN0 0x0B018 /* LinkSec Tx SA PN 0 - RW */ -#define E1000_LSECTXPN1 0x0B01C /* LinkSec Tx SA PN 1 - RW */ -#define E1000_LSECRXSCL 0x0B3D0 /* LinkSec Rx SCI Low - RW */ -#define E1000_LSECRXSCH 0x0B3E0 /* LinkSec Rx SCI High - RW */ -#define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 0 - WO */ -#define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */ -#define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ -#define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* LinkSec Rx SAs - RW */ -/* - * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit - * key - RW. - */ -#define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) - -#define E1000_SSVPC 0x041A0 /* Switch Security Violation Packet Count */ -#define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ -#define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ -#define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ -#define E1000_IPSRXIPADDR(_n) (0x0B420+ (0x04 * (_n))) /* IPSec Rx IPv4/v6 Address - RW */ -#define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */ -#define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ -#define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ -#define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) /* IPSec Tx 128-bit Key - RW */ -#define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ -#define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ -#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_RA2 0x054E0 /* 2nd half of receive address array - 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_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flexible Host Filter Table */ -#define E1000_FHFT_EXT(_n) (0x09A00 + (_n * 0x100)) /* Ext Flexible Host Filter Table */ - - -#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 */ -/* VT Registers */ -#define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ -#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ -#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ -#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ -#define E1000_VFRE 0x00C8C /* VF Receive Enables */ -#define E1000_VFTE 0x00C90 /* VF Transmit Enables */ -#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ -#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ -#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ -#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ -#define E1000_IOVTCL 0x05BBC /* IOV Control Register */ -#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ -/* These act per VF so an array friendly macro is used */ -#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) -#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) -#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) -#define E1000_VFVMBMEM(_n) (0x00800 + (_n)) -#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) -#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine - * Filter - RW */ -/* Time Sync */ -#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ -#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ -#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ -#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ -#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ -#define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */ -#define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */ -#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ -#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ -#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ -#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ -#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ - -/* Filtering Registers */ -#define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ -#define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ -#define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ -#define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ -#define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */ -#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ -#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ - -#define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ -#define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ -#define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ -#define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ -#define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ -#define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Desc plane TC Rate-scheduler config */ -#define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */ -#define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */ -#define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */ -#define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */ -#define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */ -#define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */ -#define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */ -#define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */ -#define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/ -#define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */ -#define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ -#define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ -#define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ -#define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ -#define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ -#define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ -#define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ -#define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ -#define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ -#define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ -#define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ -#define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ -#define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ -#define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ - -#endif /* _IGB_REGS_H_ */ diff --git a/roms/ipxe/src/drivers/net/igbvf/igbvf_main.c b/roms/ipxe/src/drivers/net/igbvf/igbvf_main.c index 1f7e1dfd9..cd189ecb0 100644 --- a/roms/ipxe/src/drivers/net/igbvf/igbvf_main.c +++ b/roms/ipxe/src/drivers/net/igbvf/igbvf_main.c @@ -942,7 +942,8 @@ void igbvf_remove ( struct pci_device *pdev ) } static struct pci_device_id igbvf_pci_tbl[] = { - PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0) + PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0), + PCI_ROM(0x8086, 0x1520, "i350vf", "E1000_DEV_ID_I350_VF", 0), }; diff --git a/roms/ipxe/src/drivers/net/igbvf/igbvf_vf.h b/roms/ipxe/src/drivers/net/igbvf/igbvf_vf.h index ce8ad796c..8d8963fea 100644 --- a/roms/ipxe/src/drivers/net/igbvf/igbvf_vf.h +++ b/roms/ipxe/src/drivers/net/igbvf/igbvf_vf.h @@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_ONLY ); 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 */ diff --git a/roms/ipxe/src/drivers/net/intel.c b/roms/ipxe/src/drivers/net/intel.c new file mode 100644 index 000000000..ce17e9f2d --- /dev/null +++ b/roms/ipxe/src/drivers/net/intel.c @@ -0,0 +1,959 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + uint32_t dctl; + + /* 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 ) ); + + /* Enable ring */ + dctl = readl ( intel->regs + ring->reg + INTEL_xDCTL ); + dctl |= INTEL_xDCTL_ENABLE; + writel ( dctl, intel->regs + ring->reg + INTEL_xDCTL ); + + 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; + + /* 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 ); + + /* Fill receive ring */ + intel_refill_rx ( intel ); + + /* 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 completions, if applicable */ + if ( icr & ( INTEL_IRQ_RXT0 | INTEL_IRQ_RXO ) ) + intel_poll_rx ( netdev ); + + /* Report receive overruns */ + if ( icr & INTEL_IRQ_RXO ) + netdev_rx_err ( netdev, NULL, -ENOBUFS ); + + /* 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: + iounmap ( intel->regs ); + 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 */ + iounmap ( intel->regs ); + 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, 0x1533, "i210", "I210", 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/roms/ipxe/src/drivers/net/intel.h b/roms/ipxe/src/drivers/net/intel.h new file mode 100644 index 000000000..e9e9052b8 --- /dev/null +++ b/roms/ipxe/src/drivers/net/intel.h @@ -0,0 +1,257 @@ +#ifndef _INTEL_H +#define _INTEL_H + +/** @file + * + * Intel 10/100/1000 network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include + +/** 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 */ +#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */ + +/** 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/Transmit Descriptor Control (offset) */ +#define INTEL_xDCTL 0x28 +#define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */ + +/** 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/roms/ipxe/src/drivers/net/ipoib.c b/roms/ipxe/src/drivers/net/ipoib.c index 4917b58e8..c1b8cad9a 100644 --- a/roms/ipxe/src/drivers/net/ipoib.c +++ b/roms/ipxe/src/drivers/net/ipoib.c @@ -13,24 +13,30 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include #include #include #include +#include #include +#include +#include #include #include #include #include #include +#include #include /** @file @@ -57,6 +63,8 @@ struct ipoib_device { struct ib_completion_queue *cq; /** Queue pair */ struct ib_queue_pair *qp; + /** Local MAC */ + struct ipoib_mac mac; /** Broadcast MAC */ struct ipoib_mac broadcast; /** Joined to IPv4 broadcast multicast group @@ -67,6 +75,8 @@ struct ipoib_device { int broadcast_joined; /** IPv4 broadcast multicast group membership */ struct ib_mc_membership broadcast_membership; + /** REMAC cache */ + struct list_head peers; }; /** Broadcast IPoIB address */ @@ -88,176 +98,140 @@ struct errortab ipoib_errors[] __errortab = { /**************************************************************************** * - * IPoIB peer cache + * IPoIB REMAC 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. - */ +/** An IPoIB REMAC cache entry */ struct ipoib_peer { - /** Key */ - uint8_t key; + /** List of REMAC cache entries */ + struct list_head list; + /** Remote Ethermet MAC */ + struct ipoib_remac remac; /** 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 = 1; - /** - * Look up cached peer by key + * Find IPoIB MAC from REMAC * - * @v key Peer cache key - * @ret peer Peer cache entry, or NULL + * @v ipoib IPoIB device + * @v remac Remote Ethernet MAC + * @ret mac IPoIB MAC (or NULL if not found) */ -static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) { +static struct ipoib_mac * ipoib_find_remac ( struct ipoib_device *ipoib, + const struct ipoib_remac *remac ) { struct ipoib_peer *peer; - unsigned int i; - for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) { - peer = &ipoib_peer_cache[i]; - if ( peer->key == key ) - return peer; + /* Check for broadcast REMAC */ + if ( is_broadcast_ether_addr ( remac ) ) + return &ipoib->broadcast; + + /* Try to find via REMAC cache */ + list_for_each_entry ( peer, &ipoib->peers, list ) { + if ( memcmp ( remac, &peer->remac, + sizeof ( peer->remac ) ) == 0 ) { + /* Move peer to start of list */ + list_del ( &peer->list ); + list_add ( &peer->list, &ipoib->peers ); + return &peer->mac; + } } - if ( key != 0 ) { - DBG ( "IPoIB warning: peer cache lost track of key %x while " - "still in use\n", key ); - } + DBGC ( ipoib, "IPoIB %p unknown REMAC %s\n", + ipoib, eth_ntoa ( remac ) ); return NULL; } /** - * Store GID and QPN in peer cache + * Add IPoIB MAC to REMAC cache * - * @v mac Peer MAC address - * @ret peer Peer cache entry + * @v ipoib IPoIB device + * @v remac Remote Ethernet MAC + * @v mac IPoIB MAC + * @ret rc Return status code */ -static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) { +static int ipoib_map_remac ( struct ipoib_device *ipoib, + const struct ipoib_remac *remac, + const struct ipoib_mac *mac ) { struct ipoib_peer *peer; - unsigned int 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; + /* Check for existing entry in REMAC cache */ + list_for_each_entry ( peer, &ipoib->peers, list ) { + if ( memcmp ( remac, &peer->remac, + sizeof ( peer->remac ) ) == 0 ) { + /* Move peer to start of list */ + list_del ( &peer->list ); + list_add ( &peer->list, &ipoib->peers ); + /* Update MAC */ + memcpy ( &peer->mac, mac, sizeof ( peer->mac ) ); + return 0; + } } - /* No entry found: create a new one */ - key = ipoib_peer_cache_idx++; - 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; + /* Create new entry */ + peer = malloc ( sizeof ( *peer ) ); + if ( ! peer ) + return -ENOMEM; + memcpy ( &peer->remac, remac, sizeof ( peer->remac ) ); memcpy ( &peer->mac, mac, sizeof ( peer->mac ) ); - DBG ( "IPoIB peer %x has MAC %s\n", - peer->key, ipoib_ntoa ( &peer->mac ) ); - return peer; -} + list_add ( &peer->list, &ipoib->peers ); -/**************************************************************************** - * - * IPoIB link layer - * - **************************************************************************** - */ + return 0; +} /** - * Add IPoIB link-layer header + * Flush REMAC cache * - * @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 + * @v ipoib IPoIB device */ -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; +static void ipoib_flush_remac ( struct ipoib_device *ipoib ) { + struct ipoib_peer *peer; + struct ipoib_peer *tmp; - return 0; + list_for_each_entry_safe ( peer, tmp, &ipoib->peers, list ) { + list_del ( &peer->list ); + free ( peer ); + } } /** - * Remove IPoIB link-layer header + * Discard some entries from the REMAC cache * - * @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 rc Return status code + * @ret discarded Number of cached items discarded */ -static int ipoib_pull ( struct net_device *netdev, - struct io_buffer *iobuf, const void **ll_dest, - const void **ll_source, uint16_t *net_proto ) { - 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; +static unsigned int ipoib_discard_remac ( void ) { + struct ib_device *ibdev; + struct ipoib_device *ipoib; + struct ipoib_peer *peer; + unsigned int discarded = 0; + + /* Try to discard one cache entry for each IPoIB device */ + for_each_ibdev ( ibdev ) { + ipoib = ib_get_ownerdata ( ibdev ); + list_for_each_entry_reverse ( peer, &ipoib->peers, list ) { + list_del ( &peer->list ); + free ( peer ); + discarded++; + break; + } } - /* 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; + return discarded; +} - /* Fill in required fields */ - *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast ); - *ll_source = ( source ? &source->mac : &ipoib->broadcast ); - *net_proto = ipoib_hdr->proto; +/** IPoIB cache discarder */ +struct cache_discarder ipoib_discarder __cache_discarder ( CACHE_NORMAL ) = { + .discard = ipoib_discard_remac, +}; - return 0; -} +/**************************************************************************** + * + * IPoIB link layer + * + **************************************************************************** + */ /** * Initialise IPoIB link-layer address @@ -266,133 +240,205 @@ static int ipoib_pull ( struct net_device *netdev, * @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; + const uint8_t *guid = hw_addr; + uint8_t *eth_addr = ll_addr; + uint8_t guid_mask = IPOIB_GUID_MASK; + unsigned int i; - memset ( mac, 0, sizeof ( *mac ) ); - memcpy ( &mac->gid.s.guid, guid, sizeof ( mac->gid.s.guid ) ); + /* Extract bytes from GUID according to mask */ + for ( i = 0 ; i < 8 ; i++, guid++, guid_mask <<= 1 ) { + if ( guid_mask & 0x80 ) + *(eth_addr++) = *guid; + } } +/** IPoIB protocol */ +struct ll_protocol ipoib_protocol __ll_protocol = { + .name = "IPoIB", + .ll_proto = htons ( ARPHRD_ETHER ), + .hw_addr_len = sizeof ( union ib_guid ), + .ll_addr_len = ETH_ALEN, + .ll_header_len = ETH_HLEN, + .push = eth_push, + .pull = eth_pull, + .init_addr = ipoib_init_addr, + .ntoa = eth_ntoa, + .mc_hash = eth_mc_hash, + .eth_addr = eth_eth_addr, + .flags = LL_NAME_ONLY, +}; + /** - * Transcribe IPoIB link-layer address + * Allocate IPoIB device * - * @v ll_addr Link-layer address - * @ret string Link-layer address in human-readable format + * @v priv_size Size of driver private data + * @ret netdev Network device, or NULL */ -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; +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 = eth_broadcast; + netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE; + } + return netdev; } +/**************************************************************************** + * + * IPoIB translation layer + * + **************************************************************************** + */ + /** - * Hash multicast address + * Translate transmitted ARP packet * - * @v af Address family - * @v net_addr Network-layer address - * @v ll_addr Link-layer address to fill in + * @v netdev Network device + * @v iobuf Packet to be transmitted (with no link-layer headers) * @ret rc Return status code */ -static int ipoib_mc_hash ( unsigned int af __unused, - const void *net_addr __unused, - void *ll_addr __unused ) { +static int ipoib_translate_tx_arp ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct ipoib_device *ipoib = netdev->priv; + struct arphdr *arphdr = iobuf->data; + struct ipoib_mac *target_ha = NULL; + void *sender_pa; + void *target_pa; + + /* Do nothing unless ARP contains eIPoIB link-layer addresses */ + if ( arphdr->ar_hln != ETH_ALEN ) + return 0; + + /* Fail unless we have room to expand packet */ + if ( iob_tailroom ( iobuf ) < ( 2 * ( sizeof ( ipoib->mac ) - + ETH_ALEN ) ) ) { + DBGC ( ipoib, "IPoIB %p insufficient space in TX ARP\n", + ipoib ); + return -ENOBUFS; + } + + /* Look up REMAC, if applicable */ + if ( arphdr->ar_op == ARPOP_REPLY ) { + target_ha = ipoib_find_remac ( ipoib, arp_target_pa ( arphdr )); + if ( ! target_ha ) + return -ENXIO; + } + + /* Construct new packet */ + iob_put ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) ); + sender_pa = arp_sender_pa ( arphdr ); + target_pa = arp_target_pa ( arphdr ); + arphdr->ar_hrd = htons ( ARPHRD_INFINIBAND ); + arphdr->ar_hln = sizeof ( ipoib->mac ); + memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln ); + memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln ); + memcpy ( arp_sender_ha ( arphdr ), &ipoib->mac, sizeof ( ipoib->mac ) ); + memset ( arp_target_ha ( arphdr ), 0, sizeof ( ipoib->mac ) ); + if ( target_ha ) { + memcpy ( arp_target_ha ( arphdr ), target_ha, + sizeof ( *target_ha ) ); + } - return -ENOTSUP; + return 0; } /** - * Generate Mellanox Ethernet-compatible compressed link-layer address + * Translate transmitted packet * - * @v ll_addr Link-layer address - * @v eth_addr Ethernet-compatible address to fill in + * @v netdev Network device + * @v iobuf Packet to be transmitted (with no link-layer headers) + * @v net_proto Network-layer protocol (in network byte order) + * @ret rc Return status code */ -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; +static int ipoib_translate_tx ( struct net_device *netdev, + struct io_buffer *iobuf, uint16_t net_proto ) { + + switch ( net_proto ) { + case htons ( ETH_P_ARP ) : + return ipoib_translate_tx_arp ( netdev, iobuf ); + case htons ( ETH_P_IP ) : + /* No translation needed */ + return 0; + default: + /* Cannot handle other traffic via eIPoIB */ + return -ENOTSUP; + } } -/** 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 + * Translate received ARP packet * - * @v ll_addr Link-layer address - * @v eth_addr Ethernet-compatible address to fill in + * @v netdev Network device + * @v iobuf Received packet (with no link-layer headers) + * @v remac Constructed Remote Ethernet MAC + * @ret rc Return status code */ -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; +static int ipoib_translate_rx_arp ( struct net_device *netdev, + struct io_buffer *iobuf, + struct ipoib_remac *remac ) { + struct ipoib_device *ipoib = netdev->priv; + struct arphdr *arphdr = iobuf->data; + void *sender_pa; + void *target_pa; + int rc; - 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 ); - } + /* Do nothing unless ARP contains IPoIB link-layer addresses */ + if ( arphdr->ar_hln != sizeof ( ipoib->mac ) ) + return 0; + + /* Create REMAC cache entry */ + if ( ( rc = ipoib_map_remac ( ipoib, remac, + arp_sender_ha ( arphdr ) ) ) != 0 ) { + DBGC ( ipoib, "IPoIB %p could not map REMAC: %s\n", + ipoib, strerror ( rc ) ); + return rc; } - 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, -}; + /* Construct new packet */ + sender_pa = arp_sender_pa ( arphdr ); + target_pa = arp_target_pa ( arphdr ); + arphdr->ar_hrd = htons ( ARPHRD_ETHER ); + arphdr->ar_hln = ETH_ALEN; + memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln ); + memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln ); + memcpy ( arp_sender_ha ( arphdr ), remac, ETH_ALEN ); + memset ( arp_target_ha ( arphdr ), 0, ETH_ALEN ); + if ( arphdr->ar_op == ARPOP_REPLY ) { + /* Assume received replies were directed to us */ + memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, ETH_ALEN ); + } + iob_unput ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) ); + + return 0; +} /** - * Allocate IPoIB device + * Translate received packet * - * @v priv_size Size of driver private data - * @ret netdev Network device, or NULL + * @v netdev Network device + * @v iobuf Received packet (with no link-layer headers) + * @v remac Constructed Remote Ethernet MAC + * @v net_proto Network-layer protocol (in network byte order) + * @ret rc Return status code */ -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; +static int ipoib_translate_rx ( struct net_device *netdev, + struct io_buffer *iobuf, + struct ipoib_remac *remac, + uint16_t net_proto ) { + + switch ( net_proto ) { + case htons ( ETH_P_ARP ) : + return ipoib_translate_rx_arp ( netdev, iobuf, remac ); + case htons ( ETH_P_IP ) : + /* No translation needed */ + return 0; + default: + /* Cannot handle other traffic via eIPoIB */ + return -ENOTSUP; } - return netdev; } /**************************************************************************** @@ -413,17 +459,18 @@ 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 ethhdr *ethhdr; struct ipoib_hdr *ipoib_hdr; - struct ipoib_peer *dest; - struct ib_address_vector av; + struct ipoib_mac *mac; + struct ib_address_vector dest; + uint16_t net_proto; int rc; /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) { + if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) { 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. @@ -431,23 +478,36 @@ static int ipoib_transmit ( struct net_device *netdev, if ( ! ib_link_ok ( ibdev ) ) return -ENETUNREACH; + /* Strip eIPoIB header */ + ethhdr = iobuf->data; + net_proto = ethhdr->h_protocol; + iob_pull ( iobuf, sizeof ( *ethhdr ) ); + /* Identify destination address */ - dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest ); - if ( ! dest ) + mac = ipoib_find_remac ( ipoib, ( ( void *) ethhdr->h_dest ) ); + if ( ! mac ) return -ENXIO; - ipoib_hdr->u.reserved = 0; + + /* Translate packet if applicable */ + if ( ( rc = ipoib_translate_tx ( netdev, iobuf, net_proto ) ) != 0 ) + return rc; + + /* Prepend real IPoIB header */ + ipoib_hdr = iob_push ( iobuf, sizeof ( *ipoib_hdr ) ); + ipoib_hdr->proto = net_proto; + ipoib_hdr->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 ) { + memset ( &dest, 0, sizeof ( dest ) ); + dest.qpn = ( ntohl ( mac->flags__qpn ) & IB_QPN_MASK ); + dest.gid_present = 1; + memcpy ( &dest.gid, &mac->gid, sizeof ( dest.gid ) ); + if ( ( rc = ib_resolve_path ( ibdev, &dest ) ) != 0 ) { /* Path not resolved yet */ return rc; } - return ib_post_send ( ibdev, ipoib->qp, &av, iobuf ); + return ib_post_send ( ibdev, ipoib->qp, &dest, iobuf ); } /** @@ -471,19 +531,22 @@ static void ipoib_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v dest Destination address vector, or NULL + * @v source Source 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 ib_address_vector *dest, + struct ib_address_vector *source, 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; + struct ethhdr *ethhdr; + struct ipoib_remac remac; + uint16_t net_proto; /* Record errors */ if ( rc != 0 ) { @@ -499,20 +562,44 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, netdev_rx_err ( netdev, iobuf, -EIO ); return; } - ipoib_hdr = iobuf->data; - if ( ! av ) { + if ( ! source ) { 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; + /* Strip real IPoIB header */ + ipoib_hdr = iobuf->data; + net_proto = ipoib_hdr->proto; + iob_pull ( iobuf, sizeof ( *ipoib_hdr ) ); + + /* Construct source address from remote QPN and LID */ + remac.qpn = htonl ( source->qpn | EIPOIB_QPN_LA ); + remac.lid = htons ( source->lid ); + + /* Translate packet if applicable */ + if ( ( rc = ipoib_translate_rx ( netdev, iobuf, &remac, + net_proto ) ) != 0 ) { + netdev_rx_err ( netdev, iobuf, rc ); + return; + } + + /* Prepend eIPoIB header */ + ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) ); + memcpy ( ðhdr->h_source, &remac, sizeof ( ethhdr->h_source ) ); + ethhdr->h_protocol = net_proto; + + /* Construct destination address */ + if ( dest->gid_present && ( memcmp ( &dest->gid, &ipoib->broadcast.gid, + sizeof ( dest->gid ) ) == 0 ) ) { + /* Broadcast GID; use the Ethernet broadcast address */ + memcpy ( ðhdr->h_dest, eth_broadcast, + sizeof ( ethhdr->h_dest ) ); + } else { + /* Assume destination address is local Ethernet MAC */ + memcpy ( ðhdr->h_dest, netdev->ll_addr, + sizeof ( ethhdr->h_dest ) ); } /* Hand off to network layer */ @@ -525,6 +612,42 @@ static struct ib_completion_queue_operations ipoib_cq_op = { .complete_recv = ipoib_complete_recv, }; +/** + * Allocate IPoIB receive I/O buffer + * + * @v len Length of buffer + * @ret iobuf I/O buffer, or NULL + * + * Some Infiniband hardware requires 2kB alignment of receive buffers + * and provides no way to disable header separation. The result is + * that there are only four bytes of link-layer header (the real IPoIB + * header) before the payload. This is not sufficient space to insert + * an eIPoIB link-layer pseudo-header. + * + * We therefore allocate I/O buffers offset to start slightly before + * the natural alignment boundary, in order to allow sufficient space. + */ +static struct io_buffer * ipoib_alloc_iob ( size_t len ) { + struct io_buffer *iobuf; + size_t reserve_len; + + /* Calculate additional length required at start of buffer */ + reserve_len = ( sizeof ( struct ethhdr ) - + sizeof ( struct ipoib_hdr ) ); + + /* Allocate buffer */ + iobuf = alloc_iob_raw ( ( len + reserve_len ), len, -reserve_len ); + if ( iobuf ) { + iob_reserve ( iobuf, reserve_len ); + } + return iobuf; +} + +/** IPoIB queue pair operations */ +static struct ib_queue_pair_operations ipoib_qp_op = { + .alloc_iob = ipoib_alloc_iob, +}; + /** * Poll IPoIB network device * @@ -534,7 +657,11 @@ static void ipoib_poll ( struct net_device *netdev ) { struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; + /* Poll Infiniband device */ ib_poll_eq ( ibdev ); + + /* Poll the retry timers (required for IPoIB multicast join) */ + retry_poll(); } /** @@ -601,15 +728,14 @@ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) { 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 ) ); + memcpy ( &ipoib->mac.gid.s.prefix, &ibdev->gid.s.prefix, + sizeof ( ipoib->mac.gid.s.prefix ) ); /* Update broadcast GID based on potentially-new partition key */ ipoib->broadcast.gid.words[2] = @@ -638,7 +764,6 @@ static void ipoib_link_state_changed ( struct ib_device *ibdev ) { 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 */ @@ -658,9 +783,9 @@ static int ipoib_open ( struct net_device *netdev ) { } /* Allocate queue pair */ - ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, - IPOIB_NUM_SEND_WQES, ipoib->cq, - IPOIB_NUM_RECV_WQES, ipoib->cq ); + ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, IPOIB_NUM_SEND_WQES, + ipoib->cq, IPOIB_NUM_RECV_WQES, ipoib->cq, + &ipoib_qp_op ); if ( ! ipoib->qp ) { DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n", ipoib ); @@ -670,7 +795,7 @@ static int ipoib_open ( struct net_device *netdev ) { ib_qp_set_ownerdata ( ipoib->qp, ipoib ); /* Update MAC address with QPN */ - mac->flags__qpn = htonl ( ipoib->qp->qpn ); + ipoib->mac.flags__qpn = htonl ( ipoib->qp->qpn ); /* Fill receive rings */ ib_refill_recv ( ibdev, ipoib->qp ); @@ -697,13 +822,15 @@ static int ipoib_open ( struct net_device *netdev ) { 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 ); + + /* Flush REMAC cache */ + ipoib_flush_remac ( ipoib ); /* Leave broadcast group */ ipoib_leave_broadcast_group ( ipoib ); /* Remove QPN from MAC address */ - mac->flags__qpn = 0; + ipoib->mac.flags__qpn = 0; /* Tear down the queues */ ib_destroy_qp ( ibdev, ipoib->qp ); @@ -743,15 +870,19 @@ static int ipoib_probe ( struct ib_device *ibdev ) { memset ( ipoib, 0, sizeof ( *ipoib ) ); ipoib->netdev = netdev; ipoib->ibdev = ibdev; + INIT_LIST_HEAD ( &ipoib->peers ); /* Extract hardware address */ memcpy ( netdev->hw_addr, &ibdev->gid.s.guid, sizeof ( ibdev->gid.s.guid ) ); - /* Set default broadcast address */ + /* Set local MAC address */ + memcpy ( &ipoib->mac.gid.s.guid, &ibdev->gid.s.guid, + sizeof ( ipoib->mac.gid.s.guid ) ); + + /* Set default broadcast MAC 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 ) diff --git a/roms/ipxe/src/drivers/net/jme.c b/roms/ipxe/src/drivers/net/jme.c index 545402650..29694b699 100644 --- a/roms/ipxe/src/drivers/net/jme.c +++ b/roms/ipxe/src/drivers/net/jme.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/jme.h b/roms/ipxe/src/drivers/net/jme.h index 7e2254309..42db01ed3 100644 --- a/roms/ipxe/src/drivers/net/jme.h +++ b/roms/ipxe/src/drivers/net/jme.h @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/mii.c b/roms/ipxe/src/drivers/net/mii.c new file mode 100644 index 000000000..c4d32514d --- /dev/null +++ b/roms/ipxe/src/drivers/net/mii.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include + +/** @file + * + * Media Independent Interface + * + */ + +/** + * Restart autonegotiation + * + * @v mii MII interface + * @ret rc Return status code + */ +int mii_restart ( struct mii_interface *mii ) { + int bmcr; + int rc; + + /* Read BMCR */ + 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; + } + + /* Enable and restart autonegotiation */ + bmcr |= ( BMCR_ANENABLE | BMCR_ANRESTART ); + if ( ( rc = mii_write ( mii, MII_BMCR, bmcr ) ) != 0 ) { + DBGC ( mii, "MII %p could not write BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + DBGC ( mii, "MII %p restarted autonegotiation\n", mii ); + return 0; +} + +/** + * 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_restart ( mii ) ) != 0 ) + 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/roms/ipxe/src/drivers/net/mtd80x.c b/roms/ipxe/src/drivers/net/mtd80x.c deleted file mode 100644 index 170b5c524..000000000 --- a/roms/ipxe/src/drivers/net/mtd80x.c +++ /dev/null @@ -1,1022 +0,0 @@ -/************************************************************************** -* -* mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip. -* Written 2004-2004 by Erdem Güven -* -* This program is free software; you can redistribute it and/or modify -* 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: -* fealnx.c: A Linux device driver for the mtd80x Ethernet chip -* Written 1998-2000 by Donald Becker -* -***************************************************************************/ - -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 -#include -#include - -/* 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 get_unaligned(ptr) (*(ptr)) - - -/* Operational parameters that are set at compile time. */ - -/* Keep the ring sizes a power of two for compile efficiency. */ -/* The compiler will convert '%'<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 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 HZ 100 -#define TX_TIME_OUT (6*HZ) - -/* Allocation size of Rx buffers with normal sized Ethernet frames. - Do not change this value without good reason. This is not a limit, - but a way to keep a consistent allocation size among drivers. - */ -#define PKT_BUF_SZ 1536 - -/* for different PHY */ -enum phy_type_flags { - MysonPHY = 1, - AhdocPHY = 2, - SeeqPHY = 3, - MarvellPHY = 4, - Myson981 = 5, - LevelOnePHY = 6, - OtherPHY = 10, -}; - -/* A chip capabilities table*/ -enum chip_capability_flags { - HAS_MII_XCVR, - HAS_CHIP_XCVR, -}; - -#if 0 /* not used */ -static -struct chip_info -{ - u16 dev_id; - int flag; -} -mtd80x_chips[] = { - {0x0800, HAS_MII_XCVR}, - {0x0803, HAS_CHIP_XCVR}, - {0x0891, HAS_MII_XCVR} - }; -static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info ); -#endif - -/* Offsets to the Command and Status Registers. */ -enum mtd_offsets { - PAR0 = 0x0, /* physical address 0-3 */ - PAR1 = 0x04, /* physical address 4-5 */ - MAR0 = 0x08, /* multicast address 0-3 */ - MAR1 = 0x0C, /* multicast address 4-7 */ - FAR0 = 0x10, /* flow-control address 0-3 */ - FAR1 = 0x14, /* flow-control address 4-5 */ - TCRRCR = 0x18, /* receive & transmit configuration */ - BCR = 0x1C, /* bus command */ - TXPDR = 0x20, /* transmit polling demand */ - RXPDR = 0x24, /* receive polling demand */ - RXCWP = 0x28, /* receive current word pointer */ - TXLBA = 0x2C, /* transmit list base address */ - RXLBA = 0x30, /* receive list base address */ - ISR = 0x34, /* interrupt status */ - IMR = 0x38, /* interrupt mask */ - FTH = 0x3C, /* flow control high/low threshold */ - MANAGEMENT = 0x40, /* bootrom/eeprom and mii management */ - TALLY = 0x44, /* tally counters for crc and mpa */ - TSR = 0x48, /* tally counter for transmit status */ - BMCRSR = 0x4c, /* basic mode control and status */ - PHYIDENTIFIER = 0x50, /* phy identifier */ - ANARANLPAR = 0x54, /* auto-negotiation advertisement and link - partner ability */ - ANEROCR = 0x58, /* auto-negotiation expansion and pci conf. */ - BPREMRPSR = 0x5c, /* bypass & receive error mask and phy status */ -}; - -/* Bits in the interrupt status/enable registers. */ -/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */ -enum intr_status_bits { - RFCON = 0x00020000, /* receive flow control xon packet */ - RFCOFF = 0x00010000, /* receive flow control xoff packet */ - LSCStatus = 0x00008000, /* link status change */ - ANCStatus = 0x00004000, /* autonegotiation completed */ - FBE = 0x00002000, /* fatal bus error */ - FBEMask = 0x00001800, /* mask bit12-11 */ - ParityErr = 0x00000000, /* parity error */ - TargetErr = 0x00001000, /* target abort */ - MasterErr = 0x00000800, /* master error */ - TUNF = 0x00000400, /* transmit underflow */ - ROVF = 0x00000200, /* receive overflow */ - ETI = 0x00000100, /* transmit early int */ - ERI = 0x00000080, /* receive early int */ - CNTOVF = 0x00000040, /* counter overflow */ - RBU = 0x00000020, /* receive buffer unavailable */ - TBU = 0x00000010, /* transmit buffer unavilable */ - TI = 0x00000008, /* transmit interrupt */ - RI = 0x00000004, /* receive interrupt */ - RxErr = 0x00000002, /* receive error */ -}; - -/* Bits in the NetworkConfig register. */ -enum rx_mode_bits { - RxModeMask = 0xe0, - AcceptAllPhys = 0x80, /* promiscuous mode */ - AcceptBroadcast = 0x40, /* accept broadcast */ - AcceptMulticast = 0x20, /* accept mutlicast */ - AcceptRunt = 0x08, /* receive runt pkt */ - ALP = 0x04, /* receive long pkt */ - AcceptErr = 0x02, /* receive error pkt */ - - AcceptMyPhys = 0x00000000, - RxEnable = 0x00000001, - RxFlowCtrl = 0x00002000, - TxEnable = 0x00040000, - TxModeFDX = 0x00100000, - TxThreshold = 0x00e00000, - - PS1000 = 0x00010000, - PS10 = 0x00080000, - FD = 0x00100000, -}; - -/* Bits in network_desc.status */ -enum rx_desc_status_bits { - RXOWN = 0x80000000, /* own bit */ - FLNGMASK = 0x0fff0000, /* frame length */ - FLNGShift = 16, - MARSTATUS = 0x00004000, /* multicast address received */ - BARSTATUS = 0x00002000, /* broadcast address received */ - PHYSTATUS = 0x00001000, /* physical address received */ - RXFSD = 0x00000800, /* first descriptor */ - RXLSD = 0x00000400, /* last descriptor */ - ErrorSummary = 0x80, /* error summary */ - RUNT = 0x40, /* runt packet received */ - LONG = 0x20, /* long packet received */ - FAE = 0x10, /* frame align error */ - CRC = 0x08, /* crc error */ - RXER = 0x04, /* receive error */ -}; - -enum rx_desc_control_bits { - RXIC = 0x00800000, /* interrupt control */ - RBSShift = 0, -}; - -enum tx_desc_status_bits { - TXOWN = 0x80000000, /* own bit */ - JABTO = 0x00004000, /* jabber timeout */ - CSL = 0x00002000, /* carrier sense lost */ - LC = 0x00001000, /* late collision */ - EC = 0x00000800, /* excessive collision */ - UDF = 0x00000400, /* fifo underflow */ - DFR = 0x00000200, /* deferred */ - HF = 0x00000100, /* heartbeat fail */ - NCRMask = 0x000000ff, /* collision retry count */ - NCRShift = 0, -}; - -enum tx_desc_control_bits { - TXIC = 0x80000000, /* interrupt control */ - ETIControl = 0x40000000, /* early transmit interrupt */ - TXLD = 0x20000000, /* last descriptor */ - TXFD = 0x10000000, /* first descriptor */ - CRCEnable = 0x08000000, /* crc control */ - PADEnable = 0x04000000, /* padding control */ - RetryTxLC = 0x02000000, /* retry late collision */ - PKTSMask = 0x3ff800, /* packet size bit21-11 */ - PKTSShift = 11, - TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */ - TBSShift = 0, -}; - -/* BootROM/EEPROM/MII Management Register */ -#define MASK_MIIR_MII_READ 0x00000000 -#define MASK_MIIR_MII_WRITE 0x00000008 -#define MASK_MIIR_MII_MDO 0x00000004 -#define MASK_MIIR_MII_MDI 0x00000002 -#define MASK_MIIR_MII_MDC 0x00000001 - -/* ST+OP+PHYAD+REGAD+TA */ -#define OP_READ 0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */ -#define OP_WRITE 0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */ - -/* ------------------------------------------------------------------------- */ -/* Constants for Myson PHY */ -/* ------------------------------------------------------------------------- */ -#define MysonPHYID 0xd0000302 -/* 89-7-27 add, (begin) */ -#define MysonPHYID0 0x0302 -#define StatusRegister 18 -#define SPEED100 0x0400 // bit10 -#define FULLMODE 0x0800 // bit11 -/* 89-7-27 add, (end) */ - -/* ------------------------------------------------------------------------- */ -/* Constants for Seeq 80225 PHY */ -/* ------------------------------------------------------------------------- */ -#define SeeqPHYID0 0x0016 - -#define MIIRegister18 18 -#define SPD_DET_100 0x80 -#define DPLX_DET_FULL 0x40 - -/* ------------------------------------------------------------------------- */ -/* Constants for Ahdoc 101 PHY */ -/* ------------------------------------------------------------------------- */ -#define AhdocPHYID0 0x0022 - -#define DiagnosticReg 18 -#define DPLX_FULL 0x0800 -#define Speed_100 0x0400 - -/* 89/6/13 add, */ -/* -------------------------------------------------------------------------- */ -/* Constants */ -/* -------------------------------------------------------------------------- */ -#define MarvellPHYID0 0x0141 -#define LevelOnePHYID0 0x0013 - -#define MII1000BaseTControlReg 9 -#define MII1000BaseTStatusReg 10 -#define SpecificReg 17 - -/* for 1000BaseT Control Register */ -#define PHYAbletoPerform1000FullDuplex 0x0200 -#define PHYAbletoPerform1000HalfDuplex 0x0100 -#define PHY1000AbilityMask 0x300 - -// for phy specific status register, marvell phy. -#define SpeedMask 0x0c000 -#define Speed_1000M 0x08000 -#define Speed_100M 0x4000 -#define Speed_10M 0 -#define Full_Duplex 0x2000 - -// 89/12/29 add, for phy specific status register, levelone phy, (begin) -#define LXT1000_100M 0x08000 -#define LXT1000_1000M 0x0c000 -#define LXT1000_Full 0x200 -// 89/12/29 add, for phy specific status register, levelone phy, (end) - -#if 0 -/* for 3-in-1 case */ -#define PS10 0x00080000 -#define FD 0x00100000 -#define PS1000 0x00010000 -#endif - -/* for PHY */ -#define LinkIsUp 0x0004 -#define LinkIsUp2 0x00040000 - -/* 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 { - u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8))); - u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8))); -} mtd80x_bufs __shared; -#define txb mtd80x_bufs.txb -#define rxb mtd80x_bufs.rxb - -/* The Tulip Rx and Tx buffer descriptors. */ -struct mtd_desc -{ - s32 status; - s32 control; - u32 buffer; - u32 next_desc; - struct mtd_desc *next_desc_logical; - u8* skbuff; - u32 reserved1; - u32 reserved2; -}; - -struct mtd_private -{ - struct mtd_desc rx_ring[RX_RING_SIZE]; - struct mtd_desc tx_ring[TX_RING_SIZE]; - - /* Frequently used values: keep some adjacent for cache effect. */ - int flags; - struct pci_dev *pci_dev; - unsigned long crvalue; - unsigned long bcrvalue; - /*unsigned long imrvalue;*/ - struct mtd_desc *cur_rx; - struct mtd_desc *lack_rxbuf; - int really_rx_count; - struct mtd_desc *cur_tx; - struct mtd_desc *cur_tx_copy; - int really_tx_count; - int free_tx_count; - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - - /* These values are keep track of the transceiver/media in use. */ - unsigned int linkok; - unsigned int line_speed; - unsigned int duplexmode; - unsigned int default_port: - 4; /* Last dev->if_port value. */ - unsigned int PHYType; - - /* MII transceiver section. */ - int mii_cnt; /* MII device addresses. */ - unsigned char phys[1]; /* MII device addresses. */ - - /*other*/ - const char *nic_name; - int ioaddr; - u16 dev_id; -}; - -static struct mtd_private mtdx; - -static int mdio_read(struct nic * , int phy_id, int location); -static void getlinktype(struct nic * ); -static void getlinkstatus(struct nic * ); -static void set_rx_mode(struct nic *); - -/************************************************************************** - * init_ring - setup the tx and rx descriptors - *************************************************************************/ -static void init_ring(struct nic *nic __unused) -{ - int i; - - mtdx.cur_rx = &mtdx.rx_ring[0]; - - mtdx.rx_buf_sz = PKT_BUF_SZ; - /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/ - - /* Initialize all Rx descriptors. */ - /* Fill in the Rx buffers. Handle allocation failure gracefully. */ - for (i = 0; i < RX_RING_SIZE; i++) - { - mtdx.rx_ring[i].status = RXOWN; - mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift; - mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]); - mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1]; - mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]); - mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ]; - } - /* Mark the last entry as wrapping the ring. */ - mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]); - mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0]; - - /* We only use one transmit buffer, but two - * descriptors so transmit engines have somewhere - * to point should they feel the need */ - mtdx.tx_ring[0].status = 0x00000000; - mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]); - mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]); - - /* This descriptor is never used */ - mtdx.tx_ring[1].status = 0x00000000; - mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */ - mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]); - - return; -} - -/************************************************************************** -RESET - Reset Adapter -***************************************************************************/ -static void mtd_reset( struct nic *nic ) -{ - /* Reset the chip to erase previous misconfiguration. */ - outl(0x00000001, mtdx.ioaddr + BCR); - - init_ring(nic); - - outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA); - outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA); - - /* Initialize other registers. */ - /* Configure the PCI bus bursts and FIFO thresholds. */ - mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */ - mtdx.crvalue = 0xa00; /* rx 128 burst length */ - - if ( mtdx.dev_id == 0x891 ) { - mtdx.bcrvalue |= 0x200; /* set PROG bit */ - mtdx.crvalue |= 0x02000000; /* set enhanced bit */ - } - - outl( mtdx.bcrvalue, mtdx.ioaddr + BCR); - - /* Restart Rx engine if stopped. */ - outl(0, mtdx.ioaddr + RXPDR); - - getlinkstatus(nic); - if (mtdx.linkok) - { - static const char* texts[]={"half","full","10","100","1000"}; - getlinktype(nic); - DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] ); - } else - { - DBG ( "No link!!!\n" ); - } - - mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold; - set_rx_mode(nic); - - /* Clear interrupts by setting the interrupt mask. */ - outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR); - outl( 0, mtdx.ioaddr + IMR); -} - -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int mtd_poll(struct nic *nic, __unused int retrieve) -{ - s32 rx_status = mtdx.cur_rx->status; - int retval = 0; - - if( ( rx_status & RXOWN ) != 0 ) - { - return 0; - } - - if (rx_status & ErrorSummary) - { /* there was a fatal error */ - printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n", - mtdx.nic_name, (unsigned int) rx_status, - (rx_status & (LONG | RUNT)) ? "length_error ":"", - (rx_status & RXER) ? "frame_error ":"", - (rx_status & CRC) ? "crc_error ":"" ); - retval = 0; - } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) ) - { - /* this pkt is too long, over one rx buffer */ - printf("Pkt is too long, over one rx buffer.\n"); - retval = 0; - } else - { /* this received pkt is ok */ - /* Omit the four octet CRC from the length. */ - short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4; - - DBG ( " netdev_rx() normal Rx pkt length %d" - " status %x.\n", pkt_len, (unsigned int) rx_status ); - - nic->packetlen = pkt_len; - memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len); - - retval = 1; - } - - while( ( mtdx.cur_rx->status & RXOWN ) == 0 ) - { - mtdx.cur_rx->status = RXOWN; - mtdx.cur_rx = mtdx.cur_rx->next_desc_logical; - } - - /* Restart Rx engine if stopped. */ - outl(0, mtdx.ioaddr + RXPDR); - - return retval; -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static void mtd_transmit( - struct nic *nic, - const char *dest, /* Destination */ - unsigned int type, /* Type */ - unsigned int size, /* size */ - const char *data) /* Packet */ -{ - u32 to; - u32 tx_status; - unsigned int nstype = htons ( type ); - - memcpy( txb, dest, ETH_ALEN ); - memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN ); - memcpy( txb + 2 * ETH_ALEN, &nstype, 2 ); - memcpy( txb + ETH_HLEN, data, size ); - - size += ETH_HLEN; - size &= 0x0FFF; - while( size < ETH_ZLEN ) - { - txb[size++] = '\0'; - } - - mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable; - mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */ - mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */ - mtdx.tx_ring[0].status = TXOWN; - - /* Point to transmit descriptor */ - outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA); - /* Enable Tx */ - outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR); - /* Wake the potentially-idle transmit channel. */ - outl(0, mtdx.ioaddr + TXPDR); - - to = currticks() + TX_TIME_OUT; - while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to)); - - /* Disable Tx */ - outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR); - - tx_status = mtdx.tx_ring[0].status; - if (currticks() >= to){ - DBG ( "TX Time Out" ); - } else if( tx_status & (CSL | LC | EC | UDF | HF)){ - printf( "Transmit error: %8.8x %s %s %s %s %s\n", - (unsigned int) tx_status, - tx_status & EC ? "abort" : "", - tx_status & CSL ? "carrier" : "", - tx_status & LC ? "late" : "", - tx_status & UDF ? "fifo" : "", - tx_status & HF ? "heartbeat" : "" ); - } - - /*hex_dump( txb, size );*/ - /*pause();*/ - - DBG ( "TRANSMIT\n" ); -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void mtd_disable ( struct nic *nic ) { - - /* Disable Tx Rx*/ - outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR ); - - /* Reset the chip to erase previous misconfiguration. */ - mtd_reset(nic); - - DBG ( "DISABLE\n" ); -} - -static struct nic_operations mtd_operations = { - .connect = dummy_connect, - .poll = mtd_poll, - .transmit = mtd_transmit, - .irq = dummy_irq, - -}; - -static struct pci_device_id mtd80x_nics[] = { - PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800", 0), - PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X", 0), - PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891", 0), -}; - -PCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS ); - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -***************************************************************************/ - -static int mtd_probe ( struct nic *nic, struct pci_device *pci ) { - - int i; - - if (pci->ioaddr == 0) - return 0; - - adjust_pci_device(pci); - - nic->ioaddr = pci->ioaddr; - nic->irqno = 0; - - mtdx.nic_name = pci->id->name; - mtdx.dev_id = pci->device; - mtdx.ioaddr = nic->ioaddr; - - /* read ethernet id */ - for (i = 0; i < 6; ++i) - { - nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i); - } - - if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0) - { - return 0; - } - - DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) ); - - /* Reset the chip to erase previous misconfiguration. */ - outl(0x00000001, mtdx.ioaddr + BCR); - - /* find the connected MII xcvrs */ - - if( mtdx.dev_id != 0x803 ) - { - int phy, phy_idx = 0; - - for (phy = 1; phy < 32 && phy_idx < 1; phy++) { - int mii_status = mdio_read(nic, phy, 1); - - if (mii_status != 0xffff && mii_status != 0x0000) { - mtdx.phys[phy_idx] = phy; - - DBG ( "%s: MII PHY found at address %d, status " - "0x%4.4x.\n", mtdx.nic_name, phy, mii_status ); - /* get phy type */ - { - unsigned int data; - - data = mdio_read(nic, mtdx.phys[phy_idx], 2); - if (data == SeeqPHYID0) - mtdx.PHYType = SeeqPHY; - else if (data == AhdocPHYID0) - mtdx.PHYType = AhdocPHY; - else if (data == MarvellPHYID0) - mtdx.PHYType = MarvellPHY; - else if (data == MysonPHYID0) - mtdx.PHYType = Myson981; - else if (data == LevelOnePHYID0) - mtdx.PHYType = LevelOnePHY; - else - mtdx.PHYType = OtherPHY; - } - phy_idx++; - } - } - - mtdx.mii_cnt = phy_idx; - if (phy_idx == 0) { - printf("%s: MII PHY not found -- this device may " - "not operate correctly.\n", mtdx.nic_name); - } - } else { - mtdx.phys[0] = 32; - /* get phy type */ - if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) { - mtdx.PHYType = MysonPHY; - DBG ( "MysonPHY\n" ); - } else { - mtdx.PHYType = OtherPHY; - DBG ( "OtherPHY\n" ); - } - } - - getlinkstatus(nic); - if( !mtdx.linkok ) - { - printf("No link!!!\n"); - return 0; - } - - mtd_reset( nic ); - - /* point to NIC specific routines */ - nic->nic_op = &mtd_operations; - return 1; -} - - -/**************************************************************************/ -static void set_rx_mode(struct nic *nic __unused) -{ - u32 mc_filter[2]; /* Multicast hash filter */ - u32 rx_mode; - - /* Too many to match, or accept all multicasts. */ - mc_filter[1] = mc_filter[0] = ~0; - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - - outl(mc_filter[0], mtdx.ioaddr + MAR0); - outl(mc_filter[1], mtdx.ioaddr + MAR1); - - mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode; - outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR); -} -/**************************************************************************/ -static unsigned int m80x_read_tick(void) -/* function: Reads the Timer tick count register which decrements by 2 from */ -/* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */ -/* count represents 838 nsec's. */ -/* input : none. */ -/* output : none. */ -{ - unsigned char tmp; - int value; - - outb((char) 0x06, 0x43); // Command 8254 to latch T0's count - - // now read the count. - tmp = (unsigned char) inb(0x40); - value = ((int) tmp) << 8; - tmp = (unsigned char) inb(0x40); - value |= (((int) tmp) & 0xff); - return (value); -} - -static void m80x_delay(unsigned int interval) -/* function: to wait for a specified time. */ -/* input : interval ... the specified time. */ -/* output : none. */ -{ - unsigned int interval1, interval2, i = 0; - - interval1 = m80x_read_tick(); // get initial value - do - { - interval2 = m80x_read_tick(); - if (interval1 < interval2) - interval1 += 65536; - ++i; - } while (((interval1 - interval2) < (u16) interval) && (i < 65535)); -} - - -static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad) -{ - u32 miir; - int i; - unsigned int mask, data; - - /* enable MII output */ - miir = (u32) inl(miiport); - miir &= 0xfffffff0; - - miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO; - - /* send 32 1's preamble */ - for (i = 0; i < 32; i++) { - /* low MDC; MDO is already high (miir) */ - miir &= ~MASK_MIIR_MII_MDC; - outl(miir, miiport); - - /* high MDC */ - miir |= MASK_MIIR_MII_MDC; - outl(miir, miiport); - } - - /* calculate ST+OP+PHYAD+REGAD+TA */ - data = opcode | (phyad << 7) | (regad << 2); - - /* sent out */ - mask = 0x8000; - while (mask) { - /* low MDC, prepare MDO */ - miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO); - if (mask & data) - miir |= MASK_MIIR_MII_MDO; - - outl(miir, miiport); - /* high MDC */ - miir |= MASK_MIIR_MII_MDC; - outl(miir, miiport); - m80x_delay(30); - - /* next */ - mask >>= 1; - if (mask == 0x2 && opcode == OP_READ) - miir &= ~MASK_MIIR_MII_WRITE; - } - return miir; -} - -static int mdio_read(struct nic *nic __unused, int phyad, int regad) -{ - long miiport = mtdx.ioaddr + MANAGEMENT; - u32 miir; - unsigned int mask, data; - - miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad); - - /* read data */ - mask = 0x8000; - data = 0; - while (mask) - { - /* low MDC */ - miir &= ~MASK_MIIR_MII_MDC; - outl(miir, miiport); - - /* read MDI */ - miir = inl(miiport); - if (miir & MASK_MIIR_MII_MDI) - data |= mask; - - /* high MDC, and wait */ - miir |= MASK_MIIR_MII_MDC; - outl(miir, miiport); - m80x_delay((int) 30); - - /* next */ - mask >>= 1; - } - - /* low MDC */ - miir &= ~MASK_MIIR_MII_MDC; - outl(miir, miiport); - - return data & 0xffff; -} - -#if 0 /* not used */ -static void mdio_write(struct nic *nic __unused, int phyad, int regad, - int data) -{ - long miiport = mtdx.ioaddr + MANAGEMENT; - u32 miir; - unsigned int mask; - - miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad); - - /* write data */ - mask = 0x8000; - while (mask) - { - /* low MDC, prepare MDO */ - miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO); - if (mask & data) - miir |= MASK_MIIR_MII_MDO; - outl(miir, miiport); - - /* high MDC */ - miir |= MASK_MIIR_MII_MDC; - outl(miir, miiport); - - /* next */ - mask >>= 1; - } - - /* low MDC */ - miir &= ~MASK_MIIR_MII_MDC; - outl(miir, miiport); - - return; -} -#endif - -static void getlinkstatus(struct nic *nic) -/* function: Routine will read MII Status Register to get link status. */ -/* input : dev... pointer to the adapter block. */ -/* output : none. */ -{ - unsigned int i, DelayTime = 0x1000; - - mtdx.linkok = 0; - - if (mtdx.PHYType == MysonPHY) - { - for (i = 0; i < DelayTime; ++i) { - if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) { - mtdx.linkok = 1; - return; - } - // delay - m80x_delay(100); - } - } else - { - for (i = 0; i < DelayTime; ++i) { - if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) { - mtdx.linkok = 1; - return; - } - // delay - m80x_delay(100); - } - } -} - - -static void getlinktype(struct nic *dev) -{ - if (mtdx.PHYType == MysonPHY) - { /* 3-in-1 case */ - if (inl(mtdx.ioaddr + TCRRCR) & FD) - mtdx.duplexmode = 2; /* full duplex */ - else - mtdx.duplexmode = 1; /* half duplex */ - if (inl(mtdx.ioaddr + TCRRCR) & PS10) - mtdx.line_speed = 1; /* 10M */ - else - mtdx.line_speed = 2; /* 100M */ - } else - { - if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */ - unsigned int data; - - data = mdio_read(dev, mtdx.phys[0], MIIRegister18); - if (data & SPD_DET_100) - mtdx.line_speed = 2; /* 100M */ - else - mtdx.line_speed = 1; /* 10M */ - if (data & DPLX_DET_FULL) - mtdx.duplexmode = 2; /* full duplex mode */ - else - mtdx.duplexmode = 1; /* half duplex mode */ - } else if (mtdx.PHYType == AhdocPHY) { - unsigned int data; - - data = mdio_read(dev, mtdx.phys[0], DiagnosticReg); - if (data & Speed_100) - mtdx.line_speed = 2; /* 100M */ - else - mtdx.line_speed = 1; /* 10M */ - if (data & DPLX_FULL) - mtdx.duplexmode = 2; /* full duplex mode */ - else - mtdx.duplexmode = 1; /* half duplex mode */ - } - /* 89/6/13 add, (begin) */ - else if (mtdx.PHYType == MarvellPHY) { - unsigned int data; - - data = mdio_read(dev, mtdx.phys[0], SpecificReg); - if (data & Full_Duplex) - mtdx.duplexmode = 2; /* full duplex mode */ - else - mtdx.duplexmode = 1; /* half duplex mode */ - data &= SpeedMask; - if (data == Speed_1000M) - mtdx.line_speed = 3; /* 1000M */ - else if (data == Speed_100M) - mtdx.line_speed = 2; /* 100M */ - else - mtdx.line_speed = 1; /* 10M */ - } - /* 89/6/13 add, (end) */ - /* 89/7/27 add, (begin) */ - else if (mtdx.PHYType == Myson981) { - unsigned int data; - - data = mdio_read(dev, mtdx.phys[0], StatusRegister); - - if (data & SPEED100) - mtdx.line_speed = 2; - else - mtdx.line_speed = 1; - - if (data & FULLMODE) - mtdx.duplexmode = 2; - else - mtdx.duplexmode = 1; - } - /* 89/7/27 add, (end) */ - /* 89/12/29 add */ - else if (mtdx.PHYType == LevelOnePHY) { - unsigned int data; - - data = mdio_read(dev, mtdx.phys[0], SpecificReg); - if (data & LXT1000_Full) - mtdx.duplexmode = 2; /* full duplex mode */ - else - mtdx.duplexmode = 1; /* half duplex mode */ - data &= SpeedMask; - if (data == LXT1000_1000M) - mtdx.line_speed = 3; /* 1000M */ - else if (data == LXT1000_100M) - mtdx.line_speed = 2; /* 100M */ - else - mtdx.line_speed = 1; /* 10M */ - } - // chage crvalue - // mtdx.crvalue&=(~PS10)&(~FD); - mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000); - if (mtdx.line_speed == 1) - mtdx.crvalue |= PS10; - else if (mtdx.line_speed == 3) - mtdx.crvalue |= PS1000; - if (mtdx.duplexmode == 2) - mtdx.crvalue |= FD; - } -} - -DRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver, - mtd_probe, mtd_disable ); diff --git a/roms/ipxe/src/drivers/net/myri10ge.c b/roms/ipxe/src/drivers/net/myri10ge.c index 5bb555d82..ae6b6c21e 100644 --- a/roms/ipxe/src/drivers/net/myri10ge.c +++ b/roms/ipxe/src/drivers/net/myri10ge.c @@ -13,7 +13,8 @@ * * You 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. ****************************************************************/ FILE_LICENCE ( GPL2_ONLY ); @@ -304,10 +305,10 @@ static int myri10ge_command ( struct myri10ge_private *priv, command->response_addr.high = 0; command->response_addr.low = htonl ( virt_to_bus ( &priv->dma->command_response ) ); - for ( i=0; i<36; i+=4 ) - * ( uint32 * ) &command->pad[i] = 0; + for ( i=0; i<9; i++ ) + command->pad[i] = 0; wmb(); - * ( uint32 * ) &command->pad[36] = 0; + command->pad[9] = 0; /* Wait up to 2 seconds for a response. */ @@ -718,7 +719,7 @@ static int myri10ge_nv_init ( struct myri10ge_private *priv ) return 0; } - /* Initilize NonVolatile Storage state. */ + /* Initialize NonVolatile Storage state. */ priv->nvs.word_len_log2 = 0; priv->nvs.size = hdr.eeprom_len; diff --git a/roms/ipxe/src/drivers/net/myri10ge_mcp.h b/roms/ipxe/src/drivers/net/myri10ge_mcp.h index 397f8b0dd..6c82b3c76 100644 --- a/roms/ipxe/src/drivers/net/myri10ge_mcp.h +++ b/roms/ipxe/src/drivers/net/myri10ge_mcp.h @@ -13,7 +13,8 @@ * * You 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. ****************************************************************/ FILE_LICENCE ( GPL2_ONLY ); @@ -80,7 +81,7 @@ struct mcp_cmd { /* 16 */ struct mcp_dma_addr response_addr; /* 24 */ - uint8_t pad[40]; + uint32_t pad[10]; }; typedef struct mcp_cmd mcp_cmd_t; diff --git a/roms/ipxe/src/drivers/net/myson.c b/roms/ipxe/src/drivers/net/myson.c new file mode 100644 index 000000000..237f87210 --- /dev/null +++ b/roms/ipxe/src/drivers/net/myson.c @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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: + iounmap ( myson->regs ); + 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 */ + iounmap ( myson->regs ); + 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/roms/ipxe/src/drivers/net/myson.h b/roms/ipxe/src/drivers/net/myson.h new file mode 100644 index 000000000..8d7cc5855 --- /dev/null +++ b/roms/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 +#include + +/** 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/roms/ipxe/src/drivers/net/natsemi.c b/roms/ipxe/src/drivers/net/natsemi.c index 171542818..669fb8775 100644 --- a/roms/ipxe/src/drivers/net/natsemi.c +++ b/roms/ipxe/src/drivers/net/natsemi.c @@ -1,604 +1,929 @@ -/* - natsemi.c - iPXE driver for the NatSemi DP8381x series. - - Based on: - - natsemi.c: An Etherboot driver for the NatSemi DP8381x series. - - Copyright (C) 2001 Entity Cyber, Inc. - - This development of this Etherboot driver was funded by - - Sicom Systems: http://www.sicompos.com/ - - Author: Marty Connor - Adapted from a Linux driver which was 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. - - Original Copyright Notice: - - Written/copyright 1999-2001 by Donald Becker. - - 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. License for under other terms may be - available. Contact the original author for details. - - The original author may be reached as becker@scyld.com, or at - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Support information and updates available at - http://www.scyld.com/network/netsemi.html - - References: - - http://www.scyld.com/expert/100mbps.html - http://www.scyld.com/expert/NWay.html - Datasheet is available from: - http://www.national.com/pf/DP/DP83815.html - -*/ - -FILE_LICENCE ( GPL_ANY ); - -/* Revision History */ - /* - 02 Jul 2007 Udayan Kumar 1.2 ported the driver from etherboot to iPXE API. - Fully rewritten,adapting the old driver. - Added a circular buffer for transmit and receive. - transmit routine will not wait for transmission to finish. - poll routine deals with it. - 13 Dec 2003 Tim Legge 1.1 Enabled Multicast Support - 29 May 2001 Marty Connor 1.0 Initial Release. Tested with Netgear FA311 and FA312 boards -*/ + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); #include -#include -#include #include -#include +#include #include #include -#include -#include -#include +#include #include +#include #include -#include +#include +#include +#include +#include #include #include -#include #include "natsemi.h" -/* Function Prototypes: */ - -static int natsemi_spi_read_bit ( struct bit_basher *, unsigned int ); -static void natsemi_spi_write_bit ( struct bit_basher *,unsigned int, unsigned long ); -static void natsemi_init_eeprom ( struct natsemi_private * ); -static int natsemi_probe (struct pci_device *pci); -static void natsemi_reset (struct net_device *netdev); -static int natsemi_open (struct net_device *netdev); -static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf); -static void natsemi_poll (struct net_device *netdev); -static void natsemi_close (struct net_device *netdev); -static void natsemi_irq (struct net_device *netdev, int enable); -static void natsemi_remove (struct pci_device *pci); - -/** natsemi net device operations */ -static struct net_device_operations natsemi_operations = { - .open = natsemi_open, - .close = natsemi_close, - .transmit = natsemi_transmit, - .poll = natsemi_poll, - .irq = natsemi_irq, +/** @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_private *np = container_of ( basher, struct natsemi_private, - spibit.basher ); - uint8_t mask = natsemi_ee_bits[bit_id]; - uint8_t eereg; - - eereg = inb ( np->ioaddr + EE_REG ); - return ( eereg & mask ); + 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_private *np = container_of ( basher, struct natsemi_private, - spibit.basher ); - uint8_t mask = natsemi_ee_bits[bit_id]; - uint8_t eereg; - - eereg = inb ( np->ioaddr + EE_REG ); - eereg &= ~mask; - eereg |= ( data & mask ); - outb ( eereg, np->ioaddr + EE_REG ); + 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, }; -/* - * Set up for EEPROM access +/** + * Initialise EEPROM * - * @v NAT NATSEMI NIC + * @v natsemi National Semiconductor device */ -static void natsemi_init_eeprom ( struct natsemi_private *np ) { +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; +} - /* Initialise three-wire bus - */ - np->spibit.basher.op = &natsemi_basher_ops; - np->spibit.bus.mode = SPI_MODE_THREEWIRE; - np->spibit.endianness = SPI_BIT_LITTLE_ENDIAN; - init_spi_bit_basher ( &np->spibit ); +/** + * 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; - /*natsemi DP 83815 only supports at93c46 - */ - init_at93c46 ( &np->eeprom, 16 ); - np->eeprom.bus = &np->spibit.bus; + /* Copy MAC address from EEPROM data */ + for ( i = ( ( ETH_ALEN / 2 ) - 1 ) ; i >= 0 ; i-- ) + *(hw_addr++) = eeprom[ NATSEMI_EEPROM_MAC_SANE + i ]; - /* It looks that this portion of EEPROM can be used for - * non-volatile stored options. Data sheet does not talk about - * this region. Currently it is not working. But with some - * efforts it can. - */ - nvo_init ( &np->nvo, &np->eeprom.nvs, 0x0c, 0x68, NULL, NULL ); + DBGC ( natsemi, "NATSEMI %p has sane EEPROM layout\n", natsemi ); } /** - * Probe PCI device + * Get hardware address from insane EEPROM data * - * @v pci PCI device - * @v id PCI ID - * @ret rc Return status code + * @v natsemi National Semiconductor device + * @v eeprom EEPROM data + * @v hw_addr Hardware address to fill in */ -static int natsemi_probe (struct pci_device *pci) { - struct net_device *netdev; - struct natsemi_private *np = NULL; - uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN]; - uint8_t last=0,last1=0; - uint8_t prev_bytes[2]; - int i; - int rc; +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 ); + } - /* Allocate net device - */ - netdev = alloc_etherdev (sizeof (*np)); - if (! netdev) - return -ENOMEM; + DBGC ( natsemi, "NATSEMI %p has insane EEPROM layout\n", natsemi ); +} - netdev_init (netdev, &natsemi_operations); - np = netdev->priv; - pci_set_drvdata (pci, netdev); - netdev->dev = &pci->dev; - memset (np, 0, sizeof (*np)); - np->ioaddr = pci->ioaddr; - - adjust_pci_device (pci); - - natsemi_reset (netdev); - natsemi_init_eeprom ( np ); - nvs_read ( &np->eeprom.nvs, EE_MAC-1, prev_bytes, 1 ); - nvs_read ( &np->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN ); - - /* decoding the MAC address read from NVS - * and save it in netdev->ll_addr - */ - last = prev_bytes[1] >> 7; - for ( i = 0 ; i < ETH_ALEN ; i++ ) { - last1 = ll_addr_encoded[i] >> 7; - netdev->hw_addr[i] = ll_addr_encoded[i] << 1 | last; - last = last1; - } +/** + * 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; - if ((rc = register_netdev (netdev)) != 0) - goto err_register_netdev; + /* 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 ) ); - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); + /* 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; +} -err_register_netdev: +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ - natsemi_reset (netdev); - netdev_put (netdev); - return rc; +/** + * 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; } /** - * Remove PCI device + * Reload configuration from EEPROM * - * @v pci PCI device + * @v natsemi National Semiconductor device + * @ret rc Return status code */ -static void natsemi_remove (struct pci_device *pci) { - struct net_device *netdev = pci_get_drvdata (pci); - - unregister_netdev (netdev); - natsemi_reset (netdev); - netdev_nullify ( netdev ); - netdev_put (netdev); +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 NIC + * Reset hardware * - * @v NATSEMI NIC - * - * Issues a hardware reset and waits for the reset to complete. + * @v natsemi National Semiconductor device + * @ret rc Return status code */ -static void natsemi_reset (struct net_device *netdev) -{ - struct natsemi_private *np = netdev->priv; - int i; - u32 cfg; - u32 wcsr; - u32 rfcr; - u16 pmatch[3]; - u16 sopass[3]; - - natsemi_irq (netdev, 0); - - /* - * Resetting the chip causes some registers to be lost. - * Natsemi suggests NOT reloading the EEPROM while live, so instead - * we save the state that would have been loaded from EEPROM - * on a normal power-up (see the spec EEPROM map). - */ - - /* CFG */ - cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE; - - /* WCSR */ - wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE; - - /* RFCR */ - rfcr = inl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE; - - /* PMATCH */ - for (i = 0; i < 3; i++) { - outl(i*2, np->ioaddr + RxFilterAddr); - pmatch[i] = inw(np->ioaddr + RxFilterData); - } - - /* SOPAS */ - for (i = 0; i < 3; i++) { - outl(0xa+(i*2), np->ioaddr + RxFilterAddr); - sopass[i] = inw(np->ioaddr + RxFilterData); - } - - /* now whack the chip */ - outl(ChipReset, np->ioaddr + ChipCmd); - for (i=0; iioaddr + ChipCmd) & ChipReset)) - break; - udelay(5); - } - if (i == NATSEMI_HW_TIMEOUT) { - DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5); - } - - /* restore CFG */ - cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE; - cfg &= ~(CfgExtPhy | CfgPhyDis); - outl (cfg, np->ioaddr + ChipConfig); - - /* restore WCSR */ - wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE; - outl (wcsr, np->ioaddr + WOLCmd); - - /* read RFCR */ - rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE; - - /* restore PMATCH */ - for (i = 0; i < 3; i++) { - outl (i*2, np->ioaddr + RxFilterAddr); - outw (pmatch[i], np->ioaddr + RxFilterData); - } - for (i = 0; i < 3; i++) { - outl (0xa+(i*2), np->ioaddr + RxFilterAddr); - outw (sopass[i], np->ioaddr + RxFilterData); - } - /* restore RFCR */ - outl (rfcr, np->ioaddr + RxFilterAddr); +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 + * + ****************************************************************************** + */ + /** - * Open NIC + * Check link state * - * @v netdev Net device - * @ret rc Return status code + * @v netdev Network device */ -static int natsemi_open (struct net_device *netdev) -{ - struct natsemi_private *np = netdev->priv; - uint32_t tx_config, rx_config; - int i; - - /* Disable PME: - * The PME bit is initialized from the EEPROM contents. - * PCI cards probably have PME disabled, but motherboard - * implementations may have PME set to enable WakeOnLan. - * With PME set the chip will scan incoming packets but - * nothing will be written to memory. - */ - outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun); - - /* Set MAC address in NIC - */ - for (i = 0 ; i < ETH_ALEN ; i+=2) { - outl (i, np->ioaddr + RxFilterAddr); - outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8), - np->ioaddr + RxFilterData); +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 ); } - /* Setup Tx Ring - */ - np->tx_cur = 0; - np->tx_dirty = 0; - for (i = 0 ; i < TX_RING_SIZE ; i++) { - np->tx[i].link = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]); - np->tx[i].cmdsts = 0; - np->tx[i].bufptr = 0; + /* 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 ); } - outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr); +} - DBG ("Natsemi Tx descriptor loaded with: %#08x\n", - inl (np->ioaddr + TxRingPtr)); +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ - /* Setup RX ring - */ - np->rx_cur = 0; - for (i = 0 ; i < NUM_RX_DESC ; i++) { - np->iobuf[i] = alloc_iob (RX_BUF_SIZE); - if (! np->iobuf[i]) - goto memory_alloc_err; - np->rx[i].link = virt_to_bus ((i + 1 < NUM_RX_DESC) - ? &np->rx[i + 1] : &np->rx[0]); - np->rx[i].cmdsts = RX_BUF_SIZE; - np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data); - DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i, - &np->iobuf[i], &np->iobuf[i]->data); +/** + * 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 ); } - outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr); +} - DBG ("Natsemi Rx descriptor loaded with: %#08x\n", - inl (np->ioaddr + RxRingPtr)); +/** + * 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; - /* Setup RX Filter - */ - outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys, - np->ioaddr + RxFilterAddr); + /* Calculate descriptor offset */ + offset = ( ( natsemi->flags & NATSEMI_64BIT ) ? 0 : + offsetof ( typeof ( desc[i].d32pad ), d32 ) ); - /* Initialize other registers. - * Configure the PCI bus bursts and FIFO thresholds. - * Configure for standard, in-spec Ethernet. + /* Allocate descriptor ring. Align ring on its own size to + * ensure that it can't possibly cross the boundary of 32-bit + * address space. */ - if (inl (np->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */ - DBG ("Full duplex\n"); - tx_config = 0xD0801002 | 0xC0000000; - rx_config = 0x10000020 | 0x10000000; - } else { - DBG ("Half duplex\n"); - tx_config = 0x10801002 & ~0xC0000000; - rx_config = 0x00000020 & ~0x10000000; + 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; } - outl (tx_config, np->ioaddr + TxConfig); - outl (rx_config, np->ioaddr + RxConfig); - DBG ("Tx config register = %#08x Rx config register = %#08x\n", - inl (np->ioaddr + TxConfig), - inl (np->ioaddr + RxConfig)); + /* 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 ) ); - /*Set the Interrupt Mask register - */ - outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask); - /*start the receiver - */ - outl (RxOn, np->ioaddr + ChipCmd); - return 0; - -memory_alloc_err: - /* Frees any allocated buffers when memory - * for all buffers requested is not available - */ - i = 0; - while (np->rx[i].cmdsts == RX_BUF_SIZE) { - free_iob (np->iobuf[i]); - i++; - } - return -ENOMEM; + err_64bit: + free_dma ( ring->desc, len ); + ring->desc = NULL; + err_alloc: + return rc; } /** - * Close NIC + * Destroy descriptor ring * - * @v netdev Net device + * @v natsemi National Semiconductor device + * @v ring Descriptor ring */ -static void natsemi_close (struct net_device *netdev) -{ - struct natsemi_private *np = netdev->priv; - int i; +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; + } - natsemi_reset (netdev); + /* Get next receive descriptor */ + rx_idx = ( natsemi->rx.prod++ % NATSEMI_NUM_RX_DESC ); + rx = &natsemi->rx.desc[rx_idx]; - for (i = 0; i < NUM_RX_DESC ; i++) { - free_iob (np->iobuf[i]); + /* 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)); } } -/** - * Transmit packet +/** + * Open network device * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code + * @v netdev Network device + * @ret rc Return status code */ -static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf) -{ - struct natsemi_private *np = netdev->priv; +static int natsemi_open ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + int rc; - if (np->tx[np->tx_cur].cmdsts != 0) { - DBG ("TX overflow\n"); - return -ENOBUFS; - } + /* Set MAC address */ + natsemi_pmatch ( natsemi, netdev->ll_addr ); - /* Used by netdev_tx_complete () - */ - np->tx_iobuf[np->tx_cur] = iobuf; + /* Create transmit descriptor ring */ + if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->tx ) ) != 0 ) + goto err_create_tx; - /* Pad and align packet has not been used because its not required - * by the hardware. - * iob_pad (iobuf, ETH_ZLEN); - * can be used to achieve it, if required - */ + /* 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 ) ) ); - /* Add the packet to TX ring - */ - np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data); - np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN; + /* Create receive descriptor ring */ + if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->rx ) ) != 0 ) + goto err_create_rx; - DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur, - virt_to_bus (&iobuf->data), iob_len (iobuf)); + /* 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 ) ) ); - /* increment the circular buffer pointer to the next buffer location - */ - np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE; + /* 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 ); - /*start the transmitter + /* Unmask transmit and receive interrupts. (Interrupts will + * not be generated unless enabled via the IER.) */ - outl (TxOn, np->ioaddr + ChipCmd); + 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; } -/** - * Poll for received packets +/** + * Close network device * - * @v netdev Network device + * @v netdev Network device */ -static void natsemi_poll (struct net_device *netdev) -{ - struct natsemi_private *np = netdev->priv; - unsigned int tx_status; - unsigned int rx_status; - unsigned int intr_status; - unsigned int rx_len; - struct io_buffer *rx_iob; - int i; - - /* read the interrupt register - */ - intr_status = inl (np->ioaddr + IntrStatus); +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; + } - if (!intr_status) - goto end; + /* Destroy receive descriptor ring */ + natsemi_destroy_ring ( natsemi, &natsemi->rx ); - DBG ("natsemi_poll: intr_status = %#08x\n", intr_status); + /* Destroy transmit descriptor ring */ + natsemi_destroy_ring ( natsemi, &natsemi->tx ); +} - /* Check status of transmitted packets - */ - i = np->tx_dirty; - while (i != np->tx_cur) { - tx_status = np->tx[np->tx_dirty].cmdsts; - - DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n", - np->tx_dirty, np->tx_cur, tx_status); - - if (tx_status & OWN) - break; - - if (! (tx_status & DescPktOK)) { - netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL); - DBG ("Error transmitting packet, tx_status: %#08x\n", - tx_status); +/** + * 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 { - netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]); - DBG ("Success transmitting packet\n"); + 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 ); } - - np->tx[np->tx_dirty].cmdsts = 0; - np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE; - i = (i + 1) % TX_RING_SIZE; + natsemi->tx.cons++; } - - /* Process received packets - */ - rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts; - while ((rx_status & OWN)) { - rx_len = (rx_status & DSIZE) - CRC_SIZE; - - DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n", - np->rx_cur, rx_status, rx_len); - - if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) { - netdev_rx_err (netdev, NULL, -EINVAL); - - DBG ("natsemi_poll: Corrupted packet received!" - " Status = %#08x\n", - np->rx[np->rx_cur].cmdsts); - - } else { - - - /* If unable allocate space for this packet, - * try again next poll - */ - rx_iob = alloc_iob (rx_len); - if (! rx_iob) - goto end; - memcpy (iob_put (rx_iob, rx_len), - np->iobuf[np->rx_cur]->data, rx_len); - /* Add this packet to the receive queue. - */ - netdev_rx (netdev, rx_iob); +} + +/** + * 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 ); } - np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE; - np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC; - rx_status = np->rx[np->rx_cur].cmdsts; + natsemi->rx.cons++; } -end: - /* re-enable the potentially idle receive state machine +} + +/** + * 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. */ - outl (RxOn, np->ioaddr + ChipCmd); -} + 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: + iounmap ( natsemi->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} /** - * Enable/disable interrupts + * Remove PCI device * - * @v netdev Network device - * @v enable Non-zero for enable, zero for disable + * @v pci PCI device */ -static void natsemi_irq (struct net_device *netdev, int enable) -{ - struct natsemi_private *np = netdev->priv; +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 ); - outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0), - np->ioaddr + IntrMask); - outl ((enable ? 1 : 0), np->ioaddr + IntrEnable); + /* Reset card */ + natsemi_reset ( natsemi ); + + /* Free network device */ + iounmap ( natsemi->regs ); + 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", 0), + 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])), + .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ), .probe = natsemi_probe, .remove = natsemi_remove, }; diff --git a/roms/ipxe/src/drivers/net/natsemi.h b/roms/ipxe/src/drivers/net/natsemi.h index ae827ba39..7e8d6f800 100644 --- a/roms/ipxe/src/drivers/net/natsemi.h +++ b/roms/ipxe/src/drivers/net/natsemi.h @@ -1,232 +1,329 @@ -FILE_LICENCE ( GPL_ANY ); +#ifndef _NATSEMI_H +#define _NATSEMI_H -#define NATSEMI_HW_TIMEOUT 400 +/** @file + * + * National Semiconductor "MacPhyter" network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); -#define TX_RING_SIZE 4 -#define NUM_RX_DESC 4 -#define RX_BUF_SIZE 1536 -#define OWN 0x80000000 -#define DSIZE 0x00000FFF -#define CRC_SIZE 4 +#include +#include +#include -struct natsemi_tx { +/** 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 )); -struct natsemi_rx { - uint32_t link; +/** 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; - uint32_t bufptr; -}; + /** Extended status */ + uint32_t extsts; +} __attribute__ (( packed )); -struct natsemi_private { - unsigned short ioaddr; - unsigned short tx_cur; - unsigned short tx_dirty; - unsigned short rx_cur; - struct natsemi_tx tx[TX_RING_SIZE]; - struct natsemi_rx rx[NUM_RX_DESC]; - - /* need to add iobuf as we cannot free iobuf->data in close without this - * alternatively substracting sizeof(head) and sizeof(list_head) can also - * give the same. - */ - struct io_buffer *iobuf[NUM_RX_DESC]; - - /* netdev_tx_complete needs pointer to the iobuf of the data so as to free - * it from the memory. - */ - struct io_buffer *tx_iobuf[TX_RING_SIZE]; - struct spi_bit_basher spibit; - struct spi_device eeprom; - struct nvo_block nvo; +/** 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; }; -/* - * Support for fibre connections on Am79C874: - * This phy needs a special setup when connected to a fibre cable. - * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/22235.pdf - */ -#define PHYID_AM79C874 0x0022561b +/** Descriptor buffer size mask */ +#define NATSEMI_DESC_SIZE_MASK 0xfff -enum { - MII_MCTRL = 0x15, /* mode control register */ - MII_FX_SEL = 0x0001, /* 100BASE-FX (fiber) */ - MII_EN_SCRM = 0x0004, /* enable scrambler (tp) */ +/** 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 -/* values we might find in the silicon revision register */ -#define SRR_DP83815_C 0x0302 -#define SRR_DP83815_D 0x0403 -#define SRR_DP83816_A4 0x0504 -#define SRR_DP83816_A5 0x0505 +/** 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 */ -/* NATSEMI: 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. +/** Max DMA burst size (encoded value) + * + * This represents 256-byte bursts on 83815 controllers and 512-byte + * bursts on 83820 controllers. */ -enum register_offsets { - ChipCmd = 0x00, - ChipConfig = 0x04, - EECtrl = 0x08, - PCIBusCfg = 0x0C, - IntrStatus = 0x10, - IntrMask = 0x14, - IntrEnable = 0x18, - TxRingPtr = 0x20, - TxConfig = 0x24, - RxRingPtr = 0x30, - RxConfig = 0x34, - ClkRun = 0x3C, - WOLCmd = 0x40, - PauseCmd = 0x44, - RxFilterAddr = 0x48, - RxFilterData = 0x4C, - BootRomAddr = 0x50, - BootRomData = 0x54, - SiliconRev = 0x58, - StatsCtrl = 0x5C, - StatsData = 0x60, - RxPktErrs = 0x60, - RxMissed = 0x68, - RxCRCErrs = 0x64, - PCIPM = 0x44, - PhyStatus = 0xC0, - MIntrCtrl = 0xC4, - MIntrStatus = 0xC8, - - /* These are from the spec, around page 78... on a separate table. - */ - PGSEL = 0xCC, - PMDCSR = 0xE4, - TSTDAT = 0xFC, - DSPCFG = 0xF4, - SDCFG = 0x8C, - BasicControl = 0x80, - BasicStatus = 0x84 - -}; +#define NATSEMI_TXCFG_MXDMA_DEFAULT NATSEMI_TXCFG_MXDMA ( 0x7 ) -/* the values for the 'magic' registers above (PGSEL=1) */ -#define PMDCSR_VAL 0x189c /* enable preferred adaptation circuitry */ -#define TSTDAT_VAL 0x0 -#define DSPCFG_VAL 0x5040 -#define SDCFG_VAL 0x008c /* set voltage thresholds for Signal Detect */ -#define DSPCFG_LOCK 0x20 /* coefficient lock bit in DSPCFG */ -#define DSPCFG_COEF 0x1000 /* see coefficient (in TSTDAT) bit in DSPCFG */ -#define TSTDAT_FIXED 0xe8 /* magic number for bad coefficients */ +/** 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 ) -/* Bit in ChipCmd. +/** 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. */ -enum ChipCmdBits { - ChipReset = 0x100, - RxReset = 0x20, - TxReset = 0x10, - RxOff = 0x08, - RxOn = 0x04, - TxOff = 0x02, - TxOn = 0x01 -}; +#define NATSEMI_TXCFG_DRTH_DEFAULT NATSEMI_TXCFG_DRTH ( 1024 / 32 ) -enum ChipConfig_bits { - CfgPhyDis = 0x200, - CfgPhyRst = 0x400, - CfgExtPhy = 0x1000, - CfgAnegEnable = 0x2000, - CfgAneg100 = 0x4000, - CfgAnegFull = 0x8000, - CfgAnegDone = 0x8000000, - CfgFullDuplex = 0x20000000, - CfgSpeed100 = 0x40000000, - CfgLink = 0x80000000, -}; +/** Receive Descriptor Pointer */ +#define NATSEMI_RXDP 0x0030 +/** Receive Descriptor Pointer High Dword (64-bit) */ +#define NATSEMI_RXDP_HI_64 0x0034 -/* Bits in the RxMode register. - */ -enum rx_mode_bits { - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0xC0000000, - AcceptMulticast = 0x00200000, - AcceptAllMulticast = 0x20000000, - AcceptAllPhys = 0x10000000, - AcceptMyPhys = 0x08000000, - RxFilterEnable = 0x80000000 -}; +/** 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 */ ) -/* Bits in network_desc.status +/** 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. */ -enum desc_status_bits { - DescOwn = 0x80000000, - DescMore = 0x40000000, - DescIntr = 0x20000000, - DescNoCRC = 0x10000000, - DescPktOK = 0x08000000, - RxTooLong = 0x00400000 -}; +#define NATSEMI_RXCFG_MXDMA_DEFAULT NATSEMI_RXCFG_MXDMA ( 0x7 ) -/*Bits in Interrupt Mask register +/** 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. */ -enum Intr_mask_register_bits { - RxOk = 0x001, - RxErr = 0x004, - TxOk = 0x040, - TxErr = 0x100 -}; - -enum MIntrCtrl_bits { - MICRIntEn = 0x2, -}; +#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 -/* CFG bits [13:16] [18:23] */ -#define CFG_RESET_SAVE 0xfde000 -/* WCSR bits [0:4] [9:10] */ -#define WCSR_RESET_SAVE 0x61f -/* RFCR bits [20] [22] [27:31] */ -#define RFCR_RESET_SAVE 0xf8500000; - -/* Delay between EEPROM clock transitions. - No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need - a delay. */ -#define eeprom_delay(ee_addr) inl(ee_addr) - -enum EEPROM_Ctrl_Bits { - EE_ShiftClk = 0x04, - EE_DataIn = 0x01, - EE_ChipSelect = 0x08, - EE_DataOut = 0x02 +/** 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, }; -#define EE_Write0 (EE_ChipSelect) -#define EE_Write1 (EE_ChipSelect | EE_DataIn) +/** A National Semiconductor descriptor ring */ +struct natsemi_ring { + /** Descriptors */ + union natsemi_descriptor *desc; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), + /** Number of descriptors */ + unsigned int count; + /** Descriptor start address register */ + unsigned int reg; }; -/* EEPROM access , values are devices specific +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Descriptor start address register */ -#define EE_CS 0x08 /* EEPROM chip select */ -#define EE_SK 0x04 /* EEPROM shift clock */ -#define EE_DI 0x01 /* Data in */ -#define EE_DO 0x02 /* Data out */ +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; +} -/* Offsets within EEPROM (these are word offsets) - */ -#define EE_MAC 7 -#define EE_REG EECtrl - -static const uint8_t natsemi_ee_bits[] = { - [SPI_BIT_SCLK] = EE_SK, - [SPI_BIT_MOSI] = EE_DI, - [SPI_BIT_MISO] = EE_DO, - [SPI_BIT_SS(0)] = EE_CS, +/** 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/roms/ipxe/src/drivers/net/ns83820.c b/roms/ipxe/src/drivers/net/ns83820.c deleted file mode 100644 index 0b92a91b4..000000000 --- a/roms/ipxe/src/drivers/net/ns83820.c +++ /dev/null @@ -1,1007 +0,0 @@ -/************************************************************************** -* ns83820.c: Etherboot device driver for the National Semiconductor 83820 -* Written 2004 by Timothy Legge -* -* This program is free software; you can redistribute it and/or modify -* 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: -* ns83820.c by Benjamin LaHaise with contributions -* for Linux kernel 2.4.x. -* -* Linux Driver Version 0.20, 20020610 -* -* This development of this Etherboot driver was funded by: -* -* NXTV: http://www.nxtv.com/ -* -* REVISION HISTORY: -* ================ -* -* v1.0 02-16-2004 timlegge Initial port of Linux driver -* v1.1 02-19-2004 timlegge More rohbust transmit and poll -* -* Indent Options: indent -kr -i8 -***************************************************************************/ - -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 - -#if ARCH == ia64 /* Support 64-bit addressing */ -#define USE_64BIT_ADDR -#endif - -#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)) - -/* NIC specific static variables go here */ - -/* Global parameters. See MODULE_PARM near the bottom. */ -// static int ihr = 2; -static int reset_phy = 0; -static int lnksts = 0; /* CFG_LNKSTS bit polarity */ - -#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__) -#define USE_64BIT_ADDR "+" -#endif - -#if defined(USE_64BIT_ADDR) -#define TRY_DAC 1 -#else -#define TRY_DAC 0 -#endif - -/* tunables */ -#define RX_BUF_SIZE 1500 /* 8192 */ - -/* Must not exceed ~65000. */ -#define NR_RX_DESC 64 -#define NR_TX_DESC 1 - - /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */ -#define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6) /* rx/tx mac addr + type */ - -#define MIN_TX_DESC_FREE 8 - -/* register defines */ -#define CFGCS 0x04 - -#define CR_TXE 0x00000001 -#define CR_TXD 0x00000002 -/* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE - * The Receive engine skips one descriptor and moves - * onto the next one!! */ -#define CR_RXE 0x00000004 -#define CR_RXD 0x00000008 -#define CR_TXR 0x00000010 -#define CR_RXR 0x00000020 -#define CR_SWI 0x00000080 -#define CR_RST 0x00000100 - -#define PTSCR_EEBIST_FAIL 0x00000001 -#define PTSCR_EEBIST_EN 0x00000002 -#define PTSCR_EELOAD_EN 0x00000004 -#define PTSCR_RBIST_FAIL 0x000001b8 -#define PTSCR_RBIST_DONE 0x00000200 -#define PTSCR_RBIST_EN 0x00000400 -#define PTSCR_RBIST_RST 0x00002000 - -#define MEAR_EEDI 0x00000001 -#define MEAR_EEDO 0x00000002 -#define MEAR_EECLK 0x00000004 -#define MEAR_EESEL 0x00000008 -#define MEAR_MDIO 0x00000010 -#define MEAR_MDDIR 0x00000020 -#define MEAR_MDC 0x00000040 - -#define ISR_TXDESC3 0x40000000 -#define ISR_TXDESC2 0x20000000 -#define ISR_TXDESC1 0x10000000 -#define ISR_TXDESC0 0x08000000 -#define ISR_RXDESC3 0x04000000 -#define ISR_RXDESC2 0x02000000 -#define ISR_RXDESC1 0x01000000 -#define ISR_RXDESC0 0x00800000 -#define ISR_TXRCMP 0x00400000 -#define ISR_RXRCMP 0x00200000 -#define ISR_DPERR 0x00100000 -#define ISR_SSERR 0x00080000 -#define ISR_RMABT 0x00040000 -#define ISR_RTABT 0x00020000 -#define ISR_RXSOVR 0x00010000 -#define ISR_HIBINT 0x00008000 -#define ISR_PHY 0x00004000 -#define ISR_PME 0x00002000 -#define ISR_SWI 0x00001000 -#define ISR_MIB 0x00000800 -#define ISR_TXURN 0x00000400 -#define ISR_TXIDLE 0x00000200 -#define ISR_TXERR 0x00000100 -#define ISR_TXDESC 0x00000080 -#define ISR_TXOK 0x00000040 -#define ISR_RXORN 0x00000020 -#define ISR_RXIDLE 0x00000010 -#define ISR_RXEARLY 0x00000008 -#define ISR_RXERR 0x00000004 -#define ISR_RXDESC 0x00000002 -#define ISR_RXOK 0x00000001 - -#define TXCFG_CSI 0x80000000 -#define TXCFG_HBI 0x40000000 -#define TXCFG_MLB 0x20000000 -#define TXCFG_ATP 0x10000000 -#define TXCFG_ECRETRY 0x00800000 -#define TXCFG_BRST_DIS 0x00080000 -#define TXCFG_MXDMA1024 0x00000000 -#define TXCFG_MXDMA512 0x00700000 -#define TXCFG_MXDMA256 0x00600000 -#define TXCFG_MXDMA128 0x00500000 -#define TXCFG_MXDMA64 0x00400000 -#define TXCFG_MXDMA32 0x00300000 -#define TXCFG_MXDMA16 0x00200000 -#define TXCFG_MXDMA8 0x00100000 - -#define CFG_LNKSTS 0x80000000 -#define CFG_SPDSTS 0x60000000 -#define CFG_SPDSTS1 0x40000000 -#define CFG_SPDSTS0 0x20000000 -#define CFG_DUPSTS 0x10000000 -#define CFG_TBI_EN 0x01000000 -#define CFG_MODE_1000 0x00400000 -/* Ramit : Dont' ever use AUTO_1000, it never works and is buggy. - * Read the Phy response and then configure the MAC accordingly */ -#define CFG_AUTO_1000 0x00200000 -#define CFG_PINT_CTL 0x001c0000 -#define CFG_PINT_DUPSTS 0x00100000 -#define CFG_PINT_LNKSTS 0x00080000 -#define CFG_PINT_SPDSTS 0x00040000 -#define CFG_TMRTEST 0x00020000 -#define CFG_MRM_DIS 0x00010000 -#define CFG_MWI_DIS 0x00008000 -#define CFG_T64ADDR 0x00004000 -#define CFG_PCI64_DET 0x00002000 -#define CFG_DATA64_EN 0x00001000 -#define CFG_M64ADDR 0x00000800 -#define CFG_PHY_RST 0x00000400 -#define CFG_PHY_DIS 0x00000200 -#define CFG_EXTSTS_EN 0x00000100 -#define CFG_REQALG 0x00000080 -#define CFG_SB 0x00000040 -#define CFG_POW 0x00000020 -#define CFG_EXD 0x00000010 -#define CFG_PESEL 0x00000008 -#define CFG_BROM_DIS 0x00000004 -#define CFG_EXT_125 0x00000002 -#define CFG_BEM 0x00000001 - -#define EXTSTS_UDPPKT 0x00200000 -#define EXTSTS_TCPPKT 0x00080000 -#define EXTSTS_IPPKT 0x00020000 - -#define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0)) - -#define MIBC_MIBS 0x00000008 -#define MIBC_ACLR 0x00000004 -#define MIBC_FRZ 0x00000002 -#define MIBC_WRN 0x00000001 - -#define PCR_PSEN (1 << 31) -#define PCR_PS_MCAST (1 << 30) -#define PCR_PS_DA (1 << 29) -#define PCR_STHI_8 (3 << 23) -#define PCR_STLO_4 (1 << 23) -#define PCR_FFHI_8K (3 << 21) -#define PCR_FFLO_4K (1 << 21) -#define PCR_PAUSE_CNT 0xFFFE - -#define RXCFG_AEP 0x80000000 -#define RXCFG_ARP 0x40000000 -#define RXCFG_STRIPCRC 0x20000000 -#define RXCFG_RX_FD 0x10000000 -#define RXCFG_ALP 0x08000000 -#define RXCFG_AIRL 0x04000000 -#define RXCFG_MXDMA512 0x00700000 -#define RXCFG_DRTH 0x0000003e -#define RXCFG_DRTH0 0x00000002 - -#define RFCR_RFEN 0x80000000 -#define RFCR_AAB 0x40000000 -#define RFCR_AAM 0x20000000 -#define RFCR_AAU 0x10000000 -#define RFCR_APM 0x08000000 -#define RFCR_APAT 0x07800000 -#define RFCR_APAT3 0x04000000 -#define RFCR_APAT2 0x02000000 -#define RFCR_APAT1 0x01000000 -#define RFCR_APAT0 0x00800000 -#define RFCR_AARP 0x00400000 -#define RFCR_MHEN 0x00200000 -#define RFCR_UHEN 0x00100000 -#define RFCR_ULM 0x00080000 - -#define VRCR_RUDPE 0x00000080 -#define VRCR_RTCPE 0x00000040 -#define VRCR_RIPE 0x00000020 -#define VRCR_IPEN 0x00000010 -#define VRCR_DUTF 0x00000008 -#define VRCR_DVTF 0x00000004 -#define VRCR_VTREN 0x00000002 -#define VRCR_VTDEN 0x00000001 - -#define VTCR_PPCHK 0x00000008 -#define VTCR_GCHK 0x00000004 -#define VTCR_VPPTI 0x00000002 -#define VTCR_VGTI 0x00000001 - -#define CR 0x00 -#define CFG 0x04 -#define MEAR 0x08 -#define PTSCR 0x0c -#define ISR 0x10 -#define IMR 0x14 -#define IER 0x18 -#define IHR 0x1c -#define TXDP 0x20 -#define TXDP_HI 0x24 -#define TXCFG 0x28 -#define GPIOR 0x2c -#define RXDP 0x30 -#define RXDP_HI 0x34 -#define RXCFG 0x38 -#define PQCR 0x3c -#define WCSR 0x40 -#define PCR 0x44 -#define RFCR 0x48 -#define RFDR 0x4c - -#define SRR 0x58 - -#define VRCR 0xbc -#define VTCR 0xc0 -#define VDR 0xc4 -#define CCSR 0xcc - -#define TBICR 0xe0 -#define TBISR 0xe4 -#define TANAR 0xe8 -#define TANLPAR 0xec -#define TANER 0xf0 -#define TESR 0xf4 - -#define TBICR_MR_AN_ENABLE 0x00001000 -#define TBICR_MR_RESTART_AN 0x00000200 - -#define TBISR_MR_LINK_STATUS 0x00000020 -#define TBISR_MR_AN_COMPLETE 0x00000004 - -#define TANAR_PS2 0x00000100 -#define TANAR_PS1 0x00000080 -#define TANAR_HALF_DUP 0x00000040 -#define TANAR_FULL_DUP 0x00000020 - -#define GPIOR_GP5_OE 0x00000200 -#define GPIOR_GP4_OE 0x00000100 -#define GPIOR_GP3_OE 0x00000080 -#define GPIOR_GP2_OE 0x00000040 -#define GPIOR_GP1_OE 0x00000020 -#define GPIOR_GP3_OUT 0x00000004 -#define GPIOR_GP1_OUT 0x00000001 - -#define LINK_AUTONEGOTIATE 0x01 -#define LINK_DOWN 0x02 -#define LINK_UP 0x04 - - -#define __kick_rx() writel(CR_RXE, ns->base + CR) - -#define kick_rx() do { \ - DBG("kick_rx: maybe kicking\n"); \ - writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \ - if (ns->next_rx == ns->next_empty) \ - printf("uh-oh: next_rx == next_empty???\n"); \ - __kick_rx(); \ -} while(0) - - -#ifdef USE_64BIT_ADDR -#define HW_ADDR_LEN 8 -#else -#define HW_ADDR_LEN 4 -#endif - -#define CMDSTS_OWN 0x80000000 -#define CMDSTS_MORE 0x40000000 -#define CMDSTS_INTR 0x20000000 -#define CMDSTS_ERR 0x10000000 -#define CMDSTS_OK 0x08000000 -#define CMDSTS_LEN_MASK 0x0000ffff - -#define CMDSTS_DEST_MASK 0x01800000 -#define CMDSTS_DEST_SELF 0x00800000 -#define CMDSTS_DEST_MULTI 0x01000000 - -#define DESC_SIZE 8 /* Should be cache line sized */ - -#ifdef USE_64BIT_ADDR -struct ring_desc { - uint64_t link; - uint64_t bufptr; - u32 cmdsts; - u32 extsts; /* Extended status field */ -}; -#else -struct ring_desc { - u32 link; - u32 bufptr; - u32 cmdsts; - u32 extsts; /* Extended status field */ -}; -#endif - -/* Private Storage for the NIC */ -static struct ns83820_private { - u8 *base; - int up; - long idle; - u32 *next_rx_desc; - u16 next_rx, next_empty; - u32 cur_rx; - u32 *descs; - unsigned ihr; - u32 CFG_cache; - u32 MEAR_cache; - u32 IMR_cache; - int linkstate; - u16 tx_done_idx; - u16 tx_idx; - u16 tx_intr_idx; - u32 phy_descs; - u32 *tx_descs; - -} nsx; -static struct ns83820_private *ns; - -/* Define the TX and RX Descriptor and Buffers */ -struct { - struct ring_desc tx_ring[NR_TX_DESC] __attribute__ ((aligned(8))); - unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE]; - struct ring_desc rx_ring[NR_RX_DESC] __attribute__ ((aligned(8))); - unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE] - __attribute__ ((aligned(8))); -} ns83820_bufs __shared; -#define tx_ring ns83820_bufs.tx_ring -#define rx_ring ns83820_bufs.rx_ring -#define txb ns83820_bufs.txb -#define rxb ns83820_bufs.rxb - -static void phy_intr(struct nic *nic __unused) -{ - static char *speeds[] = - { "10", "100", "1000", "1000(?)", "1000F" }; - u32 cfg, new_cfg; - u32 tbisr, tanar, tanlpar; - int speed, fullduplex, newlinkstate; - - cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY; - if (ns->CFG_cache & CFG_TBI_EN) { - /* we have an optical transceiver */ - tbisr = readl(ns->base + TBISR); - tanar = readl(ns->base + TANAR); - tanlpar = readl(ns->base + TANLPAR); - DBG("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n", - tbisr, tanar, tanlpar); - - if ((fullduplex = (tanlpar & TANAR_FULL_DUP) - && (tanar & TANAR_FULL_DUP))) { - - /* both of us are full duplex */ - writel(readl(ns->base + TXCFG) - | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP, - ns->base + TXCFG); - writel(readl(ns->base + RXCFG) | RXCFG_RX_FD, - ns->base + RXCFG); - /* Light up full duplex LED */ - writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT, - ns->base + GPIOR); - - } else if (((tanlpar & TANAR_HALF_DUP) - && (tanar & TANAR_HALF_DUP)) - || ((tanlpar & TANAR_FULL_DUP) - && (tanar & TANAR_HALF_DUP)) - || ((tanlpar & TANAR_HALF_DUP) - && (tanar & TANAR_FULL_DUP))) { - - /* one or both of us are half duplex */ - writel((readl(ns->base + TXCFG) - & ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP, - ns->base + TXCFG); - writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD, - ns->base + RXCFG); - /* Turn off full duplex LED */ - writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT, - ns->base + GPIOR); - } - - speed = 4; /* 1000F */ - - } else { - /* we have a copper transceiver */ - new_cfg = - ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS); - - if (cfg & CFG_SPDSTS1) - new_cfg |= CFG_MODE_1000; - else - new_cfg &= ~CFG_MODE_1000; - - speed = ((cfg / CFG_SPDSTS0) & 3); - fullduplex = (cfg & CFG_DUPSTS); - - if (fullduplex) - new_cfg |= CFG_SB; - - if ((cfg & CFG_LNKSTS) && - ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) { - writel(new_cfg, ns->base + CFG); - ns->CFG_cache = new_cfg; - } - - ns->CFG_cache &= ~CFG_SPDSTS; - ns->CFG_cache |= cfg & CFG_SPDSTS; - } - - newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN; - - if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) { - printf("link now %s mbps, %s duplex and up.\n", - speeds[speed], fullduplex ? "full" : "half"); - } else if (newlinkstate & LINK_DOWN - && ns->linkstate != newlinkstate) { - printf("link now down.\n"); - } - ns->linkstate = newlinkstate; -} -static void ns83820_set_multicast(struct nic *nic __unused); -static void ns83820_setup_rx(struct nic *nic) -{ - unsigned i; - ns->idle = 1; - ns->next_rx = 0; - ns->next_rx_desc = ns->descs; - ns->next_empty = 0; - ns->cur_rx = 0; - - - for (i = 0; i < NR_RX_DESC; i++) { - rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]); - rx_ring[i].bufptr = - virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]); - rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE); - rx_ring[i].extsts = cpu_to_le32(0); - } -// No need to wrap the ring -// rx_ring[i].link = virt_to_le32desc(&rx_ring[0]); - writel(0, ns->base + RXDP_HI); - writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP); - - DBG("starting receiver\n"); - - writel(0x0001, ns->base + CCSR); - writel(0, ns->base + RFCR); - writel(0x7fc00000, ns->base + RFCR); - writel(0xffc00000, ns->base + RFCR); - - ns->up = 1; - - phy_intr(nic); - - /* Okay, let it rip */ - ns->IMR_cache |= ISR_PHY; - ns->IMR_cache |= ISR_RXRCMP; - //dev->IMR_cache |= ISR_RXERR; - //dev->IMR_cache |= ISR_RXOK; - ns->IMR_cache |= ISR_RXORN; - ns->IMR_cache |= ISR_RXSOVR; - ns->IMR_cache |= ISR_RXDESC; - ns->IMR_cache |= ISR_RXIDLE; - ns->IMR_cache |= ISR_TXDESC; - ns->IMR_cache |= ISR_TXIDLE; - - // No reason to enable interupts... - // writel(ns->IMR_cache, ns->base + IMR); - // writel(1, ns->base + IER); - ns83820_set_multicast(nic); - kick_rx(); -} - - -static void ns83820_do_reset(struct nic *nic __unused, u32 which) -{ - DBG("resetting chip...\n"); - writel(which, ns->base + CR); - do { - - } while (readl(ns->base + CR) & which); - DBG("okay!\n"); -} - -static void ns83820_reset(struct nic *nic) -{ - unsigned i; - DBG("ns83820_reset\n"); - - writel(0, ns->base + PQCR); - - ns83820_setup_rx(nic); - - for (i = 0; i < NR_TX_DESC; i++) { - tx_ring[i].link = 0; - tx_ring[i].bufptr = 0; - tx_ring[i].cmdsts = cpu_to_le32(0); - tx_ring[i].extsts = cpu_to_le32(0); - } - - ns->tx_idx = 0; - ns->tx_done_idx = 0; - writel(0, ns->base + TXDP_HI); - return; -} -static void ns83820_getmac(struct nic *nic __unused, u8 * mac) -{ - unsigned i; - for (i = 0; i < 3; i++) { - u32 data; - /* Read from the perfect match memory: this is loaded by - * the chip from the EEPROM via the EELOAD self test. - */ - writel(i * 2, ns->base + RFCR); - data = readl(ns->base + RFDR); - *mac++ = data; - *mac++ = data >> 8; - } -} - -static void ns83820_set_multicast(struct nic *nic __unused) -{ - u8 *rfcr = ns->base + RFCR; - u32 and_mask = 0xffffffff; - u32 or_mask = 0; - u32 val; - - /* Support Multicast */ - and_mask &= ~(RFCR_AAU | RFCR_AAM); - or_mask |= RFCR_AAM; - val = (readl(rfcr) & and_mask) | or_mask; - /* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */ - writel(val & ~RFCR_RFEN, rfcr); - writel(val, rfcr); - -} -static void ns83820_run_bist(struct nic *nic __unused, const char *name, - u32 enable, u32 done, u32 fail) -{ - int timed_out = 0; - long start; - u32 status; - int loops = 0; - - DBG("start %s\n", name); - - start = currticks(); - - writel(enable, ns->base + PTSCR); - for (;;) { - loops++; - status = readl(ns->base + PTSCR); - if (!(status & enable)) - break; - if (status & done) - break; - if (status & fail) - break; - if ((currticks() - start) >= HZ) { - timed_out = 1; - break; - } - } - - if (status & fail) - printf("%s failed! (0x%hX & 0x%hX)\n", name, (unsigned int) status, - (unsigned int) fail); - else if (timed_out) - printf("run_bist %s timed out! (%hX)\n", name, (unsigned int) status); - DBG("done %s in %d loops\n", name, loops); -} - -/************************************* -Check Link -*************************************/ -static void ns83820_check_intr(struct nic *nic) { - int i; - u32 isr = readl(ns->base + ISR); - if(ISR_PHY & isr) - phy_intr(nic); - if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr) - kick_rx(); - for (i = 0; i < NR_RX_DESC; i++) { - if (rx_ring[i].cmdsts == CMDSTS_OWN) { -// rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]); - rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE); - } - } -} -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int ns83820_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 cmdsts; - int entry = ns->cur_rx; - - ns83820_check_intr(nic); - - cmdsts = le32_to_cpu(rx_ring[entry].cmdsts); - - if ( ! ( (CMDSTS_OWN & (cmdsts)) && (cmdsts != (CMDSTS_OWN)) ) ) - return 0; - - if ( ! retrieve ) return 1; - - if (! (CMDSTS_OK & cmdsts) ) - return 0; - - nic->packetlen = cmdsts & 0xffff; - memcpy(nic->packet, - rxb + (entry * REAL_RX_BUF_SIZE), - nic->packetlen); - // rx_ring[entry].link = 0; - rx_ring[entry].cmdsts = cpu_to_le32(CMDSTS_OWN); - - ns->cur_rx = (ns->cur_rx + 1) % NR_RX_DESC; - - if (ns->cur_rx == 0) /* We have wrapped the ring */ - kick_rx(); - - return 1; -} - -static inline void kick_tx(struct nic *nic __unused) -{ - DBG("kick_tx\n"); - writel(CR_TXE, ns->base + CR); -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static void ns83820_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 */ - - u16 nstype; - u32 cmdsts, extsts; - int cur_tx = 0; - u32 isr = readl(ns->base + ISR); - if (ISR_TXIDLE & isr) - kick_tx(nic); - /* point to the current txb incase multiple tx_rings are used */ - 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 */ - extsts = 0; - extsts |= EXTSTS_UDPPKT; - - tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb); - tx_ring[cur_tx].extsts = cpu_to_le32(extsts); - - cmdsts = cpu_to_le32(0); - cmdsts |= cpu_to_le32(CMDSTS_OWN | s); - tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts); - - writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP); - kick_tx(nic); -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void ns83820_disable ( struct nic *nic ) { - - /* 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. - */ - /* disable interrupts */ - writel(0, ns->base + IMR); - writel(0, ns->base + IER); - readl(ns->base + IER); - - ns->up = 0; - - ns83820_do_reset(nic, CR_RST); - - ns->IMR_cache &= - ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY | - ISR_RXIDLE); - writel(ns->IMR_cache, ns->base + IMR); - - /* touch the pci bus... */ - readl(ns->base + IMR); - - /* assumes the transmitter is already disabled and reset */ - writel(0, ns->base + RXDP_HI); - writel(0, ns->base + RXDP); -} - -/************************************************************************** -IRQ - Enable, Disable, or Force interrupts -***************************************************************************/ -static void ns83820_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 ns83820_operations = { - .connect = dummy_connect, - .poll = ns83820_poll, - .transmit = ns83820_transmit, - .irq = ns83820_irq, - -}; - -static struct pci_device_id ns83820_nics[] = { - PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820", 0), -}; - -PCI_DRIVER ( ns83820_driver, ns83820_nics, PCI_NO_CLASS ); - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -***************************************************************************/ - -#define board_found 1 -#define valid_link 0 -static int ns83820_probe ( struct nic *nic, struct pci_device *pci ) { - - long addr; - int using_dac = 0; - - if (pci->ioaddr == 0) - return 0; - - printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n", - pci->id->name, pci->vendor, pci->device); - - /* point to private storage */ - ns = &nsx; - - adjust_pci_device(pci); - - addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1); - - ns->base = ioremap(addr, (1UL << 12)); - - if (!ns->base) - return 0; - - nic->irqno = 0; - nic->ioaddr = pci->ioaddr & ~3; - - /* disable interrupts */ - writel(0, ns->base + IMR); - writel(0, ns->base + IER); - readl(ns->base + IER); - - ns->IMR_cache = 0; - - ns83820_do_reset(nic, CR_RST); - - /* Must reset the ram bist before running it */ - writel(PTSCR_RBIST_RST, ns->base + PTSCR); - ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN, - PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL); - ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0, - PTSCR_EEBIST_FAIL); - ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0); - - /* I love config registers */ - ns->CFG_cache = readl(ns->base + CFG); - - if ((ns->CFG_cache & CFG_PCI64_DET)) { - printf("%s: detected 64 bit PCI data bus.\n", pci->id->name); - /*dev->CFG_cache |= CFG_DATA64_EN; */ - if (!(ns->CFG_cache & CFG_DATA64_EN)) - printf - ("%s: EEPROM did not enable 64 bit bus. Disabled.\n", - pci->id->name); - } else - ns->CFG_cache &= ~(CFG_DATA64_EN); - - ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS | - CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 | - CFG_M64ADDR); - ns->CFG_cache |= - CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS | - CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL; - ns->CFG_cache |= CFG_REQALG; - ns->CFG_cache |= CFG_POW; - ns->CFG_cache |= CFG_TMRTEST; - - /* When compiled with 64 bit addressing, we must always enable - * the 64 bit descriptor format. - */ -#ifdef USE_64BIT_ADDR - ns->CFG_cache |= CFG_M64ADDR; -#endif - -//FIXME: Enable section on dac or remove this - if (using_dac) - ns->CFG_cache |= CFG_T64ADDR; - - /* Big endian mode does not seem to do what the docs suggest */ - ns->CFG_cache &= ~CFG_BEM; - - /* setup optical transceiver if we have one */ - if (ns->CFG_cache & CFG_TBI_EN) { - DBG("%s: enabling optical transceiver\n", pci->id->name); - writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR); - - /* setup auto negotiation feature advertisement */ - writel(readl(ns->base + TANAR) - | TANAR_HALF_DUP | TANAR_FULL_DUP, - ns->base + TANAR); - - /* start auto negotiation */ - writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN, - ns->base + TBICR); - writel(TBICR_MR_AN_ENABLE, ns->base + TBICR); - ns->linkstate = LINK_AUTONEGOTIATE; - - ns->CFG_cache |= CFG_MODE_1000; - } - writel(ns->CFG_cache, ns->base + CFG); - DBG("CFG: %hX\n", ns->CFG_cache); - - /* FIXME: reset_phy is defaulted to 0, should we reset anyway? */ - if (reset_phy) { - DBG("%s: resetting phy\n", pci->id->name); - writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG); - writel(ns->CFG_cache, ns->base + CFG); - } -#if 0 /* Huh? This sets the PCI latency register. Should be done via - * the PCI layer. FIXME. - */ - if (readl(dev->base + SRR)) - writel(readl(dev->base + 0x20c) | 0xfe00, - dev->base + 0x20c); -#endif - - /* Note! The DMA burst size interacts with packet - * transmission, such that the largest packet that - * can be transmitted is 8192 - FLTH - burst size. - * If only the transmit fifo was larger... - */ - /* Ramit : 1024 DMA is not a good idea, it ends up banging - * some DELL and COMPAQ SMP systems */ - writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512 - | ((1600 / 32) * 0x100), ns->base + TXCFG); - - /* Set Rx to full duplex, don't accept runt, errored, long or length - * range errored packets. Use 512 byte DMA. - */ - /* Ramit : 1024 DMA is not a good idea, it ends up banging - * some DELL and COMPAQ SMP systems - * Turn on ALP, only we are accpeting Jumbo Packets */ - writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD - | RXCFG_STRIPCRC - //| RXCFG_ALP - | (RXCFG_MXDMA512) | 0, ns->base + RXCFG); - - /* Disable priority queueing */ - writel(0, ns->base + PQCR); - - /* Enable IP checksum validation and detetion of VLAN headers. - * Note: do not set the reject options as at least the 0x102 - * revision of the chip does not properly accept IP fragments - * at least for UDP. - */ - /* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since - * the MAC it calculates the packetsize AFTER stripping the VLAN - * header, and if a VLAN Tagged packet of 64 bytes is received (like - * a ping with a VLAN header) then the card, strips the 4 byte VLAN - * tag and then checks the packet size, so if RXCFG_ARP is not enabled, - * it discrards it!. These guys...... - */ - writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR); - - /* Enable per-packet TCP/UDP/IP checksumming */ - writel(VTCR_PPCHK, ns->base + VTCR); - - /* Ramit : Enable async and sync pause frames */ -// writel(0, ns->base + PCR); - writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K | - PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT), - ns->base + PCR); - - /* Disable Wake On Lan */ - writel(0, ns->base + WCSR); - - ns83820_getmac(nic, nic->node_addr); - - if (using_dac) { - DBG("%s: using 64 bit addressing.\n", pci->id->name); - } - - DBG("%s: DP83820 %d.%d: io=%#04lx\n", - pci->id->name, - (unsigned) readl(ns->base + SRR) >> 8, - (unsigned) readl(ns->base + SRR) & 0xff, - pci->ioaddr); - -#ifdef PHY_CODE_IS_FINISHED - ns83820_probe_phy(dev); -#endif - - ns83820_reset(nic); - /* point to NIC specific routines */ - nic->nic_op = &ns83820_operations; - return 1; -} - -DRIVER ( "NS83820/PCI", nic_driver, pci_driver, ns83820_driver, - ns83820_probe, ns83820_disable ); - -/* - * Local variables: - * c-basic-offset: 8 - * c-indent-level: 8 - * tab-width: 8 - * End: - */ diff --git a/roms/ipxe/src/drivers/net/p80211hdr.h b/roms/ipxe/src/drivers/net/p80211hdr.h index 835467122..110905c5f 100644 --- a/roms/ipxe/src/drivers/net/p80211hdr.h +++ b/roms/ipxe/src/drivers/net/p80211hdr.h @@ -258,7 +258,7 @@ typedef union p80211_hdr /*================================================================*/ /* Function Declarations */ -/* Frame and header lenght macros */ +/* Frame and header length macros */ #define WLAN_CTL_FRAMELEN(fstype) (\ (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \ diff --git a/roms/ipxe/src/drivers/net/pcnet32.c b/roms/ipxe/src/drivers/net/pcnet32.c index d6da3c5e5..26633a248 100644 --- a/roms/ipxe/src/drivers/net/pcnet32.c +++ b/roms/ipxe/src/drivers/net/pcnet32.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ @@ -406,7 +407,7 @@ pcnet32_chip_detect ( struct pcnet32_private *priv ) /* * 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 + * one for latency - although on PCI this isn't 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. */ diff --git a/roms/ipxe/src/drivers/net/pcnet32.h b/roms/ipxe/src/drivers/net/pcnet32.h index bd03cbc01..5e4492ef9 100644 --- a/roms/ipxe/src/drivers/net/pcnet32.h +++ b/roms/ipxe/src/drivers/net/pcnet32.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/roms/ipxe/src/drivers/net/phantom/nx_bitops.h b/roms/ipxe/src/drivers/net/phantom/nx_bitops.h index 40686326a..15f3d3767 100644 --- a/roms/ipxe/src/drivers/net/phantom/nx_bitops.h +++ b/roms/ipxe/src/drivers/net/phantom/nx_bitops.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/phantom/phantom.c b/roms/ipxe/src/drivers/net/phantom/phantom.c index a55319ea6..1c798e04a 100644 --- a/roms/ipxe/src/drivers/net/phantom/phantom.c +++ b/roms/ipxe/src/drivers/net/phantom/phantom.c @@ -14,7 +14,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/phantom/phantom.h b/roms/ipxe/src/drivers/net/phantom/phantom.h index a55f32fbb..1647168ba 100644 --- a/roms/ipxe/src/drivers/net/phantom/phantom.h +++ b/roms/ipxe/src/drivers/net/phantom/phantom.h @@ -17,7 +17,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/phantom/phantom_hw.h b/roms/ipxe/src/drivers/net/phantom/phantom_hw.h index 950f36a4f..7dfff52b2 100644 --- a/roms/ipxe/src/drivers/net/phantom/phantom_hw.h +++ b/roms/ipxe/src/drivers/net/phantom/phantom_hw.h @@ -17,7 +17,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/net/r8169.c b/roms/ipxe/src/drivers/net/r8169.c deleted file mode 100644 index 13ab65ba5..000000000 --- a/roms/ipxe/src/drivers/net/r8169.c +++ /dev/null @@ -1,2232 +0,0 @@ -/* - * Copyright (c) 2008 Marty Connor - * Copyright (c) 2008 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. - * - * This driver is based on rtl8169 data sheets and work by: - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "r8169.h" - -/*** Low level hardware routines ***/ - -static void mdio_write(void *ioaddr, int reg_addr, int value) -{ - int i; - - DBGP ( "mdio_write\n" ); - - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed writing to the specified - * MII register. - */ - if (!(RTL_R32(PHYAR) & 0x80000000)) - break; - udelay(25); - } -} - -static int mdio_read(void *ioaddr, int reg_addr) -{ - int i, value = -1; - - DBGP ( "mdio_read\n" ); - - RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); - - for (i = 20; i > 0; i--) { - /* - * Check if the RTL8169 has completed retrieving data from - * the specified MII register. - */ - if (RTL_R32(PHYAR) & 0x80000000) { - value = RTL_R32(PHYAR) & 0xffff; - break; - } - udelay(25); - } - return value; -} - -static void mdio_patch(void *ioaddr, int reg_addr, int value) -{ - DBGP ( "mdio_patch\n" ); - - mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); -} - -static void rtl_ephy_write(void *ioaddr, int reg_addr, int value) -{ - unsigned int i; - - DBGP ( "rtl_ephy_write\n" ); - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) - break; - udelay(10); - } -} - -static u16 rtl_ephy_read(void *ioaddr, int reg_addr) -{ - u16 value = 0xffff; - unsigned int i; - - DBGP ( "rtl_ephy_read\n" ); - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { - value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; - break; - } - udelay(10); - } - - return value; -} - -static void rtl_csi_write(void *ioaddr, int addr, int value) -{ - unsigned int i; - - DBGP ( "rtl_csi_write\n" ); - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) - break; - udelay(10); - } -} - -static u32 rtl_csi_read(void *ioaddr, int addr) -{ - u32 value = ~0x00; - unsigned int i; - - DBGP ( "rtl_csi_read\n" ); - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - for (i = 0; i < 100; i++) { - if (RTL_R32(CSIAR) & CSIAR_FLAG) { - value = RTL_R32(CSIDR); - break; - } - udelay(10); - } - - return value; -} - -static void rtl8169_irq_mask_and_ack(void *ioaddr) -{ - DBGP ( "rtl8169_irq_mask_and_ack\n" ); - - RTL_W16(IntrMask, 0x0000); - - RTL_W16(IntrStatus, 0xffff); -} - -static unsigned int rtl8169_tbi_reset_pending(void *ioaddr) -{ - DBGP ( "rtl8169_tbi_reset_pending\n" ); - - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(void *ioaddr) -{ - DBGP ( "rtl8169_xmii_reset_pending\n" ); - - return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void *ioaddr) -{ - DBGP ( "rtl8169_tbi_link_ok\n" ); - - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void *ioaddr) -{ - DBGP ( "rtl8169_xmii_link_ok\n" ); - - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(void *ioaddr) -{ - DBGP ( "rtl8169_tbi_reset_enable\n" ); - - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(void *ioaddr) -{ - unsigned int val; - - DBGP ( "rtl8169_xmii_reset_enable\n" ); - - val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET; - mdio_write(ioaddr, MII_BMCR, val & 0xffff); -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - DBGP ( "rtl8169_set_speed_tbi\n" ); - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - DBG ( "incorrect speed setting refused in TBI mode\n" ); - ret = -EOPNOTSUPP; - } - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - int auto_nego, giga_ctrl; - - DBGP ( "rtl8169_set_speed_xmii\n" ); - - auto_nego = mdio_read(ioaddr, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl = mdio_read(ioaddr, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - if (autoneg == AUTONEG_ENABLE) { - auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else { - if (speed == SPEED_10) - auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL; - else if (speed == SPEED_100) - auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL; - else if (speed == SPEED_1000) - giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - - if (duplex == DUPLEX_HALF) - auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL); - - if (duplex == DUPLEX_FULL) - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF); - - /* This tweak comes straight from Realtek's driver. */ - if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) && - ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16))) { - auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA; - } - } - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || - (tp->mac_version == RTL_GIGA_MAC_VER_08) || - (tp->mac_version == RTL_GIGA_MAC_VER_09) || - (tp->mac_version == RTL_GIGA_MAC_VER_10) || - (tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_14) || - (tp->mac_version == RTL_GIGA_MAC_VER_15) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF))) { - DBG ( "PHY does not support 1000Mbps.\n" ); - } - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - } - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || - (tp->mac_version == RTL_GIGA_MAC_VER_12) || - (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { - /* - * Wake up the PHY. - * Vendor specific (0x1f) and reserved (0x0e) MII registers. - */ - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_write(ioaddr, 0x0e, 0x0000); - } - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - mdio_write(ioaddr, MII_ADVERTISE, auto_nego); - mdio_write(ioaddr, MII_CTRL1000, giga_ctrl); - mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - DBGP ( "rtl8169_set_speed\n" ); - - ret = tp->set_speed(dev, autoneg, speed, duplex); - - return ret; -} - -static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, - int bitnum, int bitval) -{ - int val; - - DBGP ( "rtl8169_write_gmii_reg_bit\n" ); - - val = mdio_read(ioaddr, reg); - val = (bitval == 1) ? - val | (bitval << bitnum) : val & ~(0x0001 << bitnum); - mdio_write(ioaddr, reg, val & 0xffff); -} - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - void *ioaddr) -{ - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - const struct { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168D family. */ - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_25 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3ca00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */ - }, *p = mac_info; - u32 reg; - - DBGP ( "rtl8169_get_mac_version\n" ); - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - DBG ( "tp->mac_version = %d\n", tp->mac_version ); - - if (p->mask == 0x00000000) { - DBG ( "unknown MAC (%08x)\n", reg ); - } -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_phy_write(void *ioaddr, struct phy_reg *regs, int len) -{ - DBGP ( "rtl_phy_write\n" ); - - while (len-- > 0) { - mdio_write(ioaddr, regs->reg, regs->val); - regs++; - } -} - -static void rtl8169s_hw_phy_config(void *ioaddr) -{ - struct { - u16 regs[5]; /* Beware of bit-sign propagation */ - } phy_magic[5] = { { - { 0x0000, //w 4 15 12 0 - 0x00a1, //w 3 15 0 00a1 - 0x0008, //w 2 15 0 0008 - 0x1020, //w 1 15 0 1020 - 0x1000 } },{ //w 0 15 0 1000 - { 0x7000, //w 4 15 12 7 - 0xff41, //w 3 15 0 ff41 - 0xde60, //w 2 15 0 de60 - 0x0140, //w 1 15 0 0140 - 0x0077 } },{ //w 0 15 0 0077 - { 0xa000, //w 4 15 12 a - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xfa00 } },{ //w 0 15 0 fa00 - { 0xb000, //w 4 15 12 b - 0xff41, //w 3 15 0 ff41 - 0xde20, //w 2 15 0 de20 - 0x0140, //w 1 15 0 0140 - 0x00bb } },{ //w 0 15 0 00bb - { 0xf000, //w 4 15 12 f - 0xdf01, //w 3 15 0 df01 - 0xdf20, //w 2 15 0 df20 - 0xff95, //w 1 15 0 ff95 - 0xbf00 } //w 0 15 0 bf00 - } - }, *p = phy_magic; - unsigned int i; - - DBGP ( "rtl8169s_hw_phy_config\n" ); - - mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1 - mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000 - mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - - for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) { - int val, pos = 4; - - val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff); - mdio_write(ioaddr, pos, val); - while (--pos >= 0) - mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff); - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1 - rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0 - } - mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0 -} - -static void rtl8169sb_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8169sb_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - mdio_write(ioaddr, 0x1f, 0x0001); - mdio_patch(ioaddr, 0x16, 1 << 0); - - DBGP ( "rtl8168bb_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8168bef_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8168cp_1_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8168cp_2_hw_phy_config\n" ); - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - DBGP ( "rtl8168c_1_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8168c_2_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8168c_3_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - mdio_patch(ioaddr, 0x16, 1 << 0); - mdio_patch(ioaddr, 0x14, 1 << 5); - mdio_patch(ioaddr, 0x0d, 1 << 5); - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(void *ioaddr) -{ - DBGP ( "rtl8168c_4_hw_phy_config\n" ); - - rtl8168c_3_hw_phy_config(ioaddr); -} - -static void rtl8168d_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init_0[] = { - { 0x1f, 0x0001 }, - { 0x09, 0x2770 }, - { 0x08, 0x04d0 }, - { 0x0b, 0xad15 }, - { 0x0c, 0x5bf0 }, - { 0x1c, 0xf101 }, - { 0x1f, 0x0003 }, - { 0x14, 0x94d7 }, - { 0x12, 0xf4d6 }, - { 0x09, 0xca0f }, - { 0x1f, 0x0002 }, - { 0x0b, 0x0b10 }, - { 0x0c, 0xd1f7 }, - { 0x1f, 0x0002 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0000 }, - { 0x14, 0x0060 }, - { 0x1f, 0x0000 }, - { 0x0d, 0xf8a0 }, - { 0x1f, 0x0005 }, - { 0x05, 0xffc2 } - }; - - DBGP ( "rtl8168d_hw_phy_config\n" ); - - rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (mdio_read(ioaddr, 0x06) == 0xc400) { - struct phy_reg phy_reg_init_1[] = { - { 0x1f, 0x0005 }, - { 0x01, 0x0300 }, - { 0x1f, 0x0000 }, - { 0x11, 0x401c }, - { 0x16, 0x4100 }, - { 0x1f, 0x0005 }, - { 0x07, 0x0010 }, - { 0x05, 0x83dc }, - { 0x06, 0x087d }, - { 0x05, 0x8300 }, - { 0x06, 0x0101 }, - { 0x06, 0x05f8 }, - { 0x06, 0xf9fa }, - { 0x06, 0xfbef }, - { 0x06, 0x79e2 }, - { 0x06, 0x835f }, - { 0x06, 0xe0f8 }, - { 0x06, 0x9ae1 }, - { 0x06, 0xf89b }, - { 0x06, 0xef31 }, - { 0x06, 0x3b65 }, - { 0x06, 0xaa07 }, - { 0x06, 0x81e4 }, - { 0x06, 0xf89a }, - { 0x06, 0xe5f8 }, - { 0x06, 0x9baf }, - { 0x06, 0x06ae }, - { 0x05, 0x83dc }, - { 0x06, 0x8300 }, - }; - - rtl_phy_write(ioaddr, phy_reg_init_1, - ARRAY_SIZE(phy_reg_init_1)); - } - - mdio_write(ioaddr, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(void *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - DBGP ( "rtl8102e_hw_phy_config\n" ); - - mdio_write(ioaddr, 0x1f, 0x0000); - mdio_patch(ioaddr, 0x11, 1 << 12); - mdio_patch(ioaddr, 0x19, 1 << 13); - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - - DBGP ( "rtl_hw_phy_config\n" ); - - DBG ( "mac_version = 0x%02x\n", tp->mac_version ); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(ioaddr); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_hw_phy_config(ioaddr); - break; - - default: - break; - } -} - -static void rtl8169_phy_reset(struct net_device *dev __unused, - struct rtl8169_private *tp) -{ - void *ioaddr = tp->mmio_addr; - unsigned int i; - - DBGP ( "rtl8169_phy_reset\n" ); - - tp->phy_reset_enable(ioaddr); - for (i = 0; i < 100; i++) { - if (!tp->phy_reset_pending(ioaddr)) - return; - mdelay ( 1 ); - } - DBG ( "PHY reset failed.\n" ); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void *ioaddr = tp->mmio_addr; - - DBGP ( "rtl8169_init_phy\n" ); - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - DBG ( "Set MAC Reg C+CR Offset 0x82h = 0x01h\n" ); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - DBG ( "Set MAC Reg C+CR Offset 0x82h = 0x01h\n" ); - RTL_W8(0x82, 0x01); - DBG ( "Set PHY Reg 0x0bh = 0x00h\n" ); - mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - /* - * rtl8169_set_speed_xmii takes good care of the Fast Ethernet - * only 8101. Don't panic. - */ - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - - if ((RTL_R8(PHYstatus) & TBI_Enable)) - DBG ( "TBI auto-negotiating\n" ); -} - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 intr_event; - u16 napi_event; - unsigned features; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, - .features = RTL_FEATURE_GMII - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, - } -}; - -static void rtl8169_hw_reset(void *ioaddr) -{ - DBGP ( "rtl8169_hw_reset\n" ); - - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); - - /* Reset the chipset */ - RTL_W8(ChipCmd, CmdReset); - - /* PCI commit */ - RTL_R8(ChipCmd); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void *ioaddr = tp->mmio_addr; - u32 cfg = rtl8169_rx_config; - - DBGP ( "rtl_set_rx_tx_config_registers\n" ); - - cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, cfg); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_soft_reset ( struct net_device *dev ) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - unsigned int i; - - DBGP ( "rtl_hw_soft_reset\n" ); - - /* Soft reset the chip. */ - RTL_W8(ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 0; i < 100; i++) { - if ((RTL_R8(ChipCmd) & CmdReset) == 0) - break; - mdelay ( 1 ); - } - - if ( i == 100 ) { - DBG ( "Reset Failed! (> 100 iterations)\n" ); - } -} - -static void rtl_hw_start ( struct net_device *dev ) -{ - struct rtl8169_private *tp = netdev_priv ( dev ); - - DBGP ( "rtl_hw_start\n" ); - - /* Soft reset NIC */ - rtl_soft_reset ( dev ); - - tp->hw_start ( dev ); -} - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void *ioaddr) -{ - DBGP ( "rtl_set_rx_tx_desc_registers\n" ); - - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32 ( TxDescStartAddrHigh, 0 ); - RTL_W32 ( TxDescStartAddrLow, virt_to_bus ( tp->tx_base ) ); - RTL_W32 ( RxDescAddrHigh, 0 ); - RTL_W32 ( RxDescAddrLow, virt_to_bus ( tp->rx_base ) ); -} - -static u16 rtl_rw_cpluscmd(void *ioaddr) -{ - u16 cmd; - - DBGP ( "rtl_rw_cpluscmd\n" ); - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void *ioaddr) -{ - DBGP ( "rtl_set_rx_max_size\n" ); - - RTL_W16 ( RxMaxSize, RX_BUF_SIZE ); -} - -static void rtl8169_set_magic_reg(void *ioaddr, unsigned mac_version) -{ - struct { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }, *p = cfg2_info; - unsigned int i; - u32 clk; - - DBGP ( "rtl8169_set_magic_reg\n" ); - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_set_rx_mode ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - u32 tmp; - - DBGP ( "rtl_set_rx_mode\n" ); - - /* Accept all Multicast Packets */ - - RTL_W32 ( MAR0 + 0, 0xffffffff ); - RTL_W32 ( MAR0 + 4, 0xffffffff ); - - tmp = rtl8169_rx_config | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - ( RTL_R32 ( RxConfig ) & rtl_chip_info[tp->chipset].RxConfigMask ); - - RTL_W32 ( RxConfig, tmp ); -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - struct pci_device *pdev = tp->pci_dev; - - DBGP ( "rtl_hw_start_8169\n" ); - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03)) { - DBG ( "Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n" ); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - // RTL_W16(IntrMask, tp->intr_event); -} - -static void rtl_tx_performance_tweak(struct pci_device *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - DBGP ( "rtl_tx_performance_tweak\n" ); - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - -static void rtl_csi_access_enable(void *ioaddr) -{ - u32 csi; - - DBGP ( "rtl_csi_access_enable\n" ); - - csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; - rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(void *ioaddr, struct ephy_info *e, int len) -{ - u16 w; - - DBGP ( "rtl_ephy_init\n" ); - - while (len-- > 0) { - w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(ioaddr, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_device *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - DBGP ( "rtl_disable_clock_request\n" ); - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl); - ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN; - pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl); - } -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168bb\n" ); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - rtl_tx_performance_tweak(pdev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void rtl_hw_start_8168bef(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168bef\n" ); - - rtl_hw_start_8168bb(ioaddr, pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "__rtl_hw_start_8168cp\n" ); - - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(void *ioaddr, struct pci_device *pdev) -{ - static struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - DBGP ( "rtl_hw_start_8168cp_1\n" ); - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168cp_2(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168cp_2\n" ); - - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168cp_3\n" ); - - rtl_csi_access_enable(ioaddr); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(void *ioaddr, struct pci_device *pdev) -{ - static struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - DBGP ( "rtl_hw_start_8168c_1\n" ); - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_2(void *ioaddr, struct pci_device *pdev) -{ - static struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - DBGP ( "rtl_hw_start_8168c_2\n" ); - - rtl_csi_access_enable(ioaddr); - - rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_3(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168c_3\n" ); - - rtl_hw_start_8168c_2(ioaddr, pdev); -} - -static void rtl_hw_start_8168c_4(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168c_4\n" ); - - rtl_csi_access_enable(ioaddr); - - __rtl_hw_start_8168cp(ioaddr, pdev); -} - -static void rtl_hw_start_8168d(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8168d\n" ); - - rtl_csi_access_enable(ioaddr); - - rtl_disable_clock_request(pdev); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - struct pci_device *pdev = tp->pci_dev; - - DBGP ( "rtl_hw_start_8168\n" ); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_mode(dev); - - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_25: - rtl_hw_start_8168d(ioaddr, pdev); - break; - - default: - DBG ( "Unknown chipset (mac_version = %d).\n", - tp->mac_version ); - break; - } - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - // RTL_W16(IntrMask, tp->intr_event); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_half_dup | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - PCIDAC | \ - PCIMulRW) - -static void rtl_hw_start_8102e_1(void *ioaddr, struct pci_device *pdev) -{ - static struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - DBGP ( "rtl_hw_start_8102e_1\n" ); - - rtl_csi_access_enable(ioaddr); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); - - rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8102e_2\n" ); - - rtl_csi_access_enable(ioaddr); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8102e_3(void *ioaddr, struct pci_device *pdev) -{ - DBGP ( "rtl_hw_start_8102e_3\n" ); - - rtl_hw_start_8102e_2(ioaddr, pdev); - - rtl_ephy_write(ioaddr, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - struct pci_device *pdev = tp->pci_dev; - - DBGP ( "rtl_hw_start_8101\n" ); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || - (tp->mac_version == RTL_GIGA_MAC_VER_16)) { - int cap = tp->pcie_cap; - - if (cap) { - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - } - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(ioaddr, pdev); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(ioaddr, pdev); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(EarlyTxThres, EarlyTxThld); - - rtl_set_rx_max_size(ioaddr); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_R8(IntrMask); - - rtl_set_rx_mode(dev); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - // RTL_W16(IntrMask, tp->intr_event); -} - -/*** iPXE API Support Routines ***/ - -/** - * setup_tx_resources - allocate tx resources (descriptors) - * - * @v tp Driver private storage - * - * @ret rc Returns 0 on success, negative on failure - **/ -static int -rtl8169_setup_tx_resources ( struct rtl8169_private *tp ) -{ - DBGP ( "rtl8169_setup_tx_resources\n" ); - - tp->tx_base = malloc_dma ( R8169_TX_RING_BYTES, TX_RING_ALIGN ); - - if ( ! tp->tx_base ) { - return -ENOMEM; - } - - memset ( tp->tx_base, 0, R8169_TX_RING_BYTES ); - - DBG ( "tp->tx_base = %#08lx\n", virt_to_bus ( tp->tx_base ) ); - - tp->tx_fill_ctr = 0; - tp->tx_curr = 0; - tp->tx_tail = 0; - - return 0; -} - -static void -rtl8169_process_tx_packets ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - - uint32_t tx_status; - struct TxDesc *tx_curr_desc; - - DBGP ( "rtl8169_process_tx_packets\n" ); - - while ( tp->tx_tail != tp->tx_curr ) { - - tx_curr_desc = tp->tx_base + tp->tx_tail; - - tx_status = tx_curr_desc->opts1; - - DBG2 ( "Before DescOwn check tx_status: %#08x\n", tx_status ); - - /* if the packet at tx_tail is not owned by hardware it is for us */ - if ( tx_status & DescOwn ) - break; - - DBG ( "Transmitted packet.\n" ); - DBG ( "tp->tx_fill_ctr = %d\n", tp->tx_fill_ctr ); - DBG ( "tp->tx_tail = %d\n", tp->tx_tail ); - DBG ( "tp->tx_curr = %d\n", tp->tx_curr ); - DBG ( "tx_status = %d\n", tx_status ); - DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) ); - - /* Pass packet to core for processing */ - netdev_tx_complete ( netdev, tp->tx_iobuf[tp->tx_tail] ); - - memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) ); - - /* Decrement count of used descriptors */ - tp->tx_fill_ctr--; - - /* Increment sent packets index */ - tp->tx_tail = ( tp->tx_tail + 1 ) % NUM_TX_DESC; - } -} - -static void -rtl8169_free_tx_resources ( struct rtl8169_private *tp ) -{ - DBGP ( "rtl8169_free_tx_resources\n" ); - - free_dma ( tp->tx_base, R8169_TX_RING_BYTES ); -} - -static void -rtl8169_populate_rx_descriptor ( struct rtl8169_private *tp, struct RxDesc *rx_desc, uint32_t index ) -{ - DBGP ( "rtl8169_populate_rx_descriptor\n" ); - - DBG ( "Populating rx descriptor %d\n", index ); - - memset ( rx_desc, 0, sizeof ( *rx_desc ) ); - - rx_desc->addr_hi = 0; - rx_desc->addr_lo = virt_to_bus ( tp->rx_iobuf[index]->data ); - rx_desc->opts2 = 0; - rx_desc->opts1 = ( index == ( NUM_RX_DESC - 1 ) ? RingEnd : 0 ) | - RX_BUF_SIZE; - rx_desc->opts1 |= DescOwn; -} - -/** - * Refill descriptor ring - * - * @v netdev Net device - */ -static void rtl8169_refill_rx_ring ( struct rtl8169_private *tp ) -{ - struct RxDesc *rx_curr_desc; - int i; - - DBGP ( "rtl8169_refill_rx_ring\n" ); - - for ( i = 0; i < NUM_RX_DESC; i++ ) { - - rx_curr_desc = ( tp->rx_base ) + i; - - /* Don't touch descriptors owned by the NIC */ - if ( rx_curr_desc->opts1 & DescOwn ) - continue; - - /* Don't touch descriptors with iobufs, they still need to be - processed by the poll routine */ - if ( tp->rx_iobuf[tp->rx_curr] != NULL ) - continue; - - /** If we can't get an iobuf for this descriptor - try again later (next poll). - */ - if ( ! ( tp->rx_iobuf[i] = alloc_iob ( RX_BUF_SIZE ) ) ) { - DBG ( "Refill rx ring failed!!\n" ); - break; - } - - rtl8169_populate_rx_descriptor ( tp, rx_curr_desc, i ); - } -} - -/** - * setup_rx_resources - allocate Rx resources (Descriptors) - * - * @v tp: Driver private structure - * - * @ret rc Returns 0 on success, negative on failure - * - **/ -static int -rtl8169_setup_rx_resources ( struct rtl8169_private *tp ) -{ - DBGP ( "rtl8169_setup_rx_resources\n" ); - - tp->rx_base = malloc_dma ( R8169_RX_RING_BYTES, RX_RING_ALIGN ); - - DBG ( "tp->rx_base = %#08lx\n", virt_to_bus ( tp->rx_base ) ); - - if ( ! tp->rx_base ) { - return -ENOMEM; - } - memset ( tp->rx_base, 0, R8169_RX_RING_BYTES ); - - rtl8169_refill_rx_ring ( tp ); - - tp->rx_curr = 0; - - return 0; -} - -static void -rtl8169_process_rx_packets ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - uint32_t rx_status; - uint16_t rx_len; - struct RxDesc *rx_curr_desc; - int i; - - DBGP ( "rtl8169_process_rx_packets\n" ); - - for ( i = 0; i < NUM_RX_DESC; i++ ) { - - rx_curr_desc = tp->rx_base + tp->rx_curr; - - rx_status = rx_curr_desc->opts1; - - DBG2 ( "Before DescOwn check rx_status: %#08x\n", rx_status ); - - /* Hardware still owns the descriptor */ - if ( rx_status & DescOwn ) - break; - - /* We own the descriptor, but it has not been refilled yet */ - if ( tp->rx_iobuf[tp->rx_curr] == NULL ) - break; - - rx_len = rx_status & 0x3fff; - - DBG ( "Received packet.\n" ); - DBG ( "tp->rx_curr = %d\n", tp->rx_curr ); - DBG ( "rx_len = %d\n", rx_len ); - DBG ( "rx_status = %#08x\n", rx_status ); - DBG ( "rx_curr_desc = %#08lx\n", virt_to_bus ( rx_curr_desc ) ); - - if ( rx_status & RxRES ) { - - netdev_rx_err ( netdev, tp->rx_iobuf[tp->rx_curr], -EINVAL ); - - DBG ( "rtl8169_poll: Corrupted packet received!\n" - " rx_status: %#08x\n", rx_status ); - - } else { - - /* Adjust size of the iobuf to reflect received data */ - iob_put ( tp->rx_iobuf[tp->rx_curr], rx_len ); - - /* Add this packet to the receive queue. */ - netdev_rx ( netdev, tp->rx_iobuf[tp->rx_curr] ); - } - - /* Invalidate this iobuf and descriptor */ - tp->rx_iobuf[tp->rx_curr] = NULL; - memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) ); - - /* Update pointer to next available rx descriptor */ - tp->rx_curr = ( tp->rx_curr + 1 ) % NUM_RX_DESC; - } - rtl8169_refill_rx_ring ( tp ); -} - -static void -rtl8169_free_rx_resources ( struct rtl8169_private *tp ) -{ - int i; - - DBGP ( "rtl8169_free_rx_resources\n" ); - - free_dma ( tp->rx_base, R8169_RX_RING_BYTES ); - - for ( i = 0; i < NUM_RX_DESC; i++ ) { - free_iob ( tp->rx_iobuf[i] ); - tp->rx_iobuf[i] = NULL; - } -} - -static void rtl8169_irq_enable ( struct rtl8169_private *tp ) -{ - void *ioaddr = tp->mmio_addr; - - DBGP ( "rtl8169_irq_enable\n" ); - - RTL_W16 ( IntrMask, tp->intr_event ); -} - -static void rtl8169_irq_disable ( struct rtl8169_private *tp ) -{ - void *ioaddr = tp->mmio_addr; - - DBGP ( "rtl8169_irq_disable\n" ); - - RTL_W16 ( IntrMask, 0x0000 ); -} - -/*** iPXE Core API Routines ***/ - -/** - * open - Called when a network interface is made active - * - * @v netdev network interface device structure - * @ret rc Return status code, 0 on success, negative value on failure - * - **/ -static int -rtl8169_open ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - int rc; - - DBGP ( "rtl8169_open\n" ); - - /* allocate transmit descriptors */ - rc = rtl8169_setup_tx_resources ( tp ); - if ( rc ) { - DBG ( "Error setting up TX resources!\n" ); - goto err_setup_tx; - } - - /* allocate receive descriptors */ - rc = rtl8169_setup_rx_resources ( tp ); - if ( rc ) { - DBG ( "Error setting up RX resources!\n" ); - goto err_setup_rx; - } - - rtl_hw_start ( netdev ); - - DBG ( "TxDescStartAddrHigh = %#08lx\n", RTL_R32 ( TxDescStartAddrHigh ) ); - DBG ( "TxDescStartAddrLow = %#08lx\n", RTL_R32 ( TxDescStartAddrLow ) ); - DBG ( "RxDescAddrHigh = %#08lx\n", RTL_R32 ( RxDescAddrHigh ) ); - DBG ( "RxDescAddrLow = %#08lx\n", RTL_R32 ( RxDescAddrLow ) ); - - return 0; - -err_setup_rx: - rtl8169_free_tx_resources ( tp ); -err_setup_tx: - rtl8169_hw_reset ( 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 -rtl8169_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - uint32_t tx_len = iob_len ( iobuf ); - - struct TxDesc *tx_curr_desc; - - DBGP ("rtl8169_transmit\n"); - - if ( tp->tx_fill_ctr == NUM_TX_DESC ) { - DBG ("TX overflow\n"); - return -ENOBUFS; - } - - /** - * The rtl8169 family automatically pads short packets to a - * minimum size, but if it did not, like some older cards, - * we could do: - * iob_pad ( iobuf, ETH_ZLEN ); - */ - - /* Save pointer to this iobuf we have been given to transmit so - we can pass it to netdev_tx_complete() later */ - tp->tx_iobuf[tp->tx_curr] = iobuf; - - tx_curr_desc = tp->tx_base + tp->tx_curr; - - DBG ( "tp->tx_fill_ctr = %d\n", tp->tx_fill_ctr ); - DBG ( "tp->tx_curr = %d\n", tp->tx_curr ); - DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) ); - DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) ); - DBG ( "tx_len = %d\n", tx_len ); - - /* Configure current descriptor to transmit supplied packet */ - tx_curr_desc->addr_hi = 0; - tx_curr_desc->addr_lo = virt_to_bus ( iobuf->data ); - tx_curr_desc->opts2 = 0; - tx_curr_desc->opts1 = FirstFrag | LastFrag | - ( tp->tx_curr == ( NUM_TX_DESC - 1 ) ? RingEnd : 0 ) | - tx_len; - - /* Mark descriptor as owned by NIC */ - tx_curr_desc->opts1 |= DescOwn; - - DBG ( "tx_curr_desc->opts1 = %#08x\n", tx_curr_desc->opts1 ); - DBG ( "tx_curr_desc->opts2 = %#08x\n", tx_curr_desc->opts2 ); - DBG ( "tx_curr_desc->addr_hi = %#08x\n", tx_curr_desc->addr_hi ); - DBG ( "tx_curr_desc->addr_lo = %#08x\n", tx_curr_desc->addr_lo ); - - RTL_W8 ( TxPoll, NPQ ); /* set polling bit */ - - /* Point to next free descriptor */ - tp->tx_curr = ( tp->tx_curr + 1 ) % NUM_TX_DESC; - - /* Increment number of tx descriptors in use */ - tp->tx_fill_ctr++; - - return 0; -} - -/** - * poll - Poll for received packets - * - * @v netdev Network device - */ -static void -rtl8169_poll ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - - uint16_t intr_status; - uint16_t intr_mask; - - DBGP ( "rtl8169_poll\n" ); - - intr_status = RTL_R16 ( IntrStatus ); - intr_mask = RTL_R16 ( IntrMask ); - - DBG2 ( "rtl8169_poll (before): intr_mask = %#04x intr_status = %#04x\n", - intr_mask, intr_status ); - - RTL_W16 ( IntrStatus, 0xffff ); - - /* hotplug / major error / no more work / shared irq */ - if ( intr_status == 0xffff ) - return; - - /* Process transmitted packets */ - rtl8169_process_tx_packets ( netdev ); - - /* Process received packets */ - rtl8169_process_rx_packets ( netdev ); -} - -/** - * close - Disable network interface - * - * @v netdev network interface device structure - * - **/ -static void -rtl8169_close ( struct net_device *netdev ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - - DBGP ( "r8169_close\n" ); - - rtl8169_hw_reset ( ioaddr ); - - rtl8169_free_tx_resources ( tp ); - rtl8169_free_rx_resources ( tp ); -} - -/** - * irq - enable or Disable interrupts - * - * @v netdev network adapter - * @v action requested interrupt action - * - **/ -static void -rtl8169_irq ( struct net_device *netdev, int action ) -{ - struct rtl8169_private *tp = netdev_priv ( netdev ); - - DBGP ( "rtl8169_irq\n" ); - - switch ( action ) { - case 0 : - rtl8169_irq_disable ( tp ); - break; - default : - rtl8169_irq_enable ( tp ); - break; - } -} - -static struct net_device_operations rtl8169_operations = { - .open = rtl8169_open, - .transmit = rtl8169_transmit, - .poll = rtl8169_poll, - .close = rtl8169_close, - .irq = rtl8169_irq, -}; - -/** - * probe - Initial configuration of NIC - * - * @v pci PCI device - * @v id PCI IDs - * - * @ret rc Return status code - **/ -static int -rtl8169_probe ( struct pci_device *pdev ) -{ - int i, rc; - struct net_device *netdev; - struct rtl8169_private *tp; - void *ioaddr; - - const struct rtl_cfg_info *cfg = rtl_cfg_infos + pdev->id->driver_data; - - DBGP ( "rtl8169_probe\n" ); - - DBG ( "id->vendor = %#04x, id->device = %#04x\n", - pdev->id->vendor, pdev->id->device ); - - DBG ( "cfg->intr_event = %#04x\n", cfg->intr_event ); - - rc = -ENOMEM; - - /* Allocate net device ( also allocates memory for netdev->priv - and makes netdev-priv point to it ) - */ - netdev = alloc_etherdev ( sizeof ( *tp ) ); - - if ( ! netdev ) - goto err_alloc_etherdev; - - /* Associate driver-specific network operations with - generic network device layer - */ - netdev_init ( netdev, &rtl8169_operations ); - - /* Associate this network device with the given PCI device */ - pci_set_drvdata ( pdev, netdev ); - netdev->dev = &pdev->dev; - - /* Initialize driver private storage */ - tp = netdev_priv ( netdev ); - memset ( tp, 0, ( sizeof ( *tp ) ) ); - - tp->pci_dev = pdev; - tp->irqno = pdev->irq; - tp->netdev = netdev; - tp->intr_event = cfg->intr_event; - tp->cp_cmd = PCIMulRW; - - tp->hw_start = cfg->hw_start; - - rc = -EIO; - - adjust_pci_device ( pdev ); - - /* ioremap MMIO region */ - ioaddr = ioremap ( pdev->membase, R8169_REGS_SIZE ); - - if ( ! ioaddr ) { - DBG ( "cannot remap MMIO\n" ); - rc = -EIO; - goto err_ioremap; - } - - tp->mmio_addr = ioaddr; - - tp->pcie_cap = pci_find_capability ( pdev, PCI_CAP_ID_EXP ); - if ( tp->pcie_cap ) { - DBG ( "PCI Express capability\n" ); - } else { - DBG ( "No PCI Express capability\n" ); - } - - /* Mask interrupts just in case */ - rtl8169_irq_mask_and_ack ( ioaddr ); - - /* Soft reset NIC */ - rtl_soft_reset ( netdev ); - - /* Identify chip attached to board */ - rtl8169_get_mac_version ( tp, ioaddr ); - - for ( i = 0; (u32) i < ARRAY_SIZE ( rtl_chip_info ); i++ ) { - if ( tp->mac_version == rtl_chip_info[i].mac_version ) - break; - } - if ( i == ARRAY_SIZE(rtl_chip_info ) ) { - /* Unknown chip: assume array element #0, original RTL-8169 */ - DBG ( "Unknown chip version, assuming %s\n", rtl_chip_info[0].name ); - i = 0; - } - tp->chipset = i; - - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - - tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */ - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - } - - /* Get MAC address */ - for ( i = 0; i < MAC_ADDR_LEN; i++ ) - netdev->hw_addr[i] = RTL_R8 ( MAC0 + i ); - - DBG ( "%s\n", eth_ntoa ( netdev->hw_addr ) ); - - rtl8169_init_phy ( netdev, tp ); - - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); - - DBG ( "rtl8169_probe succeeded!\n" ); - - /* No errors, return success */ - return 0; - -/* Error return paths */ -err_register: -err_ioremap: - netdev_put ( netdev ); -err_alloc_etherdev: - return rc; -} - -/** - * remove - Device Removal Routine - * - * @v pdev PCI device information struct - * - **/ -static void -rtl8169_remove ( struct pci_device *pdev ) -{ - struct net_device *netdev = pci_get_drvdata ( pdev ); - struct rtl8169_private *tp = netdev_priv ( netdev ); - void *ioaddr = tp->mmio_addr; - - DBGP ( "rtl8169_remove\n" ); - - rtl8169_hw_reset ( ioaddr ); - - unregister_netdev ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -static struct pci_device_id rtl8169_nics[] = { - PCI_ROM(0x10ec, 0x8129, "rtl8169-0x8129", "rtl8169-0x8129", RTL_CFG_0), - PCI_ROM(0x10ec, 0x8136, "rtl8169-0x8136", "rtl8169-0x8136", RTL_CFG_2), - PCI_ROM(0x10ec, 0x8167, "rtl8169-0x8167", "rtl8169-0x8167", RTL_CFG_0), - PCI_ROM(0x10ec, 0x8168, "rtl8169-0x8168", "rtl8169-0x8168", RTL_CFG_1), - PCI_ROM(0x10ec, 0x8169, "rtl8169-0x8169", "rtl8169-0x8169", RTL_CFG_0), - PCI_ROM(0x1186, 0x4300, "rtl8169-0x4300", "rtl8169-0x4300", RTL_CFG_0), - PCI_ROM(0x1259, 0xc107, "rtl8169-0xc107", "rtl8169-0xc107", RTL_CFG_0), - PCI_ROM(0x16ec, 0x0116, "rtl8169-0x0116", "rtl8169-0x0116", RTL_CFG_0), - PCI_ROM(0x1737, 0x1032, "rtl8169-0x1032", "rtl8169-0x1032", RTL_CFG_0), - PCI_ROM(0x0001, 0x8168, "rtl8169-0x8168", "rtl8169-0x8168", RTL_CFG_2), -}; - -struct pci_driver rtl8169_driver __pci_driver = { - .ids = rtl8169_nics, - .id_count = ( sizeof ( rtl8169_nics ) / sizeof ( rtl8169_nics[0] ) ), - .probe = rtl8169_probe, - .remove = rtl8169_remove, -}; - -/* - * Local variables: - * c-basic-offset: 8 - * c-indent-level: 8 - * tab-width: 8 - * End: - */ diff --git a/roms/ipxe/src/drivers/net/r8169.h b/roms/ipxe/src/drivers/net/r8169.h deleted file mode 100644 index bcf3df0bb..000000000 --- a/roms/ipxe/src/drivers/net/r8169.h +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) 2008 Marty Connor - * Copyright (c) 2008 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. - * - * This driver is based on rtl8169 data sheets and work by: - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef _R8169_H_ -#define _R8169_H_ - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -/** FIXME: include/linux/pci_regs.h has these PCI regs, maybe - we need such a file in iPXE? -**/ -#define PCI_EXP_DEVCTL 8 /* Device Control */ -#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */ -#define PCI_EXP_LNKCTL 16 /* Link Control */ -#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ -#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ - -/** FIXME: update mii.h in src/include/mii.h from Linux sources - so we don't have to include these definitiions. -**/ -/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define SPEED_2500 2500 -#define SPEED_10000 10000 - -/* Duplex, half or full. */ -#define DUPLEX_HALF 0x00 -#define DUPLEX_FULL 0x01 - -#define AUTONEG_DISABLE 0x00 -#define AUTONEG_ENABLE 0x01 - -/* MAC address length */ -#define MAC_ADDR_LEN 6 - -#define MAX_READ_REQUEST_SHIFT 12 -#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ -#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 8 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 8 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define TX_RING_ALIGN 256 -#define RX_RING_ALIGN 256 - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x01, // 8169 - RTL_GIGA_MAC_VER_02 = 0x02, // 8169S - RTL_GIGA_MAC_VER_03 = 0x03, // 8110S - RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB - RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd - RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe - RTL_GIGA_MAC_VER_07 = 0x07, // 8102e - RTL_GIGA_MAC_VER_08 = 0x08, // 8102e - RTL_GIGA_MAC_VER_09 = 0x09, // 8102e - RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e - RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb - RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be - RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb - RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ? - RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ? - RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec - RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf - RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP - RTL_GIGA_MAC_VER_19 = 0x13, // 8168C - RTL_GIGA_MAC_VER_20 = 0x14, // 8168C - RTL_GIGA_MAC_VER_21 = 0x15, // 8168C - RTL_GIGA_MAC_VER_22 = 0x16, // 8168C - RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP - RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP - RTL_GIGA_MAC_VER_25 = 0x19, // 8168D -}; - -#define _R(NAME,MAC,MASK) \ - { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } - -static const struct { - const char *name; - u8 mac_version; - u32 RxConfigMask; /* Clears the bits supported by this chip */ -} rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 - _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S - _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe - _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E - _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139 - _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139 - _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E - _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_21, 0xff7e1880), // PCI-E - _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E - _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E - _R("RTL8168d/8111d", RTL_GIGA_MAC_VER_25, 0xff7e1880) // PCI-E -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -#if 0 -/** Device Table from Linux Driver **/ -static struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; -#endif - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff - - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum desc_status_bit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ - IPCS = (1 << 18), /* Calculate IP checksum */ - UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - volatile uint32_t opts1; - volatile uint32_t opts2; - volatile uint32_t addr_lo; - volatile uint32_t addr_hi; -}; - -struct RxDesc { - volatile uint32_t opts1; - volatile uint32_t opts2; - volatile uint32_t addr_lo; - volatile uint32_t addr_hi; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -static void rtl_hw_start_8169(struct net_device *); -static void rtl_hw_start_8168(struct net_device *); -static void rtl_hw_start_8101(struct net_device *); - -struct rtl8169_private { - - struct pci_device *pci_dev; - struct net_device *netdev; - uint8_t *hw_addr; - void *mmio_addr; - uint32_t irqno; - - int chipset; - int mac_version; - u16 intr_event; - - struct io_buffer *tx_iobuf[NUM_TX_DESC]; - struct io_buffer *rx_iobuf[NUM_RX_DESC]; - - struct TxDesc *tx_base; - struct RxDesc *rx_base; - - uint32_t tx_curr; - uint32_t rx_curr; - - uint32_t tx_tail; - - uint32_t tx_fill_ctr; - - u16 cp_cmd; - - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - - int ( *set_speed ) (struct net_device *, u8 autoneg, u16 speed, u8 duplex ); - void ( *phy_reset_enable ) ( void *ioaddr ); - void ( *hw_start ) ( struct net_device * ); - unsigned int ( *phy_reset_pending ) ( void *ioaddr ); - unsigned int ( *link_ok ) ( void *ioaddr ); - - int pcie_cap; - - unsigned features; - -}; - -static const unsigned int rtl8169_rx_config = - (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); - -#endif /* _R8169_H_ */ - -/* - * Local variables: - * c-basic-offset: 8 - * c-indent-level: 8 - * tab-width: 8 - * End: - */ diff --git a/roms/ipxe/src/drivers/net/realtek.c b/roms/ipxe/src/drivers/net/realtek.c new file mode 100644 index 000000000..76fa47bbc --- /dev/null +++ b/roms/ipxe/src/drivers/net/realtek.c @@ -0,0 +1,1169 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * (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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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, +}; + +/** + * Open bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static void realtek_spi_open_bit ( struct bit_basher *basher ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + + /* Enable EEPROM access */ + writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR ); +} + +/** + * Close bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static void realtek_spi_close_bit ( struct bit_basher *basher ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + + /* Disable EEPROM access */ + writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR ); +} + +/** + * 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 = { + .open = realtek_spi_open_bit, + .close = realtek_spi_close_bit, + .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; +} + +/** + * Configure PHY for Gigabit operation + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_phy_speed ( struct realtek_nic *rtl ) { + int ctrl1000; + int rc; + + /* Read CTRL1000 register */ + ctrl1000 = mii_read ( &rtl->mii, MII_CTRL1000 ); + if ( ctrl1000 < 0 ) { + rc = ctrl1000; + DBGC ( rtl, "REALTEK %p could not read CTRL1000: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + /* Advertise 1000Mbps speeds */ + ctrl1000 |= ( ADVERTISE_1000FULL | ADVERTISE_1000HALF ); + if ( ( rc = mii_write ( &rtl->mii, MII_CTRL1000, ctrl1000 ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not write CTRL1000: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Reset PHY + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_phy_reset ( struct realtek_nic *rtl ) { + int rc; + + /* Do nothing if we have no separate PHY register access */ + if ( ! rtl->have_phy_regs ) + return 0; + + /* Perform MII reset */ + if ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not reset MII: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + /* Some cards (e.g. RTL8169SC) do not advertise Gigabit by + * default. Try to enable advertisement of Gigabit speeds. + */ + if ( ( rc = realtek_phy_speed ( rtl ) ) != 0 ) { + /* Ignore failures, since the register may not be + * present on non-Gigabit PHYs (e.g. RTL8101). + */ + } + + /* Restart autonegotiation */ + if ( ( rc = mii_restart ( &rtl->mii ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not restart MII: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/****************************************************************************** + * + * 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 ( ( ( ( uint64_t ) address ) >> 32 ), + rtl->regs + ring->reg + 4 ); + writel ( ( address & 0xffffffffUL ), rtl->regs + ring->reg ); + 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 = cpu_to_le16 ( 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 tcr; + 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 transmitter */ + tcr = readl ( rtl->regs + RTL_TCR ); + tcr &= ~RTL_TCR_MXDMA_MASK; + tcr |= RTL_TCR_MXDMA_DEFAULT; + writel ( tcr, rtl->regs + RTL_TCR ); + + /* Configure receiver */ + rcr = readl ( rtl->regs + RTL_RCR ); + rcr &= ~( RTL_RCR_RXFTH_MASK | RTL_RCR_RBLEN_MASK | + RTL_RCR_MXDMA_MASK ); + rcr |= ( RTL_RCR_RXFTH_DEFAULT | RTL_RCR_RBLEN_DEFAULT | + RTL_RCR_MXDMA_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. + * + * Note that enabling DAC seems to cause bizarre behaviour + * (lockups, garbage data on the wire) on some systems, even + * if only 32-bit addresses are used. + */ + cpcr = readw ( rtl->regs + RTL_CPCR ); + cpcr |= ( RTL_CPCR_MULRW | RTL_CPCR_CPRX | RTL_CPCR_CPTX ); + if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) + cpcr |= RTL_CPCR_DAC; + 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 ) && ( cpcr != 0xffff ) ) { + 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 ( ( rc = realtek_phy_reset ( rtl ) ) != 0 ) + goto err_phy_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_phy_reset: + err_nvs_read: + realtek_reset ( rtl ); + err_reset: + iounmap ( rtl->regs ); + 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 */ + iounmap ( rtl->regs ); + 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/roms/ipxe/src/drivers/net/realtek.h b/roms/ipxe/src/drivers/net/realtek.h new file mode 100644 index 000000000..6a7b10a93 --- /dev/null +++ b/roms/ipxe/src/drivers/net/realtek.h @@ -0,0 +1,286 @@ +#ifndef _REALTEK_H +#define _REALTEK_H + +/** @file + * + * Realtek 10/100/1000 network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include + +/** 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 + +/** Transmit (Tx) Configuration Register (dword) */ +#define RTL_TCR 0x40 +#define RTL_TCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ +#define RTL_TCR_MXDMA_MASK RTL_TCR_MXDMA ( 0x7 ) +#define RTL_TCR_MXDMA_DEFAULT RTL_TCR_MXDMA ( 0x7 /* Unlimited */ ) + +/** Receive (Rx) Configuration Register (dword) */ +#define RTL_RCR 0x44 +#define RTL_RCR_RXFTH(x) ( (x) << 13 ) /**< Receive FIFO threshold */ +#define RTL_RCR_RXFTH_MASK RTL_RCR_RXFTH ( 0x7 ) +#define RTL_RCR_RXFTH_DEFAULT RTL_RCR_RXFTH ( 0x7 /* Whole packet */ ) +#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_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ +#define RTL_RCR_MXDMA_MASK RTL_RCR_MXDMA ( 0x7 ) +#define RTL_RCR_MXDMA_DEFAULT RTL_RCR_MXDMA ( 0x7 /* Unlimited */ ) +#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_EEM(x) ( (x) << 6 ) /**< Mode select */ +#define RTL_9346CR_EEM_EEPROM RTL_9346CR_EEM ( 0x2 ) /**< EEPROM mode */ +#define RTL_9346CR_EEM_NORMAL RTL_9346CR_EEM ( 0x0 ) /**< Normal mode */ +#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/roms/ipxe/src/drivers/net/rtl8139.c b/roms/ipxe/src/drivers/net/rtl8139.c deleted file mode 100644 index ebe84fb10..000000000 --- a/roms/ipxe/src/drivers/net/rtl8139.c +++ /dev/null @@ -1,596 +0,0 @@ -/* rtl8139.c - etherboot driver for the Realtek 8139 chipset - - ported from the linux driver written by Donald Becker - by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999 - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - changes to the original driver: - - removed support for interrupts, switching to polling mode (yuck!) - - removed support for the 8129 chip (external MII) - -*/ - -FILE_LICENCE ( GPL_ANY ); - -/*********************************************************************/ -/* Revision History */ -/*********************************************************************/ - -/* - 27 May 2006 mcb30@users.sourceforge.net (Michael Brown) - Rewrote to use the new net driver API, the updated PCI API, and - the generic three-wire serial device support for EEPROM access. - - 28 Dec 2002 ken_yap@users.sourceforge.net (Ken Yap) - Put in virt_to_bus calls to allow Etherboot relocation. - - 06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap) - Following email from Hyun-Joon Cha, added a disable routine, otherwise - NIC remains live and can crash the kernel later. - - 4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub) - Shuffled things around, removed the leftovers from the 8129 support - that was in the Linux driver and added a bit more 8139 definitions. - Moved the 8K receive buffer to a fixed, available address outside the - 0x98000-0x9ffff range. This is a bit of a hack, but currently the only - way to make room for the Etherboot features that need substantial amounts - of code like the ANSI console support. Currently the buffer is just below - 0x10000, so this even conforms to the tagged boot image specification, - which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000. My - interpretation of this "reserved" is that Etherboot may do whatever it - likes, as long as its environment is kept intact (like the BIOS - variables). Hopefully fixed rtl_poll() once and for all. The symptoms - were that if Etherboot was left at the boot menu for several minutes, the - first eth_poll failed. Seems like I am the only person who does this. - First of all I fixed the debugging code and then set out for a long bug - hunting session. It took me about a week full time work - poking around - various places in the driver, reading Don Becker's and Jeff Garzik's Linux - driver and even the FreeBSD driver (what a piece of crap!) - and - eventually spotted the nasty thing: the transmit routine was acknowledging - each and every interrupt pending, including the RxOverrun and RxFIFIOver - interrupts. This confused the RTL8139 thoroughly. It destroyed the - Rx ring contents by dumping the 2K FIFO contents right where we wanted to - get the next packet. Oh well, what fun. - - 18 Jan 2000 mdc@etherboot.org (Marty Connor) - Drastically simplified error handling. Basically, if any error - in transmission or reception occurs, the card is reset. - Also, pointed all transmit descriptors to the same buffer to - save buffer space. This should decrease driver size and avoid - corruption because of exceeding 32K during runtime. - - 28 Jul 1999 (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de) - rtl_poll was quite broken: it used the RxOK interrupt flag instead - of the RxBufferEmpty flag which often resulted in very bad - transmission performace - below 1kBytes/s. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TX_RING_SIZE 4 -#define TX_MAX_LEN 8192 - -struct rtl8139_tx { - unsigned int next; - struct io_buffer *iobuf[TX_RING_SIZE]; -}; - -struct rtl8139_rx { - void *ring; - unsigned int offset; -}; - -struct rtl8139_nic { - unsigned short ioaddr; - struct rtl8139_tx tx; - struct rtl8139_rx rx; - struct spi_bit_basher spibit; - struct spi_device eeprom; - struct nvo_block nvo; -}; - -/* Tuning Parameters */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ -#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 /* Calculate as 16<ioaddr + Cfg9346 ); - return ( eereg & mask ); -} - -static void rtl_spi_write_bit ( struct bit_basher *basher, - unsigned int bit_id, unsigned long data ) { - struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic, - spibit.basher ); - uint8_t mask = rtl_ee_bits[bit_id]; - uint8_t eereg; - - eereg = inb ( rtl->ioaddr + Cfg9346 ); - eereg &= ~mask; - eereg |= ( data & mask ); - outb ( eereg, rtl->ioaddr + Cfg9346 ); -} - -static struct bit_basher_operations rtl_basher_ops = { - .read = rtl_spi_read_bit, - .write = rtl_spi_write_bit, -}; - -/** - * Set up for EEPROM access - * - * @v netdev Net device - */ -static void rtl_init_eeprom ( struct net_device *netdev ) { - struct rtl8139_nic *rtl = netdev->priv; - int ee9356; - int vpd; - - /* Initialise three-wire bus */ - rtl->spibit.basher.op = &rtl_basher_ops; - rtl->spibit.bus.mode = SPI_MODE_THREEWIRE; - init_spi_bit_basher ( &rtl->spibit ); - - /* Detect EEPROM type and initialise three-wire device */ - ee9356 = ( inw ( rtl->ioaddr + RxConfig ) & Eeprom9356 ); - if ( ee9356 ) { - DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C56\n", rtl ); - init_at93c56 ( &rtl->eeprom, 16 ); - } else { - DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C46\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 rtl8139 datasheets, so we use - * it only if we detect that the card is not supporting VPD. - */ - vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable ); - if ( vpd ) { - DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use " - "for options\n", rtl ); - } else { - nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, 0x20, 0x40, NULL, - &netdev->refcnt ); - } -} - -/** - * Reset NIC - * - * @v netdev Net device - * - * Issues a hardware reset and waits for the reset to complete. - */ -static void rtl_reset ( struct net_device *netdev ) { - struct rtl8139_nic *rtl = netdev->priv; - - /* Reset chip */ - outb ( CmdReset, rtl->ioaddr + ChipCmd ); - mdelay ( 10 ); - memset ( &rtl->tx, 0, sizeof ( rtl->tx ) ); - rtl->rx.offset = 0; -} - -/** - * Open NIC - * - * @v netdev Net device - * @ret rc Return status code - */ -static int rtl_open ( struct net_device *netdev ) { - struct rtl8139_nic *rtl = netdev->priv; - int i; - - /* Program the MAC address */ - for ( i = 0 ; i < ETH_ALEN ; i++ ) - outb ( netdev->ll_addr[i], rtl->ioaddr + MAC0 + i ); - - /* Set up RX ring */ - rtl->rx.ring = malloc ( RX_BUF_LEN + RX_BUF_PAD ); - if ( ! rtl->rx.ring ) - return -ENOMEM; - outl ( virt_to_bus ( rtl->rx.ring ), rtl->ioaddr + RxBuf ); - DBGC ( rtl, "rtl8139 %p RX ring at %lx\n", - rtl, virt_to_bus ( rtl->rx.ring ) ); - - /* Enable TX and RX */ - outb ( ( CmdRxEnb | CmdTxEnb ), rtl->ioaddr + ChipCmd ); - outl ( ( ( RX_FIFO_THRESH << 13 ) | ( RX_BUF_LEN_IDX << 11 ) | - ( RX_DMA_BURST << 8 ) | AcceptBroadcast | AcceptMulticast | - AcceptMyPhys | AcceptAllPhys ), rtl->ioaddr + RxConfig ); - outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 0 ); - outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 4 ); - outl ( ( ( TX_DMA_BURST << 8 ) | ( TX_IPG << 24 ) ), - rtl->ioaddr + TxConfig ); - - return 0; -} - -/** - * Close NIC - * - * @v netdev Net device - */ -static void rtl_close ( struct net_device *netdev ) { - struct rtl8139_nic *rtl = netdev->priv; - - /* Reset the hardware to disable everything in one go */ - rtl_reset ( netdev ); - - /* Free RX ring */ - free ( rtl->rx.ring ); - rtl->rx.ring = NULL; -} - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int rtl_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct rtl8139_nic *rtl = netdev->priv; - - /* Check for space in TX ring */ - if ( rtl->tx.iobuf[rtl->tx.next] != NULL ) { - DBGC ( rtl, "rtl8139 %p TX overflow\n", rtl ); - return -ENOBUFS; - } - - /* Check for oversized packets */ - if ( iob_len ( iobuf ) >= TX_MAX_LEN ) { - DBGC ( rtl, "rtl8139 %p TX too large (%zd bytes)\n", - rtl, iob_len ( iobuf ) ); - return -ERANGE; - } - - /* Pad and align packet */ - iob_pad ( iobuf, ETH_ZLEN ); - - /* Add to TX ring */ - DBGC2 ( rtl, "rtl8139 %p TX id %d at %lx+%zx\n", rtl, rtl->tx.next, - virt_to_bus ( iobuf->data ), iob_len ( iobuf ) ); - rtl->tx.iobuf[rtl->tx.next] = iobuf; - outl ( virt_to_bus ( iobuf->data ), - rtl->ioaddr + TxAddr0 + 4 * rtl->tx.next ); - outl ( ( ( ( TX_FIFO_THRESH & 0x7e0 ) << 11 ) | iob_len ( iobuf ) ), - rtl->ioaddr + TxStatus0 + 4 * rtl->tx.next ); - rtl->tx.next = ( rtl->tx.next + 1 ) % TX_RING_SIZE; - - return 0; -} - -/** - * Poll for received packets - * - * @v netdev Network device - */ -static void rtl_poll ( struct net_device *netdev ) { - struct rtl8139_nic *rtl = netdev->priv; - unsigned int status; - unsigned int tsad; - unsigned int rx_status; - unsigned int rx_len; - struct io_buffer *rx_iob; - int wrapped_len; - int i; - - /* Acknowledge interrupts */ - status = inw ( rtl->ioaddr + IntrStatus ); - if ( ! status ) - return; - outw ( status, rtl->ioaddr + IntrStatus ); - - /* Handle TX completions */ - tsad = inw ( rtl->ioaddr + TxSummary ); - for ( i = 0 ; i < TX_RING_SIZE ; i++ ) { - if ( ( rtl->tx.iobuf[i] != NULL ) && ( tsad & ( 1 << i ) ) ) { - DBGC2 ( rtl, "rtl8139 %p TX id %d complete\n", - rtl, i ); - netdev_tx_complete ( netdev, rtl->tx.iobuf[i] ); - rtl->tx.iobuf[i] = NULL; - } - } - - /* Handle received packets */ - while ( ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ) { - rx_status = * ( ( uint16_t * ) - ( rtl->rx.ring + rtl->rx.offset ) ); - rx_len = * ( ( uint16_t * ) - ( rtl->rx.ring + rtl->rx.offset + 2 ) ); - if ( rx_status & RxOK ) { - DBGC2 ( rtl, "rtl8139 %p RX packet at offset " - "%x+%x\n", rtl, rtl->rx.offset, rx_len ); - - rx_iob = alloc_iob ( rx_len ); - if ( ! rx_iob ) { - netdev_rx_err ( netdev, NULL, -ENOMEM ); - /* Leave packet for next call to poll() */ - break; - } - - wrapped_len = ( ( rtl->rx.offset + 4 + rx_len ) - - RX_BUF_LEN ); - if ( wrapped_len < 0 ) - wrapped_len = 0; - - memcpy ( iob_put ( rx_iob, rx_len - wrapped_len ), - rtl->rx.ring + rtl->rx.offset + 4, - rx_len - wrapped_len ); - memcpy ( iob_put ( rx_iob, wrapped_len ), - rtl->rx.ring, wrapped_len ); - iob_unput ( rx_iob, 4 ); /* Strip CRC */ - - netdev_rx ( netdev, rx_iob ); - } else { - DBGC ( rtl, "rtl8139 %p RX bad packet (status %#04x " - "len %d)\n", rtl, rx_status, rx_len ); - netdev_rx_err ( netdev, NULL, -EINVAL ); - } - rtl->rx.offset = ( ( ( rtl->rx.offset + 4 + rx_len + 3 ) & ~3 ) - % RX_BUF_LEN ); - outw ( rtl->rx.offset - 16, rtl->ioaddr + RxBufPtr ); - } -} - -/** - * Enable/disable interrupts - * - * @v netdev Network device - * @v enable Interrupts should be enabled - */ -static void rtl_irq ( struct net_device *netdev, int enable ) { - struct rtl8139_nic *rtl = netdev->priv; - - DBGC ( rtl, "rtl8139 %p interrupts %s\n", - rtl, ( enable ? "enabled" : "disabled" ) ); - outw ( ( enable ? ( ROK | RER | TOK | TER ) : 0 ), - rtl->ioaddr + IntrMask ); -} - -/** RTL8139 net device operations */ -static struct net_device_operations rtl_operations = { - .open = rtl_open, - .close = rtl_close, - .transmit = rtl_transmit, - .poll = rtl_poll, - .irq = rtl_irq, -}; - -/** - * Probe PCI device - * - * @v pci PCI device - * @v id PCI ID - * @ret rc Return status code - */ -static int rtl_probe ( struct pci_device *pci ) { - struct net_device *netdev; - struct rtl8139_nic *rtl; - int rc; - - /* Allocate net device */ - netdev = alloc_etherdev ( sizeof ( *rtl ) ); - if ( ! netdev ) - return -ENOMEM; - netdev_init ( netdev, &rtl_operations ); - rtl = netdev->priv; - pci_set_drvdata ( pci, netdev ); - netdev->dev = &pci->dev; - memset ( rtl, 0, sizeof ( *rtl ) ); - rtl->ioaddr = pci->ioaddr; - - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Reset the NIC, set up EEPROM access and read MAC address */ - rtl_reset ( netdev ); - rtl_init_eeprom ( netdev ); - nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->hw_addr, 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 ); - - /* Register non-volatile storage */ - 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: - rtl_reset ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); - return rc; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void rtl_remove ( struct pci_device *pci ) { - struct net_device *netdev = pci_get_drvdata ( pci ); - struct rtl8139_nic *rtl = netdev->priv; - - if ( rtl->nvo.nvs ) - unregister_nvo ( &rtl->nvo ); - unregister_netdev ( netdev ); - rtl_reset ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -static struct pci_device_id rtl8139_nics[] = { -PCI_ROM(0x10ec, 0x8129, "rtl8129", "Realtek 8129", 0), -PCI_ROM(0x10ec, 0x8139, "rtl8139", "Realtek 8139", 0), -PCI_ROM(0x10ec, 0x8138, "rtl8139b", "Realtek 8139B", 0), -PCI_ROM(0x1186, 0x1300, "dfe538", "DFE530TX+/DFE538TX", 0), -PCI_ROM(0x1113, 0x1211, "smc1211-1", "SMC EZ10/100", 0), -PCI_ROM(0x1112, 0x1211, "smc1211", "SMC EZ10/100", 0), -PCI_ROM(0x1500, 0x1360, "delta8139", "Delta Electronics 8139", 0), -PCI_ROM(0x4033, 0x1360, "addtron8139", "Addtron Technology 8139", 0), -PCI_ROM(0x1186, 0x1340, "dfe690txd", "D-Link DFE690TXD", 0), -PCI_ROM(0x13d1, 0xab06, "fe2000vx", "AboCom FE2000VX", 0), -PCI_ROM(0x1259, 0xa117, "allied8139", "Allied Telesyn 8139", 0), -PCI_ROM(0x14ea, 0xab06, "fnw3603tx", "Planex FNW-3603-TX", 0), -PCI_ROM(0x14ea, 0xab07, "fnw3800tx", "Planex FNW-3800-TX", 0), -PCI_ROM(0xffff, 0x8139, "clone-rtl8139", "Cloned 8139", 0), -}; - -struct pci_driver rtl8139_driver __pci_driver = { - .ids = rtl8139_nics, - .id_count = ( sizeof ( rtl8139_nics ) / sizeof ( rtl8139_nics[0] ) ), - .probe = rtl_probe, - .remove = rtl_remove, -}; diff --git a/roms/ipxe/src/drivers/net/sis190.h b/roms/ipxe/src/drivers/net/sis190.h index fc6cb4b65..0551333d5 100644 --- a/roms/ipxe/src/drivers/net/sis190.h +++ b/roms/ipxe/src/drivers/net/sis190.h @@ -77,7 +77,7 @@ enum sis190_registers { IntrStatus = 0x20, IntrMask = 0x24, IntrControl = 0x28, - IntrTimer = 0x2c, // unused (Interupt Timer) + IntrTimer = 0x2c, // unused (Interrupt Timer) PMControl = 0x30, // unused (Power Mgmt Control/Status) rsv2 = 0x34, // reserved ROMControl = 0x38, @@ -218,7 +218,7 @@ enum _DescStatusBit { RxSizeMask = 0x0000ffff /* * The asic could apparently do vlan, TSO, jumbo (sis191 only) and - * provide two (unused with Linux) Tx queues. No publically + * provide two (unused with Linux) Tx queues. No publicly * available documentation alas. */ }; diff --git a/roms/ipxe/src/drivers/net/sis900.c b/roms/ipxe/src/drivers/net/sis900.c index 92eb5ce24..75e9ef962 100644 --- a/roms/ipxe/src/drivers/net/sis900.c +++ b/roms/ipxe/src/drivers/net/sis900.c @@ -328,7 +328,7 @@ static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic * * Side effects: * leaves the ioaddress of the sis900 chip in the variable ioaddr. - * leaves the sis900 initialized, and ready to recieve packets. + * leaves the sis900 initialized, and ready to receive packets. * * Returns: struct nic *: pointer to NIC data structure */ @@ -394,7 +394,7 @@ static int sis900_probe ( struct nic *nic, struct pci_device *pci ) { mii_status = sis900_mdio_read(phy_addr, MII_STATUS); if (mii_status == 0xffff || mii_status == 0x0000) - /* the mii is not accessable, try next one */ + /* the mii is not accessible, try next one */ continue; phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0); @@ -508,7 +508,7 @@ static u16 sis900_read_eeprom(int location) /* 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 + sent out separately */ static void sis900_mdio_idle(long mdio_addr) @@ -1171,8 +1171,8 @@ sis900_transmit(struct nic *nic, * * Arguments: struct nic *nic: NIC data structure * - * Returns: 1 if a packet was recieved. - * 0 if no pacet was recieved. + * Returns: 1 if a packet was received. + * 0 if no packet was received. * * Side effects: * Returns (copies) the packet to the array nic->packet. diff --git a/roms/ipxe/src/drivers/net/skeleton.c b/roms/ipxe/src/drivers/net/skeleton.c new file mode 100644 index 000000000..e50b778a8 --- /dev/null +++ b/roms/ipxe/src/drivers/net/skeleton.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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: + iounmap ( skel->regs ); + 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 */ + iounmap ( skel->regs ); + 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/roms/ipxe/src/drivers/net/skeleton.h b/roms/ipxe/src/drivers/net/skeleton.h new file mode 100644 index 000000000..3de2afa5b --- /dev/null +++ b/roms/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/roms/ipxe/src/drivers/net/skge.c b/roms/ipxe/src/drivers/net/skge.c index fea338414..6384e7647 100755 --- a/roms/ipxe/src/drivers/net/skge.c +++ b/roms/ipxe/src/drivers/net/skge.c @@ -24,7 +24,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_ONLY ); diff --git a/roms/ipxe/src/drivers/net/skge.h b/roms/ipxe/src/drivers/net/skge.h index 8a6ba6b25..d9e91457a 100755 --- a/roms/ipxe/src/drivers/net/skge.h +++ b/roms/ipxe/src/drivers/net/skge.h @@ -1095,7 +1095,7 @@ enum { 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_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ 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 */ @@ -1778,8 +1778,8 @@ enum { 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_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ 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) */ @@ -2284,7 +2284,7 @@ enum { 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_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occurred */ 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 */ diff --git a/roms/ipxe/src/drivers/net/sky2.c b/roms/ipxe/src/drivers/net/sky2.c index 5b5bd6b01..35ff66c6d 100644 --- a/roms/ipxe/src/drivers/net/sky2.c +++ b/roms/ipxe/src/drivers/net/sky2.c @@ -21,7 +21,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_ONLY ); @@ -782,7 +783,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) 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 */ + /* On chips without ram buffer, pause is controlled 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); @@ -2334,7 +2335,7 @@ static int sky2_probe(struct pci_device *pdev) sky2_show_addr(dev1); } - pci_set_drvdata(pdev, dev); + pci_set_drvdata(pdev, hw); return 0; diff --git a/roms/ipxe/src/drivers/net/sky2.h b/roms/ipxe/src/drivers/net/sky2.h index 3e86b1ded..9bb63010e 100644 --- a/roms/ipxe/src/drivers/net/sky2.h +++ b/roms/ipxe/src/drivers/net/sky2.h @@ -1056,7 +1056,7 @@ enum { 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_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ 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 */ @@ -1587,8 +1587,8 @@ enum { 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_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ 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) */ diff --git a/roms/ipxe/src/drivers/net/smc9000.h b/roms/ipxe/src/drivers/net/smc9000.h index 22b0e1893..02b1c831c 100644 --- a/roms/ipxe/src/drivers/net/smc9000.h +++ b/roms/ipxe/src/drivers/net/smc9000.h @@ -107,7 +107,7 @@ typedef unsigned long int dword; #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_100 (0x05) // LED = 100Mbps link detect #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) @@ -125,7 +125,7 @@ typedef unsigned long int dword; #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_100 (0x05) // LED = 100Mbps link detect #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) diff --git a/roms/ipxe/src/drivers/net/sundance.c b/roms/ipxe/src/drivers/net/sundance.c index 63a9ea5f1..eef7c9c7c 100644 --- a/roms/ipxe/src/drivers/net/sundance.c +++ b/roms/ipxe/src/drivers/net/sundance.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * sundance.c: A Linux device driver for the Sundance ST201 "Alta" @@ -257,7 +258,7 @@ static struct sundance_private { const char *nic_name; /* Frequently used values */ - unsigned int cur_rx; /* Producer/consumer ring indicies */ + unsigned int cur_rx; /* Producer/consumer ring indices */ unsigned int mtu; /* These values keep track of the tranceiver/media in use */ @@ -440,7 +441,7 @@ static void sundance_irq ( struct nic *nic, irq_action_t action ) { /************************************************************************** POLL - Wait for a frame ***************************************************************************/ -static int sundance_poll(struct nic *nic, int retreive) +static int sundance_poll(struct nic *nic, int retrieve) { /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ @@ -454,7 +455,7 @@ static int sundance_poll(struct nic *nic, int retreive) return 0; /* There is a packet ready */ - if(!retreive) + if(!retrieve) return 1; intr_status = inw(nic->ioaddr + IntrStatus); diff --git a/roms/ipxe/src/drivers/net/tg3.c b/roms/ipxe/src/drivers/net/tg3.c deleted file mode 100644 index e1562d4c8..000000000 --- a/roms/ipxe/src/drivers/net/tg3.c +++ /dev/null @@ -1,3435 +0,0 @@ -/* $Id$ - * tg3.c: Broadcom Tigon3 ethernet driver. - * - * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) - * Copyright (C) 2001, 2002 Jeff Garzik (jgarzik@mandrakesoft.com) - * Copyright (C) 2003 Eric Biederman (ebiederman@lnxi.com) [etherboot port] - */ - -FILE_LICENCE ( GPL2_ONLY ); - -/* 11-13-2003 timlegge Fix Issue with NetGear GA302T - * 11-18-2003 ebiederm Generalize NetGear Fix to what the code was supposed to be. - * 01-06-2005 Alf (Frederic Olivie) Add Dell bcm 5751 (0x1677) support - * 04-15-2005 Martin Vogt Add Fujitsu Siemens Computer (FSC) 0x1734 bcm 5751 0x105d support - */ - -#include "etherboot.h" -#include "nic.h" -#include -#include -#include -#include "string.h" -#include -#include "tg3.h" - -#define SUPPORT_COPPER_PHY 1 -#define SUPPORT_FIBER_PHY 1 -#define SUPPORT_LINK_REPORT 1 -#define SUPPORT_PARTNO_STR 1 -#define SUPPORT_PHY_STR 1 - -static struct tg3 tg3; - -/* These numbers seem to be hard coded in the NIC firmware somehow. - * You can't change the ring sizes, but you can change where you place - * them in the NIC onboard memory. - */ -#define TG3_RX_RING_SIZE 512 -#define TG3_DEF_RX_RING_PENDING 20 /* RX_RING_PENDING seems to be o.k. at 20 and 200 */ -#define TG3_RX_RCB_RING_SIZE 1024 - -/* (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \ - 512 : 1024) */ -#define TG3_TX_RING_SIZE 512 -#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) - -#define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RING_SIZE) -#define TG3_RX_RCB_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RCB_RING_SIZE) - -#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * TG3_TX_RING_SIZE) -#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) -#define PREV_TX(N) (((N) - 1) & (TG3_TX_RING_SIZE - 1)) - -#define RX_PKT_BUF_SZ (1536 + 2 + 64) - -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]; -}; - -struct bss { - struct tg3_rx_buffer_desc rx_std[TG3_RX_RING_SIZE]; - struct tg3_rx_buffer_desc rx_rcb[TG3_RX_RCB_RING_SIZE]; - struct tg3_tx_buffer_desc tx_ring[TG3_TX_RING_SIZE]; - struct tg3_hw_status hw_status; - struct tg3_hw_stats hw_stats; - unsigned char rx_bufs[TG3_DEF_RX_RING_PENDING][RX_PKT_BUF_SZ]; - struct eth_frame tx_frame[2]; -} tg3_bss __shared; - -/** - * pci_save_state - save the PCI configuration space of a device before suspending - * @dev: - PCI device that we're dealing with - * @buffer: - buffer to hold config space context - * - * @buffer must be large enough to hold the entire PCI 2.2 config space - * (>= 64 bytes). - */ -static int pci_save_state(struct pci_device *dev, uint32_t *buffer) -{ - int i; - for (i = 0; i < 16; i++) - pci_read_config_dword(dev, i * 4,&buffer[i]); - return 0; -} - -/** - * pci_restore_state - Restore the saved state of a PCI device - * @dev: - PCI device that we're dealing with - * @buffer: - saved PCI config space - * - */ -static int pci_restore_state(struct pci_device *dev, uint32_t *buffer) -{ - int i; - - for (i = 0; i < 16; i++) - pci_write_config_dword(dev,i * 4, buffer[i]); - return 0; -} - -static void tg3_write_indirect_reg32(uint32_t off, uint32_t val) -{ - pci_write_config_dword(tg3.pdev, TG3PCI_REG_BASE_ADDR, off); - pci_write_config_dword(tg3.pdev, TG3PCI_REG_DATA, val); -} - -#define tw32(reg,val) tg3_write_indirect_reg32((reg),(val)) -#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tg3.regs + (reg)) -#define tw16(reg,val) writew(((val) & 0xffff), tg3.regs + (reg)) -#define tw8(reg,val) writeb(((val) & 0xff), tg3.regs + (reg)) -#define tr32(reg) readl(tg3.regs + (reg)) -#define tr16(reg) readw(tg3.regs + (reg)) -#define tr8(reg) readb(tg3.regs + (reg)) - -static void tw32_carefully(uint32_t reg, uint32_t val) -{ - tw32(reg, val); - tr32(reg); - udelay(100); -} - -static void tw32_mailbox2(uint32_t reg, uint32_t val) -{ - tw32_mailbox(reg, val); - tr32(reg); -} - -static void tg3_write_mem(uint32_t off, uint32_t val) -{ - pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val); - - /* Always leave this as zero. */ - pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); -} - -static void tg3_read_mem(uint32_t off, uint32_t *val) -{ - pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val); - - /* Always leave this as zero. */ - pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); -} - -static void tg3_disable_ints(struct tg3 *tp) -{ - tw32(TG3PCI_MISC_HOST_CTRL, - (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox2(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); -} - -static void tg3_switch_clocks(struct tg3 *tp) -{ - uint32_t orig_clock_ctrl, clock_ctrl; - - 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 ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) && - (!((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) - && (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) && - (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE)!=0) { - tw32_carefully(TG3PCI_CLOCK_CTRL, - clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); - tw32_carefully(TG3PCI_CLOCK_CTRL, - clock_ctrl | (CLOCK_CTRL_ALTCLK)); - } - tw32_carefully(TG3PCI_CLOCK_CTRL, clock_ctrl); -} - -#define PHY_BUSY_LOOPS 5000 - -static int tg3_readphy(struct tg3 *tp, int reg, uint32_t *val) -{ - uint32_t frame_val; - int loops, ret; - - tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL); - - *val = 0xffffffff; - - frame_val = ((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_carefully(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; - } - } - - ret = -EBUSY; - if (loops > 0) { - *val = frame_val & MI_COM_DATA_MASK; - ret = 0; - } - - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - - return ret; -} - -static int tg3_writephy(struct tg3 *tp, int reg, uint32_t val) -{ - uint32_t frame_val; - int loops, ret; - - tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL); - - frame_val = ((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_carefully(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; - } - } - - ret = -EBUSY; - if (loops > 0) - ret = 0; - - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - - return ret; -} - -static int tg3_writedsp(struct tg3 *tp, uint16_t addr, uint16_t val) -{ - int err; - err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, addr); - err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); - return err; -} - - -static void tg3_phy_set_wirespeed(struct tg3 *tp) -{ - uint32_t val; - - if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) - return; - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); - tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); - tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); -} - -static int tg3_bmcr_reset(struct tg3 *tp) -{ - uint32_t 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) -{ - int limit = 100; - - while (limit--) { - uint32_t tmp32; - - tg3_readphy(tp, 0x16, &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) -{ - static const uint32_t 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, 0x16, 0x0002); - - for (i = 0; i < 6; i++) - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, - test_pat[chan][i]); - - tg3_writephy(tp, 0x16, 0x0202); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, - (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0082); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - tg3_writephy(tp, 0x16, 0x0802); - if (tg3_wait_macro_done(tp)) { - *resetp = 1; - return -EBUSY; - } - - for (i = 0; i < 6; i += 2) { - uint32_t low, high; - - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); - tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); - if (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) -{ - int chan; - - for (chan = 0; chan < 4; chan++) { - int i; - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, - (chan * 0x2000) | 0x0200); - tg3_writephy(tp, 0x16, 0x0002); - for (i = 0; i < 6; i++) - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000); - tg3_writephy(tp, 0x16, 0x0202); - if (tg3_wait_macro_done(tp)) - return -EBUSY; - } - - return 0; -} - -static int tg3_phy_reset_5703_4_5(struct tg3 *tp) -{ - uint32_t 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. */ - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); - 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. */ - tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); - tg3_writephy(tp, MII_TG3_CTRL, - (MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER)); - - /* Enable SM_DSP_CLOCK and 6dB. */ - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - - /* Block the PHY control access. */ - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 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_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005); - tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000); - - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); - tg3_writephy(tp, 0x16, 0x0000); - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); - - tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); - - tg3_readphy(tp, MII_TG3_EXT_CTRL, ®32); - reg32 &= ~0x3000; - tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); - - return err; -} - -/* This will reset the tigon3 PHY if there is no valid - * link. - */ -static int tg3_phy_reset(struct tg3 *tp) -{ - uint32_t phy_status; - int err; - - err = tg3_readphy(tp, MII_BMSR, &phy_status); - err |= tg3_readphy(tp, MII_BMSR, &phy_status); - if (err != 0) - return -EBUSY; - - 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; - } - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { - // Taken from Broadcom's source code - tg3_writephy(tp, 0x18, 0x0c00); - tg3_writephy(tp, 0x17, 0x000a); - tg3_writephy(tp, 0x15, 0x310b); - tg3_writephy(tp, 0x17, 0x201f); - tg3_writephy(tp, 0x15, 0x9506); - tg3_writephy(tp, 0x17, 0x401f); - tg3_writephy(tp, 0x15, 0x14e2); - tg3_writephy(tp, 0x18, 0x0400); - } - err = tg3_bmcr_reset(tp); - if (err) - return err; - out: - tg3_phy_set_wirespeed(tp); - return 0; -} - -static void tg3_set_power_state_0(struct tg3 *tp) -{ - 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_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - - return; -} - - -#if SUPPORT_LINK_REPORT -static void tg3_link_report(struct tg3 *tp) -{ - if (!tp->carrier_ok) { - printf("Link is down.\n"); - } else { - printf("Link is up at %d Mbps, %s duplex. %s %s %s\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"), - (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "TX" : "", - (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "RX" : "", - (tp->tg3_flags & (TG3_FLAG_TX_PAUSE |TG3_FLAG_RX_PAUSE)) ? "flow control" : ""); - } -} -#else -#define tg3_link_report(tp) -#endif - -static void tg3_setup_flow_control(struct tg3 *tp, uint32_t local_adv, uint32_t remote_adv) -{ - uint32_t new_tg3_flags = 0; - - if (local_adv & ADVERTISE_PAUSE_CAP) { - if (local_adv & ADVERTISE_PAUSE_ASYM) { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - else if (remote_adv & LPA_PAUSE_ASYM) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE); - } else { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - } - } else if (local_adv & ADVERTISE_PAUSE_ASYM) { - if ((remote_adv & LPA_PAUSE_CAP) && - (remote_adv & LPA_PAUSE_ASYM)) - new_tg3_flags |= TG3_FLAG_TX_PAUSE; - } - - tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); - tp->tg3_flags |= new_tg3_flags; - - if (new_tg3_flags & TG3_FLAG_RX_PAUSE) - tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; - else - tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; - - if (new_tg3_flags & TG3_FLAG_TX_PAUSE) - tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; - else - tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; -} - -#if SUPPORT_COPPER_PHY -static void tg3_aux_stat_to_speed_duplex( - struct tg3 *tp __unused, uint32_t val, uint8_t *speed, uint8_t *duplex) -{ - static const uint8_t map[] = { - [0] = (SPEED_INVALID << 2) | DUPLEX_INVALID, - [MII_TG3_AUX_STAT_10HALF >> 8] = (SPEED_10 << 2) | DUPLEX_HALF, - [MII_TG3_AUX_STAT_10FULL >> 8] = (SPEED_10 << 2) | DUPLEX_FULL, - [MII_TG3_AUX_STAT_100HALF >> 8] = (SPEED_100 << 2) | DUPLEX_HALF, - [MII_TG3_AUX_STAT_100_4 >> 8] = (SPEED_INVALID << 2) | DUPLEX_INVALID, - [MII_TG3_AUX_STAT_100FULL >> 8] = (SPEED_100 << 2) | DUPLEX_FULL, - [MII_TG3_AUX_STAT_1000HALF >> 8] = (SPEED_1000 << 2) | DUPLEX_HALF, - [MII_TG3_AUX_STAT_1000FULL >> 8] = (SPEED_1000 << 2) | DUPLEX_FULL, - }; - uint8_t result; - result = map[(val & MII_TG3_AUX_STAT_SPDMASK) >> 8]; - *speed = result >> 2; - *duplex = result & 3; -} - -static int tg3_phy_copper_begin(struct tg3 *tp) -{ - uint32_t new_adv; - - tp->link_config.advertising = - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | ADVERTISED_MII); - - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) { - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); - } - - new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - if (tp->link_config.advertising & ADVERTISED_10baseT_Half) { - new_adv |= ADVERTISE_10HALF; - } - if (tp->link_config.advertising & ADVERTISED_10baseT_Full) { - new_adv |= ADVERTISE_10FULL; - } - if (tp->link_config.advertising & ADVERTISED_100baseT_Half) { - new_adv |= ADVERTISE_100HALF; - } - if (tp->link_config.advertising & ADVERTISED_100baseT_Full) { - new_adv |= ADVERTISE_100FULL; - } - tg3_writephy(tp, MII_ADVERTISE, new_adv); - - if (tp->link_config.advertising & - (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { - new_adv = 0; - if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) { - new_adv |= MII_TG3_CTRL_ADV_1000_HALF; - } - if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) { - new_adv |= MII_TG3_CTRL_ADV_1000_FULL; - } - if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) && - (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); - } - tg3_writephy(tp, MII_TG3_CTRL, new_adv); - } else { - tg3_writephy(tp, MII_TG3_CTRL, 0); - } - - tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - - return 0; -} - -static int tg3_init_5401phy_dsp(struct tg3 *tp) -{ - int err; - - /* Turn off tap power management. */ - err = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20); - - err |= tg3_writedsp(tp, 0x0012, 0x1804); - err |= tg3_writedsp(tp, 0x0013, 0x1204); - err |= tg3_writedsp(tp, 0x8006, 0x0132); - err |= tg3_writedsp(tp, 0x8006, 0x0232); - err |= tg3_writedsp(tp, 0x201f, 0x0a20); - - udelay(40); - - return err; -} - -static int tg3_setup_copper_phy(struct tg3 *tp) -{ - int current_link_up; - uint32_t bmsr, dummy; - int i, err; - - tw32_carefully(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED - | MAC_STATUS_LNKSTATE_CHANGED)); - - tp->mi_mode = MAC_MI_MODE_BASE; - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02); - - /* 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) || - (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)) && - (tp->carrier_ok)) { - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (!(bmsr & BMSR_LSTATUS)) - tg3_phy_reset(tp); - } - - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (!(tp->tg3_flags & TG3_FLAG_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); - tg3_readphy(tp, MII_BMSR, &bmsr); - if (bmsr & BMSR_LSTATUS) { - udelay(40); - break; - } - } - - if ((tp->phy_id & PHY_ID_REV_MASK) == 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, 0x1c, 0x8c68); - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8c68); - } - - /* Clear pending interrupts... */ - tg3_readphy(tp, MII_TG3_ISTAT, &dummy); - tg3_readphy(tp, MII_TG3_ISTAT, &dummy); - - tg3_writephy(tp, MII_TG3_IMASK, ~0); - - if (tp->led_mode == led_mode_three_link) - 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; - - tg3_readphy(tp, MII_BMSR, &bmsr); - tg3_readphy(tp, MII_BMSR, &bmsr); - - if (bmsr & BMSR_LSTATUS) { - uint32_t aux_stat, bmcr; - - tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); - for (i = 0; i < 2000; i++) { - udelay(10); - tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); - if (aux_stat) - break; - } - - tg3_aux_stat_to_speed_duplex(tp, aux_stat, - &tp->link_config.active_speed, - &tp->link_config.active_duplex); - tg3_readphy(tp, MII_BMCR, &bmcr); - tg3_readphy(tp, MII_BMCR, &bmcr); - if (bmcr & BMCR_ANENABLE) { - uint32_t gig_ctrl; - - current_link_up = 1; - - /* Force autoneg restart if we are exiting - * low power mode. - */ - tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl); - if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL))) { - current_link_up = 0; - } - } else { - current_link_up = 0; - } - } - - if (current_link_up == 1 && - (tp->link_config.active_duplex == DUPLEX_FULL)) { - uint32_t local_adv, remote_adv; - - tg3_readphy(tp, MII_ADVERTISE, &local_adv); - local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - tg3_readphy(tp, MII_LPA, &remote_adv); - remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); - - /* If we are not advertising full pause capability, - * something is wrong. Bring the link down and reconfigure. - */ - if (local_adv != ADVERTISE_PAUSE_CAP) { - current_link_up = 0; - } else { - tg3_setup_flow_control(tp, local_adv, remote_adv); - } - } - - if (current_link_up == 0) { - uint32_t tmp; - - tg3_phy_copper_begin(tp); - - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (tmp & BMSR_LSTATUS) - 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 - 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; - - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if ((tp->led_mode == led_mode_link10) || - (current_link_up == 1 && - tp->link_config.active_speed == SPEED_10)) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - } else { - if (current_link_up == 1) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1); - } - - /* ??? Without this setting Netgear GA302T PHY does not - * ??? send/receive packets... - * With this other PHYs cannot bring up the link - */ - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 && - tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) { - tp->mi_mode |= MAC_MI_MODE_AUTO_POLL; - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - } - - tw32_carefully(MAC_MODE, tp->mac_mode); - - /* Link change polled. */ - tw32_carefully(MAC_EVENT, 0); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && - current_link_up == 1 && - tp->link_config.active_speed == SPEED_1000 && - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) || - (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) { - udelay(120); - tw32_carefully(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - tg3_write_mem( - NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC2); - } - - if (current_link_up != tp->carrier_ok) { - tp->carrier_ok = current_link_up; - tg3_link_report(tp); - } - - return 0; -} -#else -#define tg3_setup_copper_phy(TP) (-EINVAL) -#endif /* SUPPORT_COPPER_PHY */ - -#if SUPPORT_FIBER_PHY -struct tg3_fiber_aneginfo { - int state; -#define ANEG_STATE_UNKNOWN 0 -#define ANEG_STATE_AN_ENABLE 1 -#define ANEG_STATE_RESTART_INIT 2 -#define ANEG_STATE_RESTART 3 -#define ANEG_STATE_DISABLE_LINK_OK 4 -#define ANEG_STATE_ABILITY_DETECT_INIT 5 -#define ANEG_STATE_ABILITY_DETECT 6 -#define ANEG_STATE_ACK_DETECT_INIT 7 -#define ANEG_STATE_ACK_DETECT 8 -#define ANEG_STATE_COMPLETE_ACK_INIT 9 -#define ANEG_STATE_COMPLETE_ACK 10 -#define ANEG_STATE_IDLE_DETECT_INIT 11 -#define ANEG_STATE_IDLE_DETECT 12 -#define ANEG_STATE_LINK_OK 13 -#define ANEG_STATE_NEXT_PAGE_WAIT_INIT 14 -#define ANEG_STATE_NEXT_PAGE_WAIT 15 - - uint32_t flags; -#define MR_AN_ENABLE 0x00000001 -#define MR_RESTART_AN 0x00000002 -#define MR_AN_COMPLETE 0x00000004 -#define MR_PAGE_RX 0x00000008 -#define MR_NP_LOADED 0x00000010 -#define MR_TOGGLE_TX 0x00000020 -#define MR_LP_ADV_FULL_DUPLEX 0x00000040 -#define MR_LP_ADV_HALF_DUPLEX 0x00000080 -#define MR_LP_ADV_SYM_PAUSE 0x00000100 -#define MR_LP_ADV_ASYM_PAUSE 0x00000200 -#define MR_LP_ADV_REMOTE_FAULT1 0x00000400 -#define MR_LP_ADV_REMOTE_FAULT2 0x00000800 -#define MR_LP_ADV_NEXT_PAGE 0x00001000 -#define MR_TOGGLE_RX 0x00002000 -#define MR_NP_RX 0x00004000 - -#define MR_LINK_OK 0x80000000 - - unsigned long link_time, cur_time; - - uint32_t ability_match_cfg; - int ability_match_count; - - char ability_match, idle_match, ack_match; - - uint32_t txconfig, rxconfig; -#define ANEG_CFG_NP 0x00000080 -#define ANEG_CFG_ACK 0x00000040 -#define ANEG_CFG_RF2 0x00000020 -#define ANEG_CFG_RF1 0x00000010 -#define ANEG_CFG_PS2 0x00000001 -#define ANEG_CFG_PS1 0x00008000 -#define ANEG_CFG_HD 0x00004000 -#define ANEG_CFG_FD 0x00002000 -#define ANEG_CFG_INVAL 0x00001f06 - -}; -#define ANEG_OK 0 -#define ANEG_DONE 1 -#define ANEG_TIMER_ENAB 2 -#define ANEG_FAILED -1 - -#define ANEG_STATE_SETTLE_TIME 10000 - -static int tg3_fiber_aneg_smachine(struct tg3 *tp, - struct tg3_fiber_aneginfo *ap) -{ - unsigned long delta; - uint32_t rx_cfg_reg; - int ret; - - if (ap->state == ANEG_STATE_UNKNOWN) { - ap->rxconfig = 0; - ap->link_time = 0; - ap->cur_time = 0; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->idle_match = 0; - ap->ack_match = 0; - } - ap->cur_time++; - - if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) { - rx_cfg_reg = tr32(MAC_RX_AUTO_NEG); - - if (rx_cfg_reg != ap->ability_match_cfg) { - ap->ability_match_cfg = rx_cfg_reg; - ap->ability_match = 0; - ap->ability_match_count = 0; - } else { - if (++ap->ability_match_count > 1) { - ap->ability_match = 1; - ap->ability_match_cfg = rx_cfg_reg; - } - } - if (rx_cfg_reg & ANEG_CFG_ACK) - ap->ack_match = 1; - else - ap->ack_match = 0; - - ap->idle_match = 0; - } else { - ap->idle_match = 1; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->ack_match = 0; - - rx_cfg_reg = 0; - } - - ap->rxconfig = rx_cfg_reg; - ret = ANEG_OK; - - switch(ap->state) { - case ANEG_STATE_UNKNOWN: - if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN)) - ap->state = ANEG_STATE_AN_ENABLE; - - /* fallthru */ - case ANEG_STATE_AN_ENABLE: - ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX); - if (ap->flags & MR_AN_ENABLE) { - ap->link_time = 0; - ap->cur_time = 0; - ap->ability_match_cfg = 0; - ap->ability_match_count = 0; - ap->ability_match = 0; - ap->idle_match = 0; - ap->ack_match = 0; - - ap->state = ANEG_STATE_RESTART_INIT; - } else { - ap->state = ANEG_STATE_DISABLE_LINK_OK; - } - break; - - case ANEG_STATE_RESTART_INIT: - ap->link_time = ap->cur_time; - ap->flags &= ~(MR_NP_LOADED); - ap->txconfig = 0; - tw32(MAC_TX_AUTO_NEG, 0); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32_carefully(MAC_MODE, tp->mac_mode); - - ret = ANEG_TIMER_ENAB; - ap->state = ANEG_STATE_RESTART; - - /* fallthru */ - case ANEG_STATE_RESTART: - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - ap->state = ANEG_STATE_ABILITY_DETECT_INIT; - } else { - ret = ANEG_TIMER_ENAB; - } - break; - - case ANEG_STATE_DISABLE_LINK_OK: - ret = ANEG_DONE; - break; - - case ANEG_STATE_ABILITY_DETECT_INIT: - ap->flags &= ~(MR_TOGGLE_TX); - ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); - tw32(MAC_TX_AUTO_NEG, ap->txconfig); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32_carefully(MAC_MODE, tp->mac_mode); - - ap->state = ANEG_STATE_ABILITY_DETECT; - break; - - case ANEG_STATE_ABILITY_DETECT: - if (ap->ability_match != 0 && ap->rxconfig != 0) { - ap->state = ANEG_STATE_ACK_DETECT_INIT; - } - break; - - case ANEG_STATE_ACK_DETECT_INIT: - ap->txconfig |= ANEG_CFG_ACK; - tw32(MAC_TX_AUTO_NEG, ap->txconfig); - tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32_carefully(MAC_MODE, tp->mac_mode); - - ap->state = ANEG_STATE_ACK_DETECT; - - /* fallthru */ - case ANEG_STATE_ACK_DETECT: - if (ap->ack_match != 0) { - if ((ap->rxconfig & ~ANEG_CFG_ACK) == - (ap->ability_match_cfg & ~ANEG_CFG_ACK)) { - ap->state = ANEG_STATE_COMPLETE_ACK_INIT; - } else { - ap->state = ANEG_STATE_AN_ENABLE; - } - } else if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - } - break; - - case ANEG_STATE_COMPLETE_ACK_INIT: - if (ap->rxconfig & ANEG_CFG_INVAL) { - ret = ANEG_FAILED; - break; - } - ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX | - MR_LP_ADV_HALF_DUPLEX | - MR_LP_ADV_SYM_PAUSE | - MR_LP_ADV_ASYM_PAUSE | - MR_LP_ADV_REMOTE_FAULT1 | - MR_LP_ADV_REMOTE_FAULT2 | - MR_LP_ADV_NEXT_PAGE | - MR_TOGGLE_RX | - MR_NP_RX); - if (ap->rxconfig & ANEG_CFG_FD) - ap->flags |= MR_LP_ADV_FULL_DUPLEX; - if (ap->rxconfig & ANEG_CFG_HD) - ap->flags |= MR_LP_ADV_HALF_DUPLEX; - if (ap->rxconfig & ANEG_CFG_PS1) - ap->flags |= MR_LP_ADV_SYM_PAUSE; - if (ap->rxconfig & ANEG_CFG_PS2) - ap->flags |= MR_LP_ADV_ASYM_PAUSE; - if (ap->rxconfig & ANEG_CFG_RF1) - ap->flags |= MR_LP_ADV_REMOTE_FAULT1; - if (ap->rxconfig & ANEG_CFG_RF2) - ap->flags |= MR_LP_ADV_REMOTE_FAULT2; - if (ap->rxconfig & ANEG_CFG_NP) - ap->flags |= MR_LP_ADV_NEXT_PAGE; - - ap->link_time = ap->cur_time; - - ap->flags ^= (MR_TOGGLE_TX); - if (ap->rxconfig & 0x0008) - ap->flags |= MR_TOGGLE_RX; - if (ap->rxconfig & ANEG_CFG_NP) - ap->flags |= MR_NP_RX; - ap->flags |= MR_PAGE_RX; - - ap->state = ANEG_STATE_COMPLETE_ACK; - ret = ANEG_TIMER_ENAB; - break; - - case ANEG_STATE_COMPLETE_ACK: - if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - break; - } - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) { - ap->state = ANEG_STATE_IDLE_DETECT_INIT; - } else { - if ((ap->txconfig & ANEG_CFG_NP) == 0 && - !(ap->flags & MR_NP_RX)) { - ap->state = ANEG_STATE_IDLE_DETECT_INIT; - } else { - ret = ANEG_FAILED; - } - } - } - break; - - case ANEG_STATE_IDLE_DETECT_INIT: - ap->link_time = ap->cur_time; - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32_carefully(MAC_MODE, tp->mac_mode); - - ap->state = ANEG_STATE_IDLE_DETECT; - ret = ANEG_TIMER_ENAB; - break; - - case ANEG_STATE_IDLE_DETECT: - if (ap->ability_match != 0 && - ap->rxconfig == 0) { - ap->state = ANEG_STATE_AN_ENABLE; - break; - } - delta = ap->cur_time - ap->link_time; - if (delta > ANEG_STATE_SETTLE_TIME) { - /* XXX another gem from the Broadcom driver :( */ - ap->state = ANEG_STATE_LINK_OK; - } - break; - - case ANEG_STATE_LINK_OK: - ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK); - ret = ANEG_DONE; - break; - - case ANEG_STATE_NEXT_PAGE_WAIT_INIT: - /* ??? unimplemented */ - break; - - case ANEG_STATE_NEXT_PAGE_WAIT: - /* ??? unimplemented */ - break; - - default: - ret = ANEG_FAILED; - break; - }; - - return ret; -} - -static int tg3_setup_fiber_phy(struct tg3 *tp) -{ - uint32_t orig_pause_cfg; - uint16_t orig_active_speed; - uint8_t orig_active_duplex; - int current_link_up; - int i; - - orig_pause_cfg = - (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE)); - orig_active_speed = tp->link_config.active_speed; - orig_active_duplex = tp->link_config.active_duplex; - - tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); - tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; - tw32_carefully(MAC_MODE, tp->mac_mode); - - /* Reset when initting first time or we have a link. */ - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - /* Set PLL lock range. */ - tg3_writephy(tp, 0x16, 0x8007); - - /* SW reset */ - tg3_writephy(tp, MII_BMCR, BMCR_RESET); - - /* Wait for reset to complete. */ - mdelay(5); - - /* Config mode; select PMA/Ch 1 regs. */ - tg3_writephy(tp, 0x10, 0x8411); - - /* Enable auto-lock and comdet, select txclk for tx. */ - tg3_writephy(tp, 0x11, 0x0a10); - - tg3_writephy(tp, 0x18, 0x00a0); - tg3_writephy(tp, 0x16, 0x41ff); - - /* Assert and deassert POR. */ - tg3_writephy(tp, 0x13, 0x0400); - udelay(40); - tg3_writephy(tp, 0x13, 0x0000); - - tg3_writephy(tp, 0x11, 0x0a50); - udelay(40); - tg3_writephy(tp, 0x11, 0x0a10); - - /* Wait for signal to stabilize */ - mdelay(150); - - /* Deselect the channel register so we can read the PHYID - * later. - */ - tg3_writephy(tp, 0x10, 0x8011); - } - - /* Disable link change interrupt. */ - tw32_carefully(MAC_EVENT, 0); - - current_link_up = 0; - if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { - if (!(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) { - struct tg3_fiber_aneginfo aninfo; - int status = ANEG_FAILED; - unsigned int tick; - uint32_t tmp; - - memset(&aninfo, 0, sizeof(aninfo)); - aninfo.flags |= (MR_AN_ENABLE); - - tw32(MAC_TX_AUTO_NEG, 0); - - tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - tw32_carefully(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); - - tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); - - aninfo.state = ANEG_STATE_UNKNOWN; - aninfo.cur_time = 0; - tick = 0; - while (++tick < 195000) { - status = tg3_fiber_aneg_smachine(tp, &aninfo); - if (status == ANEG_DONE || - status == ANEG_FAILED) - break; - - udelay(1); - } - - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32_carefully(MAC_MODE, tp->mac_mode); - - if (status == ANEG_DONE && - (aninfo.flags & - (MR_AN_COMPLETE | MR_LINK_OK | - MR_LP_ADV_FULL_DUPLEX))) { - uint32_t local_adv, remote_adv; - - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (aninfo.flags & MR_LP_ADV_SYM_PAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE) - remote_adv |= LPA_PAUSE_ASYM; - - tg3_setup_flow_control(tp, local_adv, remote_adv); - - tp->tg3_flags |= - TG3_FLAG_GOT_SERDES_FLOWCTL; - current_link_up = 1; - } - for (i = 0; i < 60; i++) { - udelay(20); - tw32_carefully(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - if (current_link_up == 0 && - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - current_link_up = 1; - } - } else { - /* Forcing 1000FD link up. */ - current_link_up = 1; - } - } - - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - tw32_carefully(MAC_MODE, tp->mac_mode); - - tp->hw_status->status = - (SD_STATUS_UPDATED | - (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); - - for (i = 0; i < 100; i++) { - udelay(20); - tw32_carefully(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) - current_link_up = 0; - - if (current_link_up == 1) { - tp->link_config.active_speed = SPEED_1000; - tp->link_config.active_duplex = DUPLEX_FULL; - } else { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - } - - if (current_link_up != tp->carrier_ok) { - tp->carrier_ok = current_link_up; - tg3_link_report(tp); - } else { - uint32_t now_pause_cfg = - tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - if (orig_pause_cfg != now_pause_cfg || - orig_active_speed != tp->link_config.active_speed || - orig_active_duplex != tp->link_config.active_duplex) - tg3_link_report(tp); - } - - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { - tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - tw32_carefully(MAC_MODE, tp->mac_mode); - } - } - - return 0; -} -#else -#define tg3_setup_fiber_phy(TP) (-EINVAL) -#endif /* SUPPORT_FIBER_PHY */ - -static int tg3_setup_phy(struct tg3 *tp) -{ - int err; - - if (tp->phy_id == PHY_ID_SERDES) { - err = tg3_setup_fiber_phy(tp); - } else { - err = tg3_setup_copper_phy(tp); - } - - if (tp->link_config.active_speed == SPEED_1000 && - tp->link_config.active_duplex == DUPLEX_HALF) - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (0xff << TX_LENGTHS_SLOT_TIME_SHIFT))); - else - tw32(MAC_TX_LENGTHS, - ((2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT))); - - return err; -} - - -#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, uint32_t enable_bit) -{ - unsigned int i; - uint32_t val; - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { - 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 or 5787, just say success. - */ - return 0; - default: - break; - } - } - val = tr32(ofs); - val &= ~enable_bit; - tw32(ofs, val); - tr32(ofs); - - for (i = 0; i < MAX_WAIT_CNT; i++) { - udelay(100); - val = tr32(ofs); - if ((val & enable_bit) == 0) - break; - } - - if (i == MAX_WAIT_CNT) { - printf( "tg3_stop_block timed out, ofs=%#lx enable_bit=%3x\n", - ofs, enable_bit ); - return -ENODEV; - } - - return 0; -} - -static int tg3_abort_hw(struct tg3 *tp) -{ - int i, err; - uint32_t val; - - tg3_disable_ints(tp); - - tp->rx_mode &= ~RX_MODE_ENABLE; - tw32_carefully(MAC_RX_MODE, tp->rx_mode); - - 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, SNDBDC_MODE, SNDBDC_MODE_ENABLE); - if (err) - goto out; - - tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; - tw32_carefully(MAC_MODE, tp->mac_mode); - - tp->tx_mode &= ~TX_MODE_ENABLE; - tw32_carefully(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) { - printf("tg3_abort_hw timed out TX_MODE_ENABLE will not clear MAC_TX_MODE=%x\n", - (unsigned int) tr32(MAC_TX_MODE)); - return -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); - - val = tr32(FTQ_RESET); - val |= FTQ_RESET_DMA_READ_QUEUE | FTQ_RESET_DMA_HIGH_PRI_READ | - FTQ_RESET_SEND_BD_COMPLETION | FTQ_RESET_DMA_WRITE | - FTQ_RESET_DMA_HIGH_PRI_WRITE | FTQ_RESET_SEND_DATA_COMPLETION | - FTQ_RESET_HOST_COALESCING | FTQ_RESET_MAC_TX | - FTQ_RESET_RX_BD_COMPLETE | FTQ_RESET_RX_LIST_PLCMT | - FTQ_RESET_RX_DATA_COMPLETION; - tw32(FTQ_RESET, val); - - err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE); - err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE); - if (err) - goto out; - - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - -out: - return err; -} - -static void tg3_chip_reset(struct tg3 *tp) -{ - uint32_t val; - - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { - /* Force NVRAM to settle. - * This deals with a chip bug which can result in EEPROM - * corruption. - */ - if (tp->tg3_flags & TG3_FLAG_NVRAM) { - int i; - - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 100000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(10); - } - } - } - /* In Etherboot we don't need to worry about the 5701 - * REG_WRITE_BUG because we do all register writes indirectly. - */ - - // Alf: here patched - /* do the reset */ - val = GRC_MISC_CFG_CORECLK_RESET; - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - if (tr32(0x7e2c) == 0x60) { - tw32(0x7e2c, 0x20); - } - 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_5705) - || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) - || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) { - val |= GRC_MISC_CFG_KEEP_GPHY_POWER; - } - - // Alf : Please VALIDATE THIS. - // It is necessary in my case (5751) to prevent a reboot, but - // I have no idea about a side effect on any other version. - // It appears to be what's done in tigon3.c from Broadcom - if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { - tw32(GRC_MISC_CFG, 0x20000000) ; - val |= 0x20000000 ; - } - - tw32(GRC_MISC_CFG, val); - - /* Flush PCI posted writes. The normal MMIO registers - * are inaccessible at this time so this is the only - * way to make this reliably. 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); - - /* 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 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) - val |= PCISTATE_RETRY_SAME_DMA; - pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - - pci_restore_state(tp->pdev, tp->pci_cfg_state); - - /* Make sure PCI-X relaxed ordering bit is clear. */ - pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); - val &= ~PCIX_CAPS_RELAXED_ORDERING; - pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); - - tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); - - 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_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE); - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); - } - - tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl); -} - -static void tg3_stop_fw(struct tg3 *tp) -{ - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - uint32_t val; - int i; - - tg3_write_mem(NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); - val = tr32(GRC_RX_CPU_EVENT); - val |= (1 << 14); - tw32(GRC_RX_CPU_EVENT, val); - - /* Wait for RX cpu to ACK the event. */ - for (i = 0; i < 100; i++) { - if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14))) - break; - udelay(1); - } - } -} - -static int tg3_restart_fw(struct tg3 *tp, uint32_t state) -{ - uint32_t val; - int i; - - tg3_write_mem(NIC_SRAM_FIRMWARE_MBOX, - NIC_SRAM_FIRMWARE_MBOX_MAGIC1); - /* Wait for firmware initialization to complete. */ - for (i = 0; i < 100000; i++) { - tg3_read_mem(NIC_SRAM_FIRMWARE_MBOX, &val); - if (val == (uint32_t) ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) - break; - udelay(10); - } - if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_SUN_5704) && - !(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)) { - printf ( "Firmware will not restart magic=%#x\n", - val ); - return -ENODEV; - } - if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { - state = DRV_STATE_SUSPEND; - } - - if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && - (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)) { - // Enable PCIE bug fix - tg3_read_mem(0x7c00, &val); - tg3_write_mem(0x7c00, val | 0x02000000); - } - tg3_write_mem(NIC_SRAM_FW_DRV_STATE_MBOX, state); - return 0; -} - -static int tg3_halt(struct tg3 *tp) -{ - tg3_stop_fw(tp); - tg3_abort_hw(tp); - tg3_chip_reset(tp); - return tg3_restart_fw(tp, DRV_STATE_UNLOAD); -} - -static void __tg3_set_mac_addr(struct tg3 *tp) -{ - uint32_t addr_high, addr_low; - int i; - - addr_high = ((tp->nic->node_addr[0] << 8) | - tp->nic->node_addr[1]); - addr_low = ((tp->nic->node_addr[2] << 24) | - (tp->nic->node_addr[3] << 16) | - (tp->nic->node_addr[4] << 8) | - (tp->nic->node_addr[5] << 0)); - for (i = 0; i < 4; i++) { - 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_5700) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)) { - 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->nic->node_addr[0] + - tp->nic->node_addr[1] + - tp->nic->node_addr[2] + - tp->nic->node_addr[3] + - tp->nic->node_addr[4] + - tp->nic->node_addr[5]) & - TX_BACKOFF_SEED_MASK; - tw32(MAC_TX_BACKOFF_SEED, addr_high); -} - -static void tg3_set_bdinfo(struct tg3 *tp, uint32_t bdinfo_addr, - dma_addr_t mapping, uint32_t maxlen_flags, - uint32_t nic_addr) -{ - tg3_write_mem((bdinfo_addr + - TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH), - ((uint64_t) mapping >> 32)); - tg3_write_mem((bdinfo_addr + - TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW), - ((uint64_t) mapping & 0xffffffff)); - tg3_write_mem((bdinfo_addr + - TG3_BDINFO_MAXLEN_FLAGS), - maxlen_flags); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - tg3_write_mem((bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr); - } -} - - -static void tg3_init_rings(struct tg3 *tp) -{ - unsigned i; - - /* Zero out the tg3 variables */ - memset(&tg3_bss, 0, sizeof(tg3_bss)); - tp->rx_std = &tg3_bss.rx_std[0]; - tp->rx_rcb = &tg3_bss.rx_rcb[0]; - tp->tx_ring = &tg3_bss.tx_ring[0]; - tp->hw_status = &tg3_bss.hw_status; - tp->hw_stats = &tg3_bss.hw_stats; - tp->mac_mode = 0; - - - /* 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. - */ - - /* 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. - */ - for (i = 0; i < TG3_RX_RING_SIZE; i++) { - struct tg3_rx_buffer_desc *rxd; - - rxd = &tp->rx_std[i]; - rxd->idx_len = (RX_PKT_BUF_SZ - 2 - 64) << RXD_LEN_SHIFT; - rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); - rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT)); - - /* Note where the receive buffer for the ring is placed */ - rxd->addr_hi = 0; - rxd->addr_lo = virt_to_bus( - &tg3_bss.rx_bufs[i%TG3_DEF_RX_RING_PENDING][2]); - } -} - -#define TG3_WRITE_SETTINGS(TABLE) \ -do { \ - const uint32_t *_table, *_end; \ - _table = TABLE; \ - _end = _table + sizeof(TABLE)/sizeof(TABLE[0]); \ - for(; _table < _end; _table += 2) { \ - tw32(_table[0], _table[1]); \ - } \ -} while(0) - - -/* initialize/reset the tg3 */ -static int tg3_setup_hw(struct tg3 *tp) -{ - uint32_t val, rdmac_mode; - int i, err, limit; - - /* Simply don't support setups with extremly buggy firmware in etherboot */ - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { - printf("Error 5701_A0 firmware bug detected\n"); - return -EINVAL; - } - - tg3_disable_ints(tp); - - /* Originally this was all in tg3_init_hw */ - - /* Force the chip into D0. */ - tg3_set_power_state_0(tp); - - tg3_switch_clocks(tp); - - tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - - // This should go somewhere else -#define T3_PCIE_CAPABILITY_ID_REG 0xD0 -#define T3_PCIE_CAPABILITY_ID 0x10 -#define T3_PCIE_CAPABILITY_REG 0xD2 - - /* Originally this was all in tg3_reset_hw */ - - tg3_stop_fw(tp); - - /* No need to call tg3_abort_hw here, it is called before tg3_setup_hw. */ - - tg3_chip_reset(tp); - - tw32(GRC_MODE, tp->grc_mode); /* Redundant? */ - - err = tg3_restart_fw(tp, DRV_STATE_START); - if (err) - return err; - - if (tp->phy_id == PHY_ID_SERDES) { - tp->mac_mode = MAC_MODE_PORT_MODE_TBI; - } - tw32_carefully(MAC_MODE, tp->mac_mode); - - - /* This works around an issue with Athlon chipsets on - * B3 tigon3 silicon. This bit has no effect on any - * other revision. - * Alf: Except 5750 ! (which reboots) - */ - - if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) - tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; - tw32_carefully(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); - - if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && - (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { - val = tr32(TG3PCI_PCISTATE); - val |= PCISTATE_RETRY_SAME_DMA; - tw32(TG3PCI_PCISTATE, 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. - */ - tg3_init_rings(tp); - - /* Clear statistics/status block in chip */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - for (i = NIC_SRAM_STATS_BLK; - i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; - i += sizeof(uint32_t)) { - tg3_write_mem(i, 0); - udelay(40); - } - } - - /* This value is determined during the probe time DMA - * engine test, tg3_setup_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_TX_PHDR_CSUM; - tp->grc_mode |= GRC_MODE_NO_RX_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. */ - tw32(GRC_MISC_CFG, - (65 << GRC_MISC_CFG_PRESCALAR_SHIFT)); - - /* Initialize MBUF/DESC pool. */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { - /* Do nothing. */ - } else if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) && - (tp->pci_chip_rev_id != CHIPREV_ID_5721)) { - 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); - } - if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) { - 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); - } else { - tw32(BUFMGR_MB_RDMA_LOW_WATER, - tp->bufmgr_config.mbuf_read_dma_low_water_jumbo); - tw32(BUFMGR_MB_MACRX_LOW_WATER, - tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo); - tw32(BUFMGR_MB_HIGH_WATER, - tp->bufmgr_config.mbuf_high_water_jumbo); - } - tw32(BUFMGR_DMA_LOW_WATER, - tp->bufmgr_config.dma_low_water); - tw32(BUFMGR_DMA_HIGH_WATER, - tp->bufmgr_config.dma_high_water); - - tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); - for (i = 0; i < 2000; i++) { - if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE) - break; - udelay(10); - } - if (i >= 2000) { - printf("tg3_setup_hw cannot enable BUFMGR\n"); - return -ENODEV; - } - - tw32(FTQ_RESET, 0xffffffff); - tw32(FTQ_RESET, 0x00000000); - for (i = 0; i < 2000; i++) { - if (tr32(FTQ_RESET) == 0x00000000) - break; - udelay(10); - } - if (i >= 2000) { - printf("tg3_setup_hw cannot reset FTQ\n"); - return -ENODEV; - } - - /* 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. - * - * ??? No space allocated for mini receive ring? :( - * - * The size of each ring is fixed in the firmware, but the location is - * configurable. - */ - { - static const uint32_t table_all[] = { - /* Setup replenish thresholds. */ - RCVBDI_STD_THRESH, TG3_DEF_RX_RING_PENDING / 8, - - /* Etherboot lives below 4GB */ - RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, 0, - RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC, - }; - static const uint32_t table_not_5705[] = { - /* Buffer maximum length */ - RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT, - - /* Disable the mini frame rx ring */ - RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED, - - /* Disable the jumbo frame rx ring */ - RCVBDI_JUMBO_THRESH, 0, - RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED, - - - }; - TG3_WRITE_SETTINGS(table_all); - tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - virt_to_bus(tp->rx_std)); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) { - tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, - RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT); - } else { - TG3_WRITE_SETTINGS(table_not_5705); - } - } - - - /* There is only one send ring on 5705 and 5787, no need to explicitly - * disable the others. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) { - /* Clear out send RCB ring in SRAM. */ - for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE) - tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED); - } - - tp->tx_prod = 0; - tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - tw32_mailbox2(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - - tg3_set_bdinfo(tp, - NIC_SRAM_SEND_RCB, - virt_to_bus(tp->tx_ring), - (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - - /* There is only one receive return ring on 5705 and 5787, no need to - * explicitly disable the others. - */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) { - for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; i += TG3_BDINFO_SIZE) { - tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - } - } - - tp->rx_rcb_ptr = 0; - tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0); - - tg3_set_bdinfo(tp, - NIC_SRAM_RCV_RET_RCB, - virt_to_bus(tp->rx_rcb), - (TG3_RX_RCB_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT), - 0); - - tp->rx_std_ptr = TG3_DEF_RX_RING_PENDING; - tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, - tp->rx_std_ptr); - - tw32_mailbox2(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, 0); - - /* Initialize MAC address and backoff seed. */ - __tg3_set_mac_addr(tp); - - /* 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 (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) { - if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { - rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; - } - } - } - - /* Setup host coalescing engine. */ - tw32(HOSTCC_MODE, 0); - for (i = 0; i < 2000; i++) { - if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE)) - break; - udelay(10); - } - - tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | - MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; - tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); - - 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) - tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OUTPUT1); - tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tr32(MAILBOX_INTERRUPT_0); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - tw32_carefully(DMAC_MODE, DMAC_MODE_ENABLE); - } - - 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); - if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) && - ((tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0) && - !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) { - val |= WDMAC_MODE_RX_ACCEL; - } - - /* Host coalescing bug fix */ - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) - val |= (1 << 29); - - tw32_carefully(WDMAC_MODE, val); - - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { - val = tr32(TG3PCI_X_CAPS); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { - val &= PCIX_CAPS_BURST_MASK; - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK); - val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT); - if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) - val |= (tp->split_mode_max_reqs << - PCIX_CAPS_SPLIT_SHIFT); - } - tw32(TG3PCI_X_CAPS, val); - } - - tw32_carefully(RDMAC_MODE, rdmac_mode); - { - static const uint32_t table_all[] = { - /* MTU + ethernet header + FCS + optional VLAN tag */ - MAC_RX_MTU_SIZE, ETH_MAX_MTU + ETH_HLEN + 8, - - /* The slot time is changed by tg3_setup_phy if we - * run at gigabit with half duplex. - */ - MAC_TX_LENGTHS, - (2 << TX_LENGTHS_IPG_CRS_SHIFT) | - (6 << TX_LENGTHS_IPG_SHIFT) | - (32 << TX_LENGTHS_SLOT_TIME_SHIFT), - - /* Receive rules. */ - MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS, - RCVLPC_CONFIG, 0x0181, - - /* Receive/send statistics. */ - RCVLPC_STATS_ENABLE, 0xffffff, - RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE, - SNDDATAI_STATSENAB, 0xffffff, - SNDDATAI_STATSCTRL, (SNDDATAI_SCTRL_ENABLE |SNDDATAI_SCTRL_FASTUPD), - - /* Host coalescing engine */ - HOSTCC_RXCOL_TICKS, 0, - HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS, - HOSTCC_RXMAX_FRAMES, 1, - HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES, - HOSTCC_RXCOAL_MAXF_INT, 1, - HOSTCC_TXCOAL_MAXF_INT, 0, - - /* Status/statistics block address. */ - /* Etherboot lives below 4GB, so HIGH == 0 */ - HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0, - - /* No need to enable 32byte coalesce mode. */ - HOSTCC_MODE, HOSTCC_MODE_ENABLE | 0, - - RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE, - RCVLPC_MODE, RCVLPC_MODE_ENABLE, - - RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE, - - SNDDATAC_MODE, SNDDATAC_MODE_ENABLE, - SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE, - RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB, - RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ, - SNDDATAI_MODE, SNDDATAI_MODE_ENABLE, - SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE, - SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE, - - /* Accept all multicast frames. */ - MAC_HASH_REG_0, 0xffffffff, - MAC_HASH_REG_1, 0xffffffff, - MAC_HASH_REG_2, 0xffffffff, - MAC_HASH_REG_3, 0xffffffff, - }; - static const uint32_t table_not_5705[] = { - /* Host coalescing engine */ - HOSTCC_RXCOAL_TICK_INT, 0, - HOSTCC_TXCOAL_TICK_INT, 0, - - /* Status/statistics block address. */ - /* Etherboot lives below 4GB, so HIGH == 0 */ - HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS, - HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0, - HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK, - HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK, - - RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE, - - MBFREE_MODE, MBFREE_MODE_ENABLE, - }; - TG3_WRITE_SETTINGS(table_all); - tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - virt_to_bus(tp->hw_stats)); - tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - virt_to_bus(tp->hw_status)); - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) { - TG3_WRITE_SETTINGS(table_not_5705); - } - } - - tp->tx_mode = TX_MODE_ENABLE; - tw32_carefully(MAC_TX_MODE, tp->tx_mode); - - tp->rx_mode = RX_MODE_ENABLE; - tw32_carefully(MAC_RX_MODE, tp->rx_mode); - - tp->mi_mode = MAC_MI_MODE_BASE; - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - - tw32(MAC_LED_CTRL, 0); - tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->phy_id == PHY_ID_SERDES) { - tw32_carefully(MAC_RX_MODE, RX_MODE_RESET); - } - tp->rx_mode |= RX_MODE_KEEP_VLAN_TAG; /* drop tagged vlan packets */ - tw32_carefully(MAC_RX_MODE, tp->rx_mode); - - 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. - */ - tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2); - tr32(MAC_LOW_WMARK_MAX_RX_FRAME); - - err = tg3_setup_phy(tp); - - /* Ignore CRC stats */ - - /* 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 ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) - || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) - limit = 8; - else - limit = 16; - if (tp->tg3_flags & TG3_FLAG_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 err; -} - - - -/* Chips other than 5700/5701 use the NVRAM for fetching info. */ -static void tg3_nvram_init(struct tg3 *tp) -{ - tw32(GRC_EEPROM_ADDR, - (EEPROM_ADDR_FSM_RESET | - (EEPROM_DEFAULT_CLOCK_PERIOD << - EEPROM_ADDR_CLKPERD_SHIFT))); - - mdelay(1); - - /* Enable seeprom accesses. */ - tw32_carefully(GRC_LOCAL_CTRL, - tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { - uint32_t nvcfg1 = tr32(NVRAM_CFG1); - - tp->tg3_flags |= TG3_FLAG_NVRAM; - if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) { - if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE) - tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; - } else { - nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS; - tw32(NVRAM_CFG1, nvcfg1); - } - - } else { - tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED); - } -} - - -static int tg3_nvram_read_using_eeprom( - struct tg3 *tp __unused, uint32_t offset, uint32_t *val) -{ - uint32_t 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 < 10000; i++) { - tmp = tr32(GRC_EEPROM_ADDR); - - if (tmp & EEPROM_ADDR_COMPLETE) - break; - udelay(100); - } - if (!(tmp & EEPROM_ADDR_COMPLETE)) { - return -EBUSY; - } - - *val = tr32(GRC_EEPROM_DATA); - return 0; -} - -static int tg3_nvram_read(struct tg3 *tp, uint32_t offset, uint32_t *val) -{ - int i, saw_done_clear; - - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) - return tg3_nvram_read_using_eeprom(tp, offset, val); - - if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) - offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) << - NVRAM_BUFFERED_PAGE_POS) + - (offset % NVRAM_BUFFERED_PAGE_SIZE); - - if (offset > NVRAM_ADDR_MSK) - return -EINVAL; - - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 1000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(20); - } - - tw32(NVRAM_ADDR, offset); - tw32(NVRAM_CMD, - NVRAM_CMD_RD | NVRAM_CMD_GO | - NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); - - /* Wait for done bit to clear then set again. */ - saw_done_clear = 0; - for (i = 0; i < 1000; i++) { - udelay(10); - if (!saw_done_clear && - !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE)) - saw_done_clear = 1; - else if (saw_done_clear && - (tr32(NVRAM_CMD) & NVRAM_CMD_DONE)) - break; - } - if (i >= 1000) { - tw32(NVRAM_SWARB, SWARB_REQ_CLR1); - return -EBUSY; - } - - *val = bswap_32(tr32(NVRAM_RDDATA)); - tw32(NVRAM_SWARB, 0x20); - - return 0; -} - -struct subsys_tbl_ent { - uint16_t subsys_vendor, subsys_devid; - uint32_t phy_id; -}; - -static struct subsys_tbl_ent subsys_id_to_phy_id[] = { - /* Broadcom boards. */ - { 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ - { 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ - { 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { 0x14e4, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ - { 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ - { 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { 0x14e4, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ - { 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ - { 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ - { 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */ - { 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */ - - /* 3com boards. */ - { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ - { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - /* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX }, 3C996CT */ - /* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX }, 3C997T */ - { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ - /* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX }, 3C997SZ */ - { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ - { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ - - /* DELL boards. */ - { PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */ - { PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */ - { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */ - { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */ - { PCI_VENDOR_ID_DELL, 0x0179, PHY_ID_BCM5751 }, /* EtherXpress */ - - /* Fujitsu Siemens Computer */ - { PCI_VENDOR_ID_FSC, 0x105d, PHY_ID_BCM5751 }, /* Futro C200 */ - - /* Compaq boards. */ - { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ - { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ - { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ - { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ - { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 } /* NC7780_2 */ -}; - -static int tg3_phy_probe(struct tg3 *tp) -{ - uint32_t eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; - uint32_t hw_phy_id, hw_phy_id_masked; - enum phy_led_mode eeprom_led_mode; - uint32_t val; - unsigned i; - int eeprom_signature_found, err; - - tp->phy_id = PHY_ID_INVALID; - - for (i = 0; i < sizeof(subsys_id_to_phy_id)/sizeof(subsys_id_to_phy_id[0]); i++) { - if ((subsys_id_to_phy_id[i].subsys_vendor == tp->subsystem_vendor) && - (subsys_id_to_phy_id[i].subsys_devid == tp->subsystem_device)) { - tp->phy_id = subsys_id_to_phy_id[i].phy_id; - break; - } - } - - eeprom_phy_id = PHY_ID_INVALID; - eeprom_led_mode = led_mode_auto; - eeprom_signature_found = 0; - tg3_read_mem(NIC_SRAM_DATA_SIG, &val); - if (val == NIC_SRAM_DATA_SIG_MAGIC) { - uint32_t nic_cfg; - - tg3_read_mem(NIC_SRAM_DATA_CFG, &nic_cfg); - tp->nic_sram_data_cfg = nic_cfg; - - eeprom_signature_found = 1; - - if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == - NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { - eeprom_phy_id = PHY_ID_SERDES; - } else { - uint32_t nic_phy_id; - - tg3_read_mem(NIC_SRAM_DATA_PHY_ID, &nic_phy_id); - if (nic_phy_id != 0) { - uint32_t id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; - uint32_t 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; - } - } - - switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) { - case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD: - eeprom_led_mode = led_mode_three_link; - break; - - case NIC_SRAM_DATA_CFG_LED_LINK_SPD: - eeprom_led_mode = led_mode_link10; - break; - - default: - eeprom_led_mode = led_mode_auto; - break; - }; - 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)) && - (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) { - tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; - } - - if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) - tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; - if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) - tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; - } - - /* 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 & PHY_ID_MASK; - - if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { - tp->phy_id = hw_phy_id; - } else { - /* phy_id currently holds the value found in the - * subsys_id_to_phy_id[] table or PHY_ID_INVALID - * if a match was not found there. - */ - if (tp->phy_id == PHY_ID_INVALID) { - if (!eeprom_signature_found || - !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK)) - return -ENODEV; - tp->phy_id = eeprom_phy_id; - } - } - - err = tg3_phy_reset(tp); - if (err) - return err; - - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) { - uint32_t mii_tg3_ctrl; - - /* These chips, when reset, only advertise 10Mb - * capabilities. Fix that. - */ - err = tg3_writephy(tp, MII_ADVERTISE, - (ADVERTISE_CSMA | - ADVERTISE_PAUSE_CAP | - ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL)); - mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL | - MII_TG3_CTRL_AS_MASTER | - MII_TG3_CTRL_ENABLE_AS_MASTER); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - mii_tg3_ctrl = 0; - - err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl); - err |= tg3_writephy(tp, MII_BMCR, - (BMCR_ANRESTART | BMCR_ANENABLE)); - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) { - tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); - tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); - tg3_writedsp(tp, MII_TG3_DSP_RW_PORT, 0x2aaa); - } - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { - tg3_writephy(tp, 0x1c, 0x8d68); - tg3_writephy(tp, 0x1c, 0x8d68); - } - - /* Enable Ethernet@WireSpeed */ - tg3_phy_set_wirespeed(tp); - - if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) { - err = tg3_init_5401phy_dsp(tp); - } - - /* Determine the PHY led mode. - * Be careful if this gets set wrong it can result in an inability to - * establish a link. - */ - if (tp->phy_id == PHY_ID_SERDES) { - tp->led_mode = led_mode_three_link; - } - else if (tp->subsystem_vendor == PCI_VENDOR_ID_DELL) { - tp->led_mode = led_mode_link10; - } else { - tp->led_mode = led_mode_three_link; - if (eeprom_signature_found && - eeprom_led_mode != led_mode_auto) - tp->led_mode = eeprom_led_mode; - } - - if (tp->phy_id == PHY_ID_SERDES) - tp->link_config.advertising = - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | - ADVERTISED_FIBRE); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - tp->link_config.advertising &= - ~(ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - - return err; -} - -#if SUPPORT_PARTNO_STR -static void tg3_read_partno(struct tg3 *tp) -{ - unsigned char vpd_data[256]; - int i; - - for (i = 0; i < 256; i += 4) { - uint32_t tmp; - - if (tg3_nvram_read(tp, 0x100 + i, &tmp)) - goto out_not_found; - - vpd_data[i + 0] = ((tmp >> 0) & 0xff); - vpd_data[i + 1] = ((tmp >> 8) & 0xff); - vpd_data[i + 2] = ((tmp >> 16) & 0xff); - vpd_data[i + 3] = ((tmp >> 24) & 0xff); - } - - /* Now parse and find the part number. */ - for (i = 0; i < 256; ) { - unsigned char val = vpd_data[i]; - int block_end; - - if (val == 0x82 || val == 0x91) { - i = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); - continue; - } - - if (val != 0x90) - goto out_not_found; - - block_end = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); - i += 3; - while (i < block_end) { - if (vpd_data[i + 0] == 'P' && - vpd_data[i + 1] == 'N') { - int partno_len = vpd_data[i + 2]; - - if (partno_len > 24) - goto out_not_found; - - memcpy(tp->board_part_number, - &vpd_data[i + 3], - partno_len); - - /* Success. */ - return; - } - } - - /* Part number not found. */ - goto out_not_found; - } - -out_not_found: - memcpy(tp->board_part_number, "none", sizeof("none")); -} -#else -#define tg3_read_partno(TP) ((TP)->board_part_number[0] = '\0') -#endif - -static int tg3_get_invariants(struct tg3 *tp) -{ - uint32_t misc_ctrl_reg; - uint32_t pci_state_reg, grc_misc_cfg; - uint16_t pci_cmd; - uint8_t pci_latency; - uint32_t val ; - int err; - - /* Read the subsystem vendor and device ids */ - 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 sun_5704 code needs infrastructure etherboot does have - * ignore it for now. - */ - - /* If we have an AMD 762 or Intel ICH/ICH0 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. - * - * TG3_FLAG_MBOX_WRITE_REORDER has been forced on. - */ - - /* 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 boundry - * 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; - /* Also, force SERR#/PERR# in PCI command. */ - pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; - 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); - - /* 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); - - pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 64) { - pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, 64); - } - - pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); - - /* If this is a 5700 BX chipset, and 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. - * - * In etherboot to simplify things we just always use this work around. - */ - if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) { - tp->tg3_flags |= TG3_FLAG_PCIX_MODE; - } - /* Back to back register writes can cause problems on the 5701, - * the workaround is to read back all reg writes except those to - * mailbox regs. - * In etherboot we always use indirect register accesses so - * we don't see this. - */ - - if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0) - tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED; - if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0) - tp->tg3_flags |= TG3_FLAG_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); - } - - /* determine if it is PCIE system */ - // Alf : I have no idea what this is about... - // But it's definitely usefull - val = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); - if (val) - tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; - - /* Force the chip into D0. */ - tg3_set_power_state_0(tp); - - /* Etherboot does not ask the tg3 to do checksums */ - /* Etherboot does not ask the tg3 to do jumbo frames */ - /* Ehterboot does not ask the tg3 to use WakeOnLan. */ - - /* 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_5750) || - ((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->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; - } - - /* Avoid tagged irq status etherboot does not use irqs */ - - /* Only 5701 and later support tagged irq status mode. - * Also, 5788 chips cannot use tagged irq status. - * - * However, since etherboot does not use irqs avoid tagged irqs - * status because the interrupt condition is more difficult to - * fully clear in that mode. - */ - - /* Since some 5700_AX && 5700_BX have problems with 32BYTE - * coalesce_mode, and the rest work fine anything set. - * Don't enable HOST_CC_MODE_32BYTE in etherboot. - */ - - /* Initialize MAC MI mode, polling disabled. */ - tw32_carefully(MAC_MI_MODE, tp->mi_mode); - - /* Initialize data/descriptor byte/word swapping. */ - tw32(GRC_MODE, tp->grc_mode); - - tg3_switch_clocks(tp); - - /* Clear this out for sanity. */ - tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - - /* Etherboot does not need to check if the PCIX_TARGET_HWBUG - * is needed. It always uses it. - */ - - udelay(50); - tg3_nvram_init(tp); - - /* The TX descriptors will reside in main memory. - */ - - /* See which board we are using. - */ - 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_5704 && - grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { - tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; - tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; - } - - 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)) - tp->tg3_flags2 |= TG3_FLG2_IS_5788; - -#define PCI_DEVICE_ID_TIGON3_5901 0x170d -#define PCI_DEVICE_ID_TIGON3_5901_2 0x170e - - /* 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->tg3_flags |= TG3_FLAG_10_100_ONLY; - } - - err = tg3_phy_probe(tp); - if (err) { - printf("phy probe failed, err %d\n", err); - } - - tg3_read_partno(tp); - - - /* 5700 BX chips need to have their TX producer index mailboxes - * written twice to workaround a bug. - * In etherboot we do this unconditionally to simplify things. - */ - - /* 5700 chips can get confused if TX buffers straddle the - * 4GB address boundary in some cases. - * - * In etherboot we can ignore the problem as etherboot lives below 4GB. - */ - - /* In etherboot wake-on-lan is unconditionally disabled */ - return err; -} - -static int tg3_get_device_address(struct tg3 *tp) -{ - struct nic *nic = tp->nic; - uint32_t hi, lo, mac_offset; - - if (PCI_FUNC(tp->pdev->busdevfn) == 0) - mac_offset = 0x7c; - else - mac_offset = 0xcc; - - /* First try to get it from MAC address mailbox. */ - tg3_read_mem(NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi); - if ((hi >> 16) == 0x484b) { - nic->node_addr[0] = (hi >> 8) & 0xff; - nic->node_addr[1] = (hi >> 0) & 0xff; - - tg3_read_mem(NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo); - nic->node_addr[2] = (lo >> 24) & 0xff; - nic->node_addr[3] = (lo >> 16) & 0xff; - nic->node_addr[4] = (lo >> 8) & 0xff; - nic->node_addr[5] = (lo >> 0) & 0xff; - } - /* Next, try NVRAM. */ - else if (!tg3_nvram_read(tp, mac_offset + 0, &hi) && - !tg3_nvram_read(tp, mac_offset + 4, &lo)) { - nic->node_addr[0] = ((hi >> 16) & 0xff); - nic->node_addr[1] = ((hi >> 24) & 0xff); - nic->node_addr[2] = ((lo >> 0) & 0xff); - nic->node_addr[3] = ((lo >> 8) & 0xff); - nic->node_addr[4] = ((lo >> 16) & 0xff); - nic->node_addr[5] = ((lo >> 24) & 0xff); - } - /* Finally just fetch it out of the MAC control regs. */ - else { - hi = tr32(MAC_ADDR_0_HIGH); - lo = tr32(MAC_ADDR_0_LOW); - - nic->node_addr[5] = lo & 0xff; - nic->node_addr[4] = (lo >> 8) & 0xff; - nic->node_addr[3] = (lo >> 16) & 0xff; - nic->node_addr[2] = (lo >> 24) & 0xff; - nic->node_addr[1] = hi & 0xff; - nic->node_addr[0] = (hi >> 8) & 0xff; - } - - return 0; -} - - -static int tg3_setup_dma(struct tg3 *tp) -{ - tw32(TG3PCI_CLOCK_CTRL, 0); - - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) { - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { - tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT); - } - } else { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x7 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x00 << DMA_RWCTRL_MIN_DMA_SHIFT); - else - tp->dma_rwctrl = - (0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | - (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) | - (0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) | - (0x3 << DMA_RWCTRL_READ_WATER_SHIFT) | - (0x0f << DMA_RWCTRL_MIN_DMA_SHIFT); - - /* Wheee, some more chip bugs... */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)) { - uint32_t ccval = tr32(TG3PCI_CLOCK_CTRL) & 0x1f; - - if ((ccval == 0x6) || (ccval == 0x7)) { - tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; - } - } - } - - 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 &= ~(DMA_RWCTRL_MIN_DMA << DMA_RWCTRL_MIN_DMA_SHIFT); - } - - /* - Alf : Tried that, but it does not work. Should be this way though :-( - if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - tp->dma_rwctrl |= 0x001f0000; - } - */ - tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE; - - tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); - - return 0; -} - -static void tg3_init_link_config(struct tg3 *tp) -{ - tp->link_config.advertising = - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | ADVERTISED_MII); - tp->carrier_ok = 0; - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; -} - - -#if SUPPORT_PHY_STR -static const char * tg3_phy_string(struct tg3 *tp) -{ - switch (tp->phy_id & PHY_ID_MASK) { - case PHY_ID_BCM5400: return "5400"; - case PHY_ID_BCM5401: return "5401"; - case PHY_ID_BCM5411: return "5411"; - case PHY_ID_BCM5701: return "5701"; - case PHY_ID_BCM5703: return "5703"; - case PHY_ID_BCM5704: return "5704"; - case PHY_ID_BCM5705: return "5705"; - case PHY_ID_BCM5750: return "5750"; - case PHY_ID_BCM5751: return "5751"; - case PHY_ID_BCM5787: return "5787"; - case PHY_ID_BCM8002: return "8002/serdes"; - case PHY_ID_SERDES: return "serdes"; - default: return "unknown"; - }; -} -#else -#define tg3_phy_string(TP) "?" -#endif - - -static void tg3_poll_link(struct tg3 *tp) -{ - uint32_t mac_stat; - - mac_stat = tr32(MAC_STATUS); - if (tp->phy_id == PHY_ID_SERDES) { - if (tp->carrier_ok? - (mac_stat & MAC_STATUS_LNKSTATE_CHANGED): - (mac_stat & MAC_STATUS_PCS_SYNCED)) { - tw32_carefully(MAC_MODE, tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK); - tw32_carefully(MAC_MODE, tp->mac_mode); - - tg3_setup_phy(tp); - } - } - else { - if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) { - tg3_setup_phy(tp); - } - } -} - -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static void tg3_ack_irqs(struct tg3 *tp) -{ - if (tp->hw_status->status & SD_STATUS_UPDATED) { - /* - * writing any value to intr-mbox-0 clears PCI INTA# and - * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the - * NIC to stop sending us irqs, engaging "in-intr-handler" - * event coalescing. - */ - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000001); - /* - * Flush PCI write. This also guarantees that our - * status block has been flushed to host memory. - */ - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); - tp->hw_status->status &= ~SD_STATUS_UPDATED; - } -} - -static int tg3_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 tg3 *tp = &tg3; - int result; - - result = 0; - - if ( (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) && !retrieve ) - return 1; - - tg3_ack_irqs(tp); - - if (tp->hw_status->idx[0].rx_producer != tp->rx_rcb_ptr) { - struct tg3_rx_buffer_desc *desc; - unsigned int len; - desc = &tp->rx_rcb[tp->rx_rcb_ptr]; - if ((desc->opaque & RXD_OPAQUE_RING_MASK) == RXD_OPAQUE_RING_STD) { - len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */ - - nic->packetlen = len; - memcpy(nic->packet, bus_to_virt(desc->addr_lo), len); - result = 1; - } - tp->rx_rcb_ptr = (tp->rx_rcb_ptr + 1) % TG3_RX_RCB_RING_SIZE; - - /* ACK the status ring */ - tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, tp->rx_rcb_ptr); - - /* Refill RX ring. */ - if (result) { - tp->rx_std_ptr = (tp->rx_std_ptr + 1) % TG3_RX_RING_SIZE; - tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_std_ptr); - } - } - tg3_poll_link(tp); - return result; -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -#if 0 -static void tg3_set_txd(struct tg3 *tp, int entry, - dma_addr_t mapping, int len, uint32_t flags, - uint32_t mss_and_is_end) -{ - struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; - int is_end = (mss_and_is_end & 0x1); - if (is_end) { - flags |= TXD_FLAG_END; - } - - txd->addr_hi = 0; - txd->addr_lo = mapping & 0xffffffff; - txd->len_flags = (len << TXD_LEN_SHIFT) | flags; - txd->vlan_tag = 0 << TXD_VLAN_TAG_SHIFT; -} -#endif - -static void tg3_transmit(struct nic *nic, const char *dst_addr, - unsigned int type, unsigned int size, const char *packet) -{ - static int frame_idx; - struct eth_frame *frame; - - /* send the packet to destination */ - struct tg3_tx_buffer_desc *txd; - struct tg3 *tp; - uint32_t entry; - int i; - - /* Wait until there is a free packet frame */ - tp = &tg3; - i = 0; - entry = tp->tx_prod; - while((tp->hw_status->idx[0].tx_consumer != entry) && - (tp->hw_status->idx[0].tx_consumer != PREV_TX(entry))) { - mdelay(10); /* give the nick a chance */ - if (++i > 500) { /* timeout 5s for transmit */ - printf("transmit timed out\n"); - tg3_halt(tp); - tg3_setup_hw(tp); - return; - } - } - if (i != 0) { - printf("#"); - } - - /* Copy the packet to the our local buffer */ - frame = &tg3_bss.tx_frame[frame_idx]; - memcpy(frame->dst_addr, dst_addr, ETH_ALEN); - memcpy(frame->src_addr, nic->node_addr, ETH_ALEN); - frame->type = htons(type); - memset(frame->data, 0, sizeof(frame->data)); - memcpy(frame->data, packet, size); - - /* Setup the ring buffer entry to transmit */ - txd = &tp->tx_ring[entry]; - txd->addr_hi = 0; /* Etherboot runs under 4GB */ - txd->addr_lo = virt_to_bus(frame); - txd->len_flags = ((size + ETH_HLEN) << TXD_LEN_SHIFT) | TXD_FLAG_END; - txd->vlan_tag = 0 << TXD_VLAN_TAG_SHIFT; - - /* Advance to the next entry */ - entry = NEXT_TX(entry); - frame_idx ^= 1; - - /* Packets are ready, update Tx producer idx local and on card */ - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - tw32_mailbox2((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - tp->tx_prod = entry; -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void tg3_disable ( struct nic *nic __unused ) { - struct tg3 *tp = &tg3; - /* 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. - */ - tg3_halt(tp); - tp->tg3_flags &= ~(TG3_FLAG_INIT_COMPLETE|TG3_FLAG_GOT_SERDES_FLOWCTL); - tp->carrier_ok = 0; - iounmap((void *)tp->regs); -} - -/************************************************************************** -IRQ - Enable, Disable, or Force interrupts -***************************************************************************/ -static void tg3_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 tg3_operations = { - .connect = dummy_connect, - .poll = tg3_poll, - .transmit = tg3_transmit, - .irq = tg3_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 tg3_probe ( struct nic *nic, struct pci_device *pdev ) { - - struct tg3 *tp = &tg3; - unsigned long tg3reg_base, tg3reg_len; - int i, err, pm_cap; - - memset(tp, 0, sizeof(*tp)); - - adjust_pci_device(pdev); - - nic->irqno = 0; - nic->ioaddr = pdev->ioaddr; - - /* Find power-management capability. */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap == 0) { - printf("Cannot find PowerManagement capability, aborting.\n"); - return 0; - } - tg3reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0); - if (tg3reg_base == -1UL) { - printf("Unuseable bar\n"); - return 0; - } - tg3reg_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0); - - tp->pdev = pdev; - tp->nic = nic; - tp->pm_cap = pm_cap; - tp->rx_mode = 0; - tp->tx_mode = 0; - tp->mi_mode = MAC_MI_MODE_BASE; - tp->tg3_flags = 0 & ~TG3_FLAG_INIT_COMPLETE; - - /* 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 - tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); - if (tp->regs == 0UL) { - printf("Cannot map device registers, aborting\n"); - return 0; - } - - tg3_init_link_config(tp); - - err = tg3_get_invariants(tp); - if (err) { - printf("Problem fetching invariants of chip, aborting.\n"); - goto err_out_iounmap; - } - - err = tg3_get_device_address(tp); - if (err) { - printf("Could not obtain valid ethernet address, aborting.\n"); - goto err_out_iounmap; - } - - DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) ); - - tg3_setup_dma(tp); - - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev, tp->pci_cfg_state); - - printf("Tigon3 [partno(%s) rev %hx PHY(%s)] (PCI%s:%s:%s)\n", - tp->board_part_number, - tp->pci_chip_rev_id, - tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""), - ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ? - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") : - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")), - ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit")); - - - err = tg3_setup_hw(tp); - if (err) { - goto err_out_disable; - } - tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; - - /* Wait for a reasonable time for the link to come up */ - tg3_poll_link(tp); - for(i = 0; !tp->carrier_ok && (i < VALID_LINK_TIMEOUT*100); i++) { - mdelay(1); - tg3_poll_link(tp); - } - if (!tp->carrier_ok){ - printf("Valid link not established\n"); - goto err_out_disable; - } - - nic->nic_op = &tg3_operations; - return 1; - - err_out_iounmap: - iounmap((void *)tp->regs); - return 0; - err_out_disable: - tg3_disable(nic); - return 0; -} - - -static struct pci_device_id tg3_nics[] = { -PCI_ROM(0x14e4, 0x1644, "tg3-5700", "Broadcom Tigon 3 5700", 0), -PCI_ROM(0x14e4, 0x1645, "tg3-5701", "Broadcom Tigon 3 5701", 0), -PCI_ROM(0x14e4, 0x1646, "tg3-5702", "Broadcom Tigon 3 5702", 0), -PCI_ROM(0x14e4, 0x1647, "tg3-5703", "Broadcom Tigon 3 5703", 0), -PCI_ROM(0x14e4, 0x1648, "tg3-5704", "Broadcom Tigon 3 5704", 0), -PCI_ROM(0x14e4, 0x164d, "tg3-5702FE", "Broadcom Tigon 3 5702FE", 0), -PCI_ROM(0x14e4, 0x1653, "tg3-5705", "Broadcom Tigon 3 5705", 0), -PCI_ROM(0x14e4, 0x1654, "tg3-5705_2", "Broadcom Tigon 3 5705_2", 0), -PCI_ROM(0x14e4, 0x1659, "tg3-5721", "Broadcom Tigon 3 5721", 0), -PCI_ROM(0x14e4, 0x165d, "tg3-5705M", "Broadcom Tigon 3 5705M", 0), -PCI_ROM(0x14e4, 0x165e, "tg3-5705M_2", "Broadcom Tigon 3 5705M_2", 0), -PCI_ROM(0x14e4, 0x1677, "tg3-5751", "Broadcom Tigon 3 5751", 0), -PCI_ROM(0x14e4, 0x167a, "tg3-5754", "Broadcom Tigon 3 5754", 0), -PCI_ROM(0x14e4, 0x1693, "tg3-5787", "Broadcom Tigon 3 5787", 0), -PCI_ROM(0x14e4, 0x1696, "tg3-5782", "Broadcom Tigon 3 5782", 0), -PCI_ROM(0x14e4, 0x169a, "tg3-5786", "Broadcom Tigon 3 5786", 0), -PCI_ROM(0x14e4, 0x169c, "tg3-5788", "Broadcom Tigon 3 5788", 0), -PCI_ROM(0x14e4, 0x169d, "tg3-5789", "Broadcom Tigon 3 5789", 0), -PCI_ROM(0x14e4, 0x16a6, "tg3-5702X", "Broadcom Tigon 3 5702X", 0), -PCI_ROM(0x14e4, 0x16a7, "tg3-5703X", "Broadcom Tigon 3 5703X", 0), -PCI_ROM(0x14e4, 0x16a8, "tg3-5704S", "Broadcom Tigon 3 5704S", 0), -PCI_ROM(0x14e4, 0x16c6, "tg3-5702A3", "Broadcom Tigon 3 5702A3", 0), -PCI_ROM(0x14e4, 0x16c7, "tg3-5703A3", "Broadcom Tigon 3 5703A3", 0), -PCI_ROM(0x14e4, 0x170d, "tg3-5901", "Broadcom Tigon 3 5901", 0), -PCI_ROM(0x14e4, 0x170e, "tg3-5901_2", "Broadcom Tigon 3 5901_2", 0), -PCI_ROM(0x1148, 0x4400, "tg3-9DXX", "Syskonnect 9DXX", 0), -PCI_ROM(0x1148, 0x4500, "tg3-9MXX", "Syskonnect 9MXX", 0), -PCI_ROM(0x173b, 0x03e8, "tg3-ac1000", "Altima AC1000", 0), -PCI_ROM(0x173b, 0x03e9, "tg3-ac1001", "Altima AC1001", 0), -PCI_ROM(0x173b, 0x03ea, "tg3-ac9100", "Altima AC9100", 0), -PCI_ROM(0x173b, 0x03eb, "tg3-ac1003", "Altima AC1003", 0), -PCI_ROM(0x0e11, 0x00ca, "tg3-hp", "HP Tigon 3", 0), -}; - -PCI_DRIVER ( tg3_driver, tg3_nics, PCI_NO_CLASS ); - -DRIVER ( "TG3", nic_driver, pci_driver, tg3_driver, - tg3_probe, tg3_disable ); - -/* - * Local variables: - * c-basic-offset: 8 - * c-indent-level: 8 - * tab-width: 8 - * End: - */ diff --git a/roms/ipxe/src/drivers/net/tg3.h b/roms/ipxe/src/drivers/net/tg3.h deleted file mode 100644 index deeb0adde..000000000 --- a/roms/ipxe/src/drivers/net/tg3.h +++ /dev/null @@ -1,2121 +0,0 @@ -/* $Id$ - * tg3.h: Definitions for Broadcom Tigon3 ethernet driver. - * - * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) - * Copyright (C) 2001 Jeff Garzik (jgarzik@mandrakesoft.com) - */ - -FILE_LICENCE ( GPL2_ONLY ); - -#ifndef _T3_H -#define _T3_H - -#include "stdint.h" - -typedef unsigned long dma_addr_t; - -/* 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. - */ - -/* The forced speed, 10Mb, 100Mb, gigabit. */ -#define SPEED_10 0 -#define SPEED_100 1 -#define SPEED_1000 2 -#define SPEED_INVALID 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 */ - -/* From tg3.h */ - -#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 RX_COPY_THRESHOLD 256 - -#define RX_STD_MAX_SIZE 1536 -#define RX_STD_MAX_SIZE_5705 512 -#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */ - -/* 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_COMMAND 0x00000004 -#define TG3PCI_STATUS 0x00000006 -#define TG3PCI_CCREVID 0x00000008 -#define TG3PCI_CACHELINESZ 0x0000000c -#define TG3PCI_LATTIMER 0x0000000d -#define TG3PCI_HEADERTYPE 0x0000000e -#define TG3PCI_BIST 0x0000000f -#define TG3PCI_BASE0_LOW 0x00000010 -#define TG3PCI_BASE0_HIGH 0x00000014 -/* 0x18 --> 0x2c unused */ -#define TG3PCI_SUBSYSVENID 0x0000002c -#define TG3PCI_SUBSYSID 0x0000002e -#define TG3PCI_ROMADDR 0x00000030 -#define TG3PCI_CAPLIST 0x00000034 -/* 0x35 --> 0x3c unused */ -#define TG3PCI_IRQ_LINE 0x0000003c -#define TG3PCI_IRQ_PIN 0x0000003d -#define TG3PCI_MIN_GNT 0x0000003e -#define TG3PCI_MAX_LAT 0x0000003f -#define TG3PCI_X_CAPS 0x00000040 -#define PCIX_CAPS_RELAXED_ORDERING 0x00020000 -#define PCIX_CAPS_SPLIT_MASK 0x00700000 -#define PCIX_CAPS_SPLIT_SHIFT 20 -#define PCIX_CAPS_BURST_MASK 0x000c0000 -#define PCIX_CAPS_BURST_SHIFT 18 -#define PCIX_CAPS_MAX_BURST_CPIOB 2 -#define TG3PCI_PM_CAP_PTR 0x00000041 -#define TG3PCI_X_COMMAND 0x00000042 -#define TG3PCI_X_STATUS 0x00000044 -#define TG3PCI_PM_CAP_ID 0x00000048 -#define TG3PCI_VPD_CAP_PTR 0x00000049 -#define TG3PCI_PM_CAPS 0x0000004a -#define TG3PCI_PM_CTRL_STAT 0x0000004c -#define TG3PCI_BR_SUPP_EXT 0x0000004e -#define TG3PCI_PM_DATA 0x0000004f -#define TG3PCI_VPD_CAP_ID 0x00000050 -#define TG3PCI_MSI_CAP_PTR 0x00000051 -#define TG3PCI_VPD_ADDR_FLAG 0x00000052 -#define VPD_ADDR_FLAG_WRITE 0x00008000 -#define TG3PCI_VPD_DATA 0x00000054 -#define TG3PCI_MSI_CAP_ID 0x00000058 -#define TG3PCI_NXT_CAP_PTR 0x00000059 -#define TG3PCI_MSI_CTRL 0x0000005a -#define TG3PCI_MSI_ADDR_LOW 0x0000005c -#define TG3PCI_MSI_ADDR_HIGH 0x00000060 -#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_5705_A0 0x3000 -#define CHIPREV_ID_5705_A1 0x3001 -#define CHIPREV_ID_5705_A2 0x3002 -#define CHIPREV_ID_5705_A3 0x3003 -#define CHIPREV_ID_5721 0x4101 -#define CHIPREV_ID_5750_A0 0x4000 -#define CHIPREV_ID_5750_A1 0x4001 -#define CHIPREV_ID_5750_A3 0x4003 -#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_5787 0x0b -#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 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_MIN_DMA 0x000000ff -#define DMA_RWCTRL_MIN_DMA_SHIFT 0 -#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_32 0x00000200 -#define DMA_RWCTRL_READ_BNDRY_64 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_32 0x00001000 -#define DMA_RWCTRL_WRITE_BNDRY_64 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 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 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_MODE_CTRL 0x00000088 -#define TG3PCI_MISC_CFG 0x0000008c -#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 */ -#define TG3PCI_SND_PROD_IDX 0x000000a8 /* 64-bit */ -/* 0xb0 --> 0x100 unused */ - -/* 0x100 --> 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 MAILBOX_RCV_JUMBO_PROD_IDX 0x00000270 /* 64-bit */ -#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_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_MAC_MODE 0x00000000 -#define LED_CTRL_PHY_MODE_1 0x00000800 -#define LED_CTRL_PHY_MODE_2 0x00001000 -#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_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_CORE_CLK_62MHZ 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 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 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 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_STAT 0x00000594 -/* 0x598 --> 0x600 unused */ -#define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */ -#define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */ -/* 0x624 --> 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 -/* 0xc14 --> 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 -/* 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_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_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_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 --> 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 --> 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_STATUS 0x00003c04 -#define HOSTCC_STATUS_ERROR_ATTN 0x00000004 -#define HOSTCC_RXCOL_TICKS 0x00003c08 -#define LOW_RXCOL_TICKS 0x00000032 -#define DEFAULT_RXCOL_TICKS 0x00000048 -#define HIGH_RXCOL_TICKS 0x00000096 -#define HOSTCC_TXCOL_TICKS 0x00003c0c -#define LOW_TXCOL_TICKS 0x00000096 -#define DEFAULT_TXCOL_TICKS 0x0000012c -#define HIGH_TXCOL_TICKS 0x00000145 -#define HOSTCC_RXMAX_FRAMES 0x00003c10 -#define LOW_RXMAX_FRAMES 0x00000005 -#define DEFAULT_RXMAX_FRAMES 0x00000008 -#define HIGH_RXMAX_FRAMES 0x00000012 -#define HOSTCC_TXMAX_FRAMES 0x00003c14 -#define LOW_TXMAX_FRAMES 0x00000035 -#define DEFAULT_TXMAX_FRAMES 0x0000004b -#define HIGH_TXMAX_FRAMES 0x00000052 -#define HOSTCC_RXCOAL_TICK_INT 0x00003c18 -#define DEFAULT_RXCOAL_TICK_INT 0x00000019 -#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c -#define DEFAULT_TXCOAL_TICK_INT 0x00000019 -#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 -#define DEFAULT_RXCOAL_MAXF_INT 0x00000005 -#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 -#define DEFAULT_TXCOAL_MAXF_INT 0x00000005 -#define HOSTCC_STAT_COAL_TICKS 0x00003c28 -#define DEFAULT_STAT_COAL_TICKS 0x000f4240 -/* 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 -/* 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 -/* 0x3d00 --> 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_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 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_JUMBO 0x00000098 -#define BUFMGR_MB_HIGH_WATER 0x00004418 -#define DEFAULT_MB_HIGH_WATER 0x00000060 -#define DEFAULT_MB_HIGH_WATER_5705 0x00000060 -#define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c -#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_SPLIT_RESET 0x00001000 -#define RDMAC_MODE_FIFO_SIZE_128 0x00020000 -#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 -#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 --> 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_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 TX_CPU_BASE 0x00005400 - -/* Mailboxes */ -#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 -#define FTQ_RESET_DMA_READ_QUEUE (1 << 1) -#define FTQ_RESET_DMA_HIGH_PRI_READ (1 << 2) -#define FTQ_RESET_SEND_BD_COMPLETION (1 << 4) -#define FTQ_RESET_DMA_WRITE (1 << 6) -#define FTQ_RESET_DMA_HIGH_PRI_WRITE (1 << 7) -#define FTQ_RESET_SEND_DATA_COMPLETION (1 << 9) -#define FTQ_RESET_HOST_COALESCING (1 << 10) -#define FTQ_RESET_MAC_TX (1 << 11) -#define FTQ_RESET_RX_BD_COMPLETE (1 << 13) -#define FTQ_RESET_RX_LIST_PLCMT (1 << 14) -#define FTQ_RESET_RX_DATA_COMPLETION (1 << 16) -/* 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_STATUS 0x00006004 -#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_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_HOST_STACKUP 0x00010000 -#define GRC_MODE_HOST_SENDBDS 0x00020000 -#define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 -#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_MCAST_FRM_ENABLE 0x40000000 -#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_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_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_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 --> 0x6c00 unused */ - -/* 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_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_BIT_BANG 0x00000008 -#define NVRAM_CFG1_COMPAT_BYPASS 0x80000000 -#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_BUFFERED_PAGE_SIZE 264 -#define NVRAM_BUFFERED_PAGE_POS 9 -/* 0x7024 --> 0x7400 unused */ - -/* 0x7400 --> 0x8000 unused */ - -/* 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_UNKNOWN 0x00000000 -#define NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD 0x00000004 -#define NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN 0x00000004 -#define NIC_SRAM_DATA_CFG_LED_LINK_SPD 0x00000008 -#define NIC_SRAM_DATA_CFG_LED_OUTPUT 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_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 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_UNLOAD 0x00000002 -#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_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 - -/* Currently this is fixed. */ -#define PHY_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_EXT_CTRL 0x10 /* Extended control register */ -#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002 -#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_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ - -#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ - -#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ - -#define MII_TG3_AUX_STAT 0x19 /* auxilliary 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_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 - - -/* 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. - * - * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags. - * - * 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 { - uint32_t addr_hi; - uint32_t addr_lo; - - uint32_t 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_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 - - uint32_t 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 { - uint32_t addr_hi; - uint32_t addr_lo; - - uint32_t idx_len; -#define RXD_IDX_MASK 0xffff0000 -#define RXD_IDX_SHIFT 16 -#define RXD_LEN_MASK 0x0000ffff -#define RXD_LEN_SHIFT 0 - - uint32_t 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 - - uint32_t ip_tcp_csum; -#define RXD_IPCSUM_MASK 0xffff0000 -#define RXD_IPCSUM_SHIFT 16 -#define RXD_TCPCSUM_MASK 0x0000ffff -#define RXD_TCPCSUM_SHIFT 0 - - uint32_t 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 - - uint32_t reserved; - uint32_t 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 { - uint32_t addr_hi; - uint32_t addr_lo; - } addrlist[3]; - uint32_t len2_len1; - uint32_t 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 { - uint32_t addr_hi; - uint32_t addr_lo; - uint32_t nic_mbuf; - /* XXX FIX THIS */ -#if __BYTE_ORDER == __BIG_ENDIAN - uint16_t cqid_sqid; - uint16_t len; -#else - uint16_t len; - uint16_t cqid_sqid; -#endif - uint32_t flags; - uint32_t __cookie1; - uint32_t __cookie2; - uint32_t __cookie3; -}; - -#define TG3_HW_STATUS_SIZE 0x50 -struct tg3_hw_status { - uint32_t status; -#define SD_STATUS_UPDATED 0x00000001 -#define SD_STATUS_LINK_CHG 0x00000002 -#define SD_STATUS_ERROR 0x00000004 - - uint32_t status_tag; - -#if __BYTE_ORDER == __BIG_ENDIAN - uint16_t rx_consumer; - uint16_t rx_jumbo_consumer; -#else - uint16_t rx_jumbo_consumer; - uint16_t rx_consumer; -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN - uint16_t reserved; - uint16_t rx_mini_consumer; -#else - uint16_t rx_mini_consumer; - uint16_t reserved; -#endif - struct { -#if __BYTE_ORDER == __BIG_ENDIAN - uint16_t tx_consumer; - uint16_t rx_producer; -#else - uint16_t rx_producer; - uint16_t tx_consumer; -#endif - } idx[16]; -}; - -typedef struct { - uint32_t high, low; -} tg3_stat64_t; - -struct tg3_hw_stats { - uint8_t __reserved0[0x400-0x300]; - - /* Statistics maintained by Receive MAC. */ - tg3_stat64_t rx_octets; - uint64_t __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; - - uint64_t __unused0[37]; - - /* Statistics maintained by Transmit MAC. */ - tg3_stat64_t tx_octets; - uint64_t __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; - uint64_t __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; - - uint64_t __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; - - uint64_t __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; - - uint8_t __reserved4[0xb00-0x9c0]; -}; - -enum phy_led_mode { - led_mode_auto, - led_mode_three_link, - led_mode_link10 -}; - -#if 0 -/* '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 sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(mapping) -}; - -struct tx_ring_info { - struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(mapping) - uint32_t prev_vlan_tag; -}; -#endif - -struct tg3_config_info { - uint32_t flags; -}; - -struct tg3_link_config { - /* Describes what we're trying to get. */ - uint32_t advertising; -#if 0 - uint16_t speed; - uint8_t duplex; - uint8_t autoneg; -#define SPEED_INVALID 0xffff -#define DUPLEX_INVALID 0xff -#define AUTONEG_INVALID 0xff -#endif - - /* Describes what we actually have. */ - uint8_t active_speed; - uint8_t active_duplex; - - /* When we go in and out of low power mode we need - * to swap with this state. - */ -#if 0 - int phy_is_low_power; - uint16_t orig_speed; - uint8_t orig_duplex; - uint8_t orig_autoneg; -#endif -}; - -struct tg3_bufmgr_config { - uint32_t mbuf_read_dma_low_water; - uint32_t mbuf_mac_rx_low_water; - uint32_t mbuf_high_water; - - uint32_t mbuf_read_dma_low_water_jumbo; - uint32_t mbuf_mac_rx_low_water_jumbo; - uint32_t mbuf_high_water_jumbo; - - uint32_t dma_low_water; - uint32_t dma_high_water; -}; - -struct tg3 { -#if 0 - /* SMP locking strategy: - * - * lock: Held during all operations except TX packet - * processing. - * - * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx - * - * If you want to shut up all asynchronous processing you must - * acquire both locks, 'lock' taken before 'tx_lock'. IRQs must - * be disabled to take 'lock' but only softirq disabling is - * necessary for acquisition of 'tx_lock'. - */ - spinlock_t lock; - spinlock_t tx_lock; -#endif - - uint32_t tx_prod; -#if 0 - uint32_t tx_cons; -#endif - uint32_t rx_rcb_ptr; - uint32_t rx_std_ptr; -#if 0 - uint32_t rx_jumbo_ptr; - spinlock_t indirect_lock; - - struct net_device_stats net_stats; - struct net_device_stats net_stats_prev; -#endif - unsigned long phy_crc_errors; - -#if 0 - uint32_t rx_offset; -#endif - uint32_t tg3_flags; -#if 0 -#define TG3_FLAG_HOST_TXDS 0x00000001 -#endif -#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 -#define TG3_FLAG_RX_CHECKSUMS 0x00000004 -#define TG3_FLAG_USE_LINKCHG_REG 0x00000008 -#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010 -#define TG3_FLAG_ENABLE_ASF 0x00000020 -#define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040 -#define TG3_FLAG_POLL_SERDES 0x00000080 -#define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 -#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 -#define TG3_FLAG_WOL_SPEED_100MB 0x00000400 -#define TG3_FLAG_WOL_ENABLE 0x00000800 -#define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000 -#define TG3_FLAG_NVRAM 0x00002000 -#define TG3_FLAG_NVRAM_BUFFERED 0x00004000 -#define TG3_FLAG_RX_PAUSE 0x00008000 -#define TG3_FLAG_TX_PAUSE 0x00010000 -#define TG3_FLAG_PCIX_MODE 0x00020000 -#define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 -#define TG3_FLAG_PCI_32BIT 0x00080000 -#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 -#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 -#define TG3_FLAG_SERDES_WOL_CAP 0x00400000 -#define TG3_FLAG_JUMBO_ENABLE 0x00800000 -#define TG3_FLAG_10_100_ONLY 0x01000000 -#define TG3_FLAG_PAUSE_AUTONEG 0x02000000 -#define TG3_FLAG_PAUSE_RX 0x04000000 -#define TG3_FLAG_PAUSE_TX 0x08000000 -#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 -#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 -#define TG3_FLAG_SPLIT_MODE 0x40000000 -#define TG3_FLAG_INIT_COMPLETE 0x80000000 - - uint32_t tg3_flags2; -#define TG3_FLG2_RESTART_TIMER 0x00000001 -#define TG3_FLG2_SUN_5704 0x00000002 -#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 -#define TG3_FLG2_IS_5788 0x00000008 -#define TG3_FLG2_MAX_RXPEND_64 0x00000010 -#define TG3_FLG2_TSO_CAPABLE 0x00000020 - // Alf: Hope I'm not breaking anything here ! -#define TG3_FLG2_PCI_EXPRESS 0x00000040 - - - - uint32_t split_mode_max_reqs; -#define SPLIT_MODE_5704_MAX_REQ 3 - -#if 0 - struct timer_list timer; - uint16_t timer_counter; - uint16_t timer_multiplier; - uint32_t timer_offset; - uint16_t asf_counter; - uint16_t asf_multiplier; -#endif - - struct tg3_link_config link_config; - struct tg3_bufmgr_config bufmgr_config; - -#if 0 - uint32_t rx_pending; - uint32_t rx_jumbo_pending; - uint32_t tx_pending; -#endif - - /* cache h/w values, often passed straight to h/w */ - uint32_t rx_mode; - uint32_t tx_mode; - uint32_t mac_mode; - uint32_t mi_mode; - uint32_t misc_host_ctrl; - uint32_t grc_mode; - uint32_t grc_local_ctrl; - uint32_t dma_rwctrl; -#if 0 - uint32_t coalesce_mode; -#endif - - /* PCI block */ - uint16_t pci_chip_rev_id; -#if 0 - uint8_t pci_cacheline_sz; - uint8_t pci_lat_timer; - uint8_t pci_hdr_type; - uint8_t pci_bist; -#endif - uint32_t pci_cfg_state[64 / sizeof(uint32_t)]; - - int pm_cap; - - /* PHY info */ - uint32_t phy_id; -#define PHY_ID_MASK 0xfffffff0 -#define PHY_ID_BCM5400 0x60008040 -#define PHY_ID_BCM5401 0x60008050 -#define PHY_ID_BCM5411 0x60008070 -#define PHY_ID_BCM5701 0x60008110 -#define PHY_ID_BCM5703 0x60008160 -#define PHY_ID_BCM5704 0x60008190 -#define PHY_ID_BCM5705 0x600081a0 -#define PHY_ID_BCM5750 0x60008180 -#define PHY_ID_BCM5787 0xbc050ce0 -#define PHY_ID_BCM8002 0x60010140 -#define PHY_ID_BCM5751 0x00206180 -#define PHY_ID_SERDES 0xfeedbee0 -#define PHY_ID_INVALID 0xffffffff -#define PHY_ID_REV_MASK 0x0000000f -#define PHY_REV_BCM5401_B0 0x1 -#define PHY_REV_BCM5401_B2 0x3 -#define PHY_REV_BCM5401_C0 0x6 -#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ - - enum phy_led_mode led_mode; - - char board_part_number[24]; - uint32_t nic_sram_data_cfg; - uint32_t pci_clock_ctrl; -#if 0 - struct pci_device *pdev_peer; -#endif - - /* This macro assumes the passed PHY ID is already masked - * with PHY_ID_MASK. - */ -#define KNOWN_PHY_ID(X) \ - ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \ - (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ - (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ - (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ - (X) == PHY_ID_BCM5751 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) - - unsigned long regs; - struct pci_device *pdev; - struct nic *nic; -#if 0 - struct net_device *dev; -#endif -#if TG3_VLAN_TAG_USED - struct vlan_group *vlgrp; -#endif - - struct tg3_rx_buffer_desc *rx_std; -#if 0 - struct ring_info *rx_std_buffers; - dma_addr_t rx_std_mapping; - struct tg3_rx_buffer_desc *rx_jumbo; - struct ring_info *rx_jumbo_buffers; - dma_addr_t rx_jumbo_mapping; -#endif - - struct tg3_rx_buffer_desc *rx_rcb; -#if 0 - dma_addr_t rx_rcb_mapping; -#endif - - /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */ - struct tg3_tx_buffer_desc *tx_ring; -#if 0 - struct tx_ring_info *tx_buffers; - dma_addr_t tx_desc_mapping; -#endif - - struct tg3_hw_status *hw_status; -#if 0 - dma_addr_t status_mapping; -#endif -#if 0 - uint32_t msg_enable; -#endif - - struct tg3_hw_stats *hw_stats; -#if 0 - dma_addr_t stats_mapping; -#endif - - int carrier_ok; - uint16_t subsystem_vendor; - uint16_t subsystem_device; -}; - -#endif /* !(_T3_H) */ diff --git a/roms/ipxe/src/drivers/net/tg3/tg3.c b/roms/ipxe/src/drivers/net/tg3/tg3.c new file mode 100644 index 000000000..32ca1609c --- /dev/null +++ b/roms/ipxe/src/drivers/net/tg3/tg3.c @@ -0,0 +1,945 @@ + +FILE_LICENCE ( GPL2_ONLY ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + + err = tg3_init_hw(tp, 1); + if (err != 0) + DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err)); + else + tg3_refill_prod_ring(tp); + + 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; + + 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); + + tp->tx_prod = entry; + + mb(); + + 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++; + } + + if ((u32)idx != tpr->rx_std_prod_idx) { + 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--; + } + + if (tp->rx_rcb_ptr != sw_idx) { + tw32_rx_mbox(tp->consmbox, sw_idx); + 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, 0x1682, "14e4-1682", "14e4-1682", 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/roms/ipxe/src/drivers/net/tg3/tg3.h b/roms/ipxe/src/drivers/net/tg3/tg3.h new file mode 100644 index 000000000..e84eed879 --- /dev/null +++ b/roms/ipxe/src/drivers/net/tg3/tg3.h @@ -0,0 +1,3425 @@ +/* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $ + * 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 */ +/* */ + +/* 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) +/* */ + +/* 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 */ +/* */ + +/* mii.h */ +#define FLOW_CTRL_TX 0x01 +#define FLOW_CTRL_RX 0x02 +/* */ + +/* 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_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 +/* */ + +#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 RX_STD_MAX_SIZE 1536 +#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_57762 0x1682 +#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) + +#define TG3_DMA_ALIGNMENT 16 + +#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/roms/ipxe/src/drivers/net/tg3/tg3_hw.c b/roms/ipxe/src/drivers/net/tg3/tg3_hw.c new file mode 100644 index 000000000..9ae007c2f --- /dev/null +++ b/roms/ipxe/src/drivers/net/tg3/tg3_hw.c @@ -0,0 +1,2653 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_57762 || + 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; + + if (tg3_flag(tp, 57765_PLUS)) + val |= (RX_STD_MAX_SIZE << 2); + + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val); + + tpr->rx_std_prod_idx = 0; + + /* 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); + + __tg3_set_mac_addr(tp,0); + +#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/roms/ipxe/src/drivers/net/tg3/tg3_phy.c b/roms/ipxe/src/drivers/net/tg3/tg3_phy.c new file mode 100644 index 000000000..65dea7e66 --- /dev/null +++ b/roms/ipxe/src/drivers/net/tg3/tg3_phy.c @@ -0,0 +1,1603 @@ + +#include +#include +#include +#include +#include +#include + +#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, ®32)) + 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, ®32)) { + 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__); + + if (tp->hw_status->status & SD_STATUS_LINK_CHG) { + DBGC(tp->dev,"link_changed\n"); + tp->hw_status->status &= ~SD_STATUS_LINK_CHG; + 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, ®)) + val = reg << 16; + if (!tg3_readphy(tp, MII_BMSR, ®)) + val |= (reg & 0xffff); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); + + val = 0; + if (!tg3_readphy(tp, MII_ADVERTISE, ®)) + val = reg << 16; + if (!tg3_readphy(tp, MII_LPA, ®)) + 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, ®)) + val = reg << 16; + if (!tg3_readphy(tp, MII_STAT1000, ®)) + val |= (reg & 0xffff); + } + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); + + if (!tg3_readphy(tp, MII_PHYADDR, ®)) + 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, + ¤t_speed, + ¤t_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); + + /* Enabled attention when the link has changed state. */ + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + 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/roms/ipxe/src/drivers/net/tlan.c b/roms/ipxe/src/drivers/net/tlan.c index b1a09d187..74398df42 100644 --- a/roms/ipxe/src/drivers/net/tlan.c +++ b/roms/ipxe/src/drivers/net/tlan.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * lan.c: Linux ThunderLan Driver: @@ -201,7 +202,7 @@ 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 int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned rx_buf_sz; /* Based on mtu + Slack */ struct TLanList *txList; u32 txHead; @@ -1084,11 +1085,11 @@ These routines are based on the information in Chap. 2 of the * for this device. * phy The address of the PHY to be queried. * reg The register whose contents are to be -* retreived. +* retrieved. * val A pointer to a variable to store the * retrieved value. * -* This function uses the TLAN's MII bus to retreive the contents +* This function uses the TLAN's MII bus to retrieve 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. diff --git a/roms/ipxe/src/drivers/net/tlan.h b/roms/ipxe/src/drivers/net/tlan.h index 31b3c8f46..b787532be 100644 --- a/roms/ipxe/src/drivers/net/tlan.h +++ b/roms/ipxe/src/drivers/net/tlan.h @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code (almost all) based on: * tlan.c: Linux ThunderLan Driver: diff --git a/roms/ipxe/src/drivers/net/via-rhine.c b/roms/ipxe/src/drivers/net/via-rhine.c index 439a4a5df..f3bb4e014 100644 --- a/roms/ipxe/src/drivers/net/via-rhine.c +++ b/roms/ipxe/src/drivers/net/via-rhine.c @@ -288,7 +288,7 @@ static const char *version = "rhine.c v1.0.2 2004-10-29\n"; */ #define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */ -#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_EMBP 0x40 /* eeprom embedded programming */ #define EECSR_AUTOLD 0x20 /* eeprom content reload */ #define EECSR_DPM 0x10 /* eeprom direct programming */ #define EECSR_CS 0x08 /* eeprom CS pin */ @@ -322,7 +322,7 @@ static const char *version = "rhine.c v1.0.2 2004-10-29\n"; * Bits in the CFGA register */ -#define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */ +#define CFGA_EELOAD 0x80 /* enable eeprom embedded and direct programming */ #define CFGA_JUMPER 0x40 #define CFGA_MTGPIO 0x08 #define CFGA_T10EN 0x02 @@ -693,7 +693,7 @@ 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 int rhine_poll (struct nic *nic, int retrieve); 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); @@ -1286,7 +1286,7 @@ rhine_reset (struct nic *nic) #define IOSYNC do { inb(nic->ioaddr + StationAddr); } while (0) static int -rhine_poll (struct nic *nic, int retreive) +rhine_poll (struct nic *nic, int retrieve) { struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int rxstatus, good = 0;; @@ -1295,7 +1295,7 @@ rhine_poll (struct nic *nic, int retreive) { unsigned int intr_status; /* There is a packet ready */ - if(!retreive) + if(!retrieve) return 1; intr_status = inw(nic->ioaddr + IntrStatus); diff --git a/roms/ipxe/src/drivers/net/via-velocity.c b/roms/ipxe/src/drivers/net/via-velocity.c index fa90f9b3f..9ba0b093d 100644 --- a/roms/ipxe/src/drivers/net/via-velocity.c +++ b/roms/ipxe/src/drivers/net/via-velocity.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * This driver is based on: * via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver @@ -124,7 +125,7 @@ VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging"); /* 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, + In some environment, 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"); diff --git a/roms/ipxe/src/drivers/net/via-velocity.h b/roms/ipxe/src/drivers/net/via-velocity.h index b657224d2..753fe445f 100644 --- a/roms/ipxe/src/drivers/net/via-velocity.h +++ b/roms/ipxe/src/drivers/net/via-velocity.h @@ -878,7 +878,7 @@ enum { * Bits in the EECSR register */ -#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_EMBP 0x40 /* eeprom embedded programming */ #define EECSR_RELOAD 0x20 /* eeprom content reload */ #define EECSR_DPM 0x10 /* eeprom direct programming */ #define EECSR_ECS 0x08 /* eeprom CS pin */ diff --git a/roms/ipxe/src/drivers/net/virtio-net.c b/roms/ipxe/src/drivers/net/virtio-net.c index 54e962d1f..d5fd81979 100644 --- a/roms/ipxe/src/drivers/net/virtio-net.c +++ b/roms/ipxe/src/drivers/net/virtio-net.c @@ -69,7 +69,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * Linux source. */ -/* Virtqueue indicies */ +/* Virtqueue indices */ enum { RX_INDEX = 0, TX_INDEX, diff --git a/roms/ipxe/src/drivers/net/vmxnet3.c b/roms/ipxe/src/drivers/net/vmxnet3.c new file mode 100644 index 000000000..9401c110e --- /dev/null +++ b/roms/ipxe/src/drivers/net/vmxnet3.c @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2011 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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/roms/ipxe/src/drivers/net/vmxnet3.h b/roms/ipxe/src/drivers/net/vmxnet3.h new file mode 100644 index 000000000..db313d4b8 --- /dev/null +++ b/roms/ipxe/src/drivers/net/vmxnet3.h @@ -0,0 +1,498 @@ +#ifndef _VMXNET3_H +#define _VMXNET3_H + +/* + * Copyright (C) 2008 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** + * @file + * + * VMware vmxnet3 virtual NIC driver + * + */ + +#include + +/** 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/roms/ipxe/src/drivers/net/vxge/vxge_main.c b/roms/ipxe/src/drivers/net/vxge/vxge_main.c index b8533d311..130eab617 100644 --- a/roms/ipxe/src/drivers/net/vxge/vxge_main.c +++ b/roms/ipxe/src/drivers/net/vxge/vxge_main.c @@ -252,7 +252,7 @@ static void vxge_poll(struct net_device *ndev) /* * vxge_irq - enable or Disable interrupts * - * @netdev netdevice sturcture reference + * @netdev netdevice structure reference * @action requested interrupt action */ static void vxge_irq(struct net_device *netdev __unused, int action) diff --git a/roms/ipxe/src/drivers/net/w89c840.c b/roms/ipxe/src/drivers/net/w89c840.c index b3149550f..ce638ab99 100644 --- a/roms/ipxe/src/drivers/net/w89c840.c +++ b/roms/ipxe/src/drivers/net/w89c840.c @@ -26,7 +26,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/nvs/nvs.c b/roms/ipxe/src/drivers/nvs/nvs.c index a4a06ccff..ccb2145bd 100644 --- a/roms/ipxe/src/drivers/nvs/nvs.c +++ b/roms/ipxe/src/drivers/nvs/nvs.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/nvs/nvsvpd.c b/roms/ipxe/src/drivers/nvs/nvsvpd.c index a22ec825f..33148d5b9 100644 --- a/roms/ipxe/src/drivers/nvs/nvsvpd.c +++ b/roms/ipxe/src/drivers/nvs/nvsvpd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/nvs/spi.c b/roms/ipxe/src/drivers/nvs/spi.c index e12aeff66..84613b9dd 100644 --- a/roms/ipxe/src/drivers/nvs/spi.c +++ b/roms/ipxe/src/drivers/nvs/spi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/drivers/nvs/threewire.c b/roms/ipxe/src/drivers/nvs/threewire.c index 047091fd5..53f1ad8de 100644 --- a/roms/ipxe/src/drivers/nvs/threewire.c +++ b/roms/ipxe/src/drivers/nvs/threewire.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/autoboot_cmd.c b/roms/ipxe/src/hci/commands/autoboot_cmd.c index 0917f6fa1..f3886b1f6 100644 --- a/roms/ipxe/src/hci/commands/autoboot_cmd.c +++ b/roms/ipxe/src/hci/commands/autoboot_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/roms/ipxe/src/hci/commands/config_cmd.c b/roms/ipxe/src/hci/commands/config_cmd.c index e447d6af3..f1fb567c2 100644 --- a/roms/ipxe/src/hci/commands/config_cmd.c +++ b/roms/ipxe/src/hci/commands/config_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/roms/ipxe/src/hci/commands/dhcp_cmd.c b/roms/ipxe/src/hci/commands/dhcp_cmd.c index acf3cfdaa..279620c32 100644 --- a/roms/ipxe/src/hci/commands/dhcp_cmd.c +++ b/roms/ipxe/src/hci/commands/dhcp_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/digest_cmd.c b/roms/ipxe/src/hci/commands/digest_cmd.c index 6ca12eff1..3cf2f1026 100644 --- a/roms/ipxe/src/hci/commands/digest_cmd.c +++ b/roms/ipxe/src/hci/commands/digest_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -28,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -74,8 +76,8 @@ static int digest_exec ( int argc, char **argv, for ( i = optind ; i < argc ; i++ ) { - /* find image */ - if ( ( rc = parse_image ( argv[i], &image ) ) != 0 ) + /* Acquire image */ + if ( ( rc = imgacquire ( argv[i], &image ) ) != 0 ) continue; offset = 0; len = image->len; diff --git a/roms/ipxe/src/hci/commands/fcmgmt_cmd.c b/roms/ipxe/src/hci/commands/fcmgmt_cmd.c index a2b818ec3..b7e38040c 100644 --- a/roms/ipxe/src/hci/commands/fcmgmt_cmd.c +++ b/roms/ipxe/src/hci/commands/fcmgmt_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/gdbstub_cmd.c b/roms/ipxe/src/hci/commands/gdbstub_cmd.c index f35f0140b..33890aebc 100644 --- a/roms/ipxe/src/hci/commands/gdbstub_cmd.c +++ b/roms/ipxe/src/hci/commands/gdbstub_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/ifmgmt_cmd.c b/roms/ipxe/src/hci/commands/ifmgmt_cmd.c index 29691d4ef..3f3f6b51c 100644 --- a/roms/ipxe/src/hci/commands/ifmgmt_cmd.c +++ b/roms/ipxe/src/hci/commands/ifmgmt_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/image_cmd.c b/roms/ipxe/src/hci/commands/image_cmd.c index 1ff3ff49b..6f51a6ba2 100644 --- a/roms/ipxe/src/hci/commands/image_cmd.c +++ b/roms/ipxe/src/hci/commands/image_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -26,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -34,167 +36,258 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ -/** "imgfetch" options */ -struct imgfetch_options { +/** "img{single}" options */ +struct imgsingle_options { /** Image name */ const char *name; + /** Replace image */ + int replace; + /** Free image after execution */ + int autofree; }; -/** "imgfetch" option list */ -static struct option_descriptor imgfetch_opts[] = { +/** "img{single}" option list */ +static struct option_descriptor imgsingle_opts[] = { OPTION_DESC ( "name", 'n', required_argument, - struct imgfetch_options, name, parse_string ), + struct imgsingle_options, name, parse_string ), + OPTION_DESC ( "replace", 'r', no_argument, + struct imgsingle_options, replace, parse_flag ), + OPTION_DESC ( "autofree", 'a', no_argument, + struct imgsingle_options, autofree, parse_flag ), }; -/** "imgfetch" command descriptor */ -static struct command_descriptor imgfetch_cmd = - COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS, - "[--name ] [...]" ); +/** "img{single}" command descriptor */ +static struct command_descriptor imgsingle_cmd = + COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, + 1, MAX_ARGUMENTS, + "[--name ] [--autofree] " + " [...]" ); + +/** 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, + struct imgsingle_options *opts ); + /** Verb to describe action */ + const char *verb; +}; /** - * The "imgfetch" and friends command body + * The "img{single}" family of commands * * @v argc Argument count * @v argv Argument list - * @v cmd Command descriptor + * @v desc "img{single}" command descriptor * @v action_name Action name (for error messages) - * @v action Action to take upon a successful download + * @v action Action to take upon image * @ret rc Return status code */ -static int imgfetch_core_exec ( int argc, char **argv, - const char *action_name, - int ( * action ) ( struct image *image ) ) { - struct imgfetch_options opts; - char *uri_string; +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, &imgfetch_cmd, &opts ) ) != 0 ) + if ( ( rc = parse_options ( argc, argv, desc->cmd, &opts ) ) != 0 ) goto err_parse_options; - /* Parse URI string */ - uri_string = argv[optind]; + /* 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; + } + } + } - /* Parse command line */ - if ( argv[ optind + 1 ] != NULL ) { - cmdline = concat_args ( &argv[ optind + 1 ] ); - if ( ! cmdline ) { - rc = -ENOMEM; - goto err_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; } } - /* Fetch the image */ - if ( ( rc = imgdownload_string ( uri_string, opts.name, cmdline, - action ) ) != 0 ) { - printf ( "Could not %s %s: %s\n", - action_name, uri_string, strerror ( rc ) ); - goto err_imgdownload; + /* 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; + } } - /* Free command line */ - free ( cmdline ); + /* 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; + } + } - return 0; + /* Set the auto-unregister flag, if applicable */ + if ( opts.autofree ) + image->flags |= IMAGE_AUTO_UNREGISTER; - err_imgdownload: + /* Carry out command action, if applicable */ + if ( desc->action ) { + if ( ( rc = desc->action ( image, &opts ) ) != 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_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 ] [--autofree] [...]" ); + +/** "imgfetch" family command descriptor */ +struct imgsingle_descriptor imgfetch_desc = { + .cmd = &imgfetch_cmd, + .acquire = imgdownload_string, +}; + /** - * The "imgfetch"/"module" command + * 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 imgfetch_core_exec ( argc, argv, "fetch", - register_and_put_image ); + return imgsingle_exec ( argc, argv, &imgfetch_desc ); } /** - * The "kernel" command + * "imgselect" command action * - * @v argc Argument count - * @v argv Argument list + * @v image Image + * @v opts Options * @ret rc Return status code */ -static int kernel_exec ( int argc, char **argv ) { - - return imgfetch_core_exec ( argc, argv, "select", - register_and_select_image ); +static int imgselect ( struct image *image, + struct imgsingle_options *opts __unused ) { + return image_select ( image ); } +/** "imgselect" family command descriptor */ +struct imgsingle_descriptor imgselect_desc = { + .cmd = &imgsingle_cmd, + .acquire = imgacquire, + .action = imgselect, + .verb = "select", +}; + /** - * The "chain" command + * The "imgselect" command * * @v argc Argument count * @v argv Argument list * @ret rc Return status code */ -static int chain_exec ( int argc, char **argv) { - - return imgfetch_core_exec ( argc, argv, "boot", - register_and_boot_image ); +static int imgselect_exec ( int argc, char **argv ) { + return imgsingle_exec ( argc, argv, &imgselect_desc ); } -/** "imgselect" options */ -struct imgselect_options {}; - -/** "imgselect" option list */ -static struct option_descriptor imgselect_opts[] = {}; - -/** "imgselect" command descriptor */ -static struct command_descriptor imgselect_cmd = - COMMAND_DESC ( struct imgselect_options, imgselect_opts, 1, 1, - "" ); +/** "imgexec" command descriptor */ +static struct command_descriptor imgexec_cmd = + COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, + 0, MAX_ARGUMENTS, + "[--autofree] [--replace] " + "[ [...]]" ); /** - * The "imgselect" command + * "imgexec" command action * - * @v argc Argument count - * @v argv Argument list + * @v image Image + * @v opts Options * @ret rc Return status code */ -static int imgselect_exec ( int argc, char **argv ) { - struct imgselect_options opts; - struct image *image; +static int imgexec ( struct image *image, struct imgsingle_options *opts ) { int rc; - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &imgselect_cmd, &opts ) ) != 0 ) - return rc; + /* Perform replacement or execution as applicable */ + if ( opts->replace ) { - /* Parse image name */ - if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) - return rc; + /* Try to replace image */ + if ( ( rc = image_replace ( image ) ) != 0 ) + return rc; - /* Load image */ - if ( ( rc = imgselect ( image ) ) != 0 ) { - printf ( "Could not select %s: %s\n", - image->name, strerror ( rc ) ); - return rc; + /* Stop script and tail-recurse into replacement image */ + shell_stop ( SHELL_STOP_COMMAND_SEQUENCE ); + + } else { + + /* Try to execute image */ + if ( ( rc = image_exec ( image ) ) != 0 ) + return rc; } return 0; } -/** "imgargs" options */ -struct imgargs_options {}; +/** "imgexec" family command descriptor */ +struct imgsingle_descriptor imgexec_desc = { + .cmd = &imgexec_cmd, + .acquire = imgacquire, + .action = imgexec, + .verb = "boot", +}; -/** "imgargs" option list */ -static struct option_descriptor imgargs_opts[] = {}; +/** + * 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" command descriptor */ -static struct command_descriptor imgargs_cmd = - COMMAND_DESC ( struct imgargs_options, imgargs_opts, 1, MAX_ARGUMENTS, - " [...]" ); +/** "imgargs" family command descriptor */ +struct imgsingle_descriptor imgargs_desc = { + .cmd = &imgsingle_cmd, + .acquire = imgacquire, + .preaction = image_clear_cmdline, +}; /** * The "imgargs" command body @@ -204,105 +297,60 @@ static struct command_descriptor imgargs_cmd = * @ret rc Return status code */ static int imgargs_exec ( int argc, char **argv ) { - struct imgargs_options opts; - struct image *image; - char *cmdline = NULL; - int rc; - - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &imgargs_cmd, &opts ) ) != 0 ) - goto err_parse_options; - - /* Parse image name */ - if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) - goto err_parse_image; - - /* Parse command line */ - if ( argv[ optind + 1 ] != NULL ) { - cmdline = concat_args ( &argv[ optind + 1 ] ); - if ( ! cmdline ) { - rc = -ENOMEM; - goto err_cmdline; - } - } - - /* Set command line */ - if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) - goto err_set_cmdline; - - /* Free command line */ - free ( cmdline ); - - return 0; - - err_set_cmdline: - free ( cmdline ); - err_cmdline: - err_parse_image: - err_parse_options: - return rc; + return imgsingle_exec ( argc, argv, &imgargs_desc ); } -/** "imgexec" options */ -struct imgexec_options {}; +/** "img{multi}" options */ +struct imgmulti_options {}; -/** "imgexec" option list */ -static struct option_descriptor imgexec_opts[] = {}; +/** "img{multi}" option list */ +static struct option_descriptor imgmulti_opts[] = {}; -/** "imgexec" command descriptor */ -static struct command_descriptor imgexec_cmd = - COMMAND_DESC ( struct imgexec_options, imgexec_opts, 0, 1, - "[]" ); +/** "img{multi}" command descriptor */ +static struct command_descriptor imgmulti_cmd = + COMMAND_DESC ( struct imgmulti_options, imgmulti_opts, 0, MAX_ARGUMENTS, + "[...]" ); /** - * The "imgexec" command + * 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 imgexec_exec ( int argc, char **argv ) { - struct imgexec_options opts; +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, &imgexec_cmd, &opts ) ) != 0 ) + if ( ( rc = parse_options ( argc, argv, &imgmulti_cmd, &opts ) ) != 0 ) return rc; - /* Parse image name */ - if ( optind < argc ) { - if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) - return rc; - } else { - image = imgautoselect(); - if ( ! image ) { - rc = -ENOTTY; - printf ( "No image selected: %s\n", strerror ( rc ) ); - return rc; - } + /* If no images are explicitly specified, process all images */ + if ( optind == argc ) { + for_each_image_safe ( image, tmp ) + payload ( image ); + return 0; } - /* Execute image */ - if ( ( rc = imgexec ( image ) ) != 0 ) { - printf ( "Could not execute %s: %s\n", - image->name, strerror ( rc ) ); - return rc; + /* 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; } -/** "imgstat" options */ -struct imgstat_options {}; - -/** "imgstat" option list */ -static struct option_descriptor imgstat_opts[] = {}; - -/** "imgstat" command descriptor */ -static struct command_descriptor imgstat_cmd = - COMMAND_DESC ( struct imgstat_options, imgstat_opts, 0, 0, "" ); - /** * The "imgstat" command * @@ -311,33 +359,9 @@ static struct command_descriptor imgstat_cmd = * @ret rc Return status code */ static int imgstat_exec ( int argc, char **argv ) { - struct imgstat_options opts; - struct image *image; - int rc; - - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &imgstat_cmd, &opts ) ) != 0 ) - return rc; - - /* Show status of all images */ - for_each_image ( image ) { - imgstat ( image ); - } - - return 0; + return imgmulti_exec ( argc, argv, imgstat ); } -/** "imgfree" options */ -struct imgfree_options {}; - -/** "imgfree" option list */ -static struct option_descriptor imgfree_opts[] = {}; - -/** "imgfree" command descriptor */ -static struct command_descriptor imgfree_cmd = - COMMAND_DESC ( struct imgfree_options, imgfree_opts, 0, 1, - "[]" ); - /** * The "imgfree" command * @@ -346,28 +370,7 @@ static struct command_descriptor imgfree_cmd = * @ret rc Return status code */ static int imgfree_exec ( int argc, char **argv ) { - struct imgfree_options opts; - struct image *image; - struct image *tmp; - int rc; - - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &imgfree_cmd, &opts ) ) != 0 ) - return rc; - - if ( optind < argc ) { - /* Free specified image */ - if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) - return rc; - imgfree ( image ); - } else { - /* Free all images */ - list_for_each_entry_safe ( image, tmp, &images, list ) { - imgfree ( image ); - } - } - - return 0; + return imgmulti_exec ( argc, argv, unregister_image ); } /** Image management commands */ @@ -386,19 +389,19 @@ struct command image_commands[] __command = { }, { .name = "kernel", - .exec = kernel_exec, + .exec = imgselect_exec, /* synonym for "imgselect" */ }, { .name = "chain", - .exec = chain_exec, + .exec = imgexec_exec, /* synonym for "imgexec" */ }, { .name = "imgselect", .exec = imgselect_exec, }, { - .name = "imgload", /* synonym for "imgselect" */ - .exec = imgselect_exec, + .name = "imgload", + .exec = imgselect_exec, /* synonym for "imgselect" */ }, { .name = "imgargs", diff --git a/roms/ipxe/src/hci/commands/image_trust_cmd.c b/roms/ipxe/src/hci/commands/image_trust_cmd.c new file mode 100644 index 000000000..e7a2bf122 --- /dev/null +++ b/roms/ipxe/src/hci/commands/image_trust_cmd.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @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 ] [--keep] " + "" ); + +/** + * 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/roms/ipxe/src/hci/commands/iwmgmt_cmd.c b/roms/ipxe/src/hci/commands/iwmgmt_cmd.c index 00a8360db..d91ad1e34 100644 --- a/roms/ipxe/src/hci/commands/iwmgmt_cmd.c +++ b/roms/ipxe/src/hci/commands/iwmgmt_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/login_cmd.c b/roms/ipxe/src/hci/commands/login_cmd.c index 3286932d0..bc23e6ff5 100644 --- a/roms/ipxe/src/hci/commands/login_cmd.c +++ b/roms/ipxe/src/hci/commands/login_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/roms/ipxe/src/hci/commands/lotest_cmd.c b/roms/ipxe/src/hci/commands/lotest_cmd.c index 172be2d8c..92f08887a 100644 --- a/roms/ipxe/src/hci/commands/lotest_cmd.c +++ b/roms/ipxe/src/hci/commands/lotest_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/menu_cmd.c b/roms/ipxe/src/hci/commands/menu_cmd.c new file mode 100644 index 000000000..10966db27 --- /dev/null +++ b/roms/ipxe/src/hci/commands/menu_cmd.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +/** @file + * + * Menu commands + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 ] [--delete] []" ); + +/** + * 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, &setting_type_string, + 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/roms/ipxe/src/hci/commands/nslookup_cmd.c b/roms/ipxe/src/hci/commands/nslookup_cmd.c new file mode 100644 index 000000000..265afdc3d --- /dev/null +++ b/roms/ipxe/src/hci/commands/nslookup_cmd.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include <stdio.h> +#include <getopt.h> +#include <ipxe/command.h> +#include <ipxe/parseopt.h> +#include <usr/nslookup.h> + +/** @file + * + * nslookup command + * + */ + +/** "nslookup" options */ +struct nslookup_options {}; + +/** "nslookup" option list */ +static struct option_descriptor nslookup_opts[] = {}; + +/** "nslookup" command descriptor */ +static struct command_descriptor nslookup_cmd = + COMMAND_DESC ( struct nslookup_options, nslookup_opts, 2, 2, + "<setting> <name>" ); + +/** + * The "nslookup" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int nslookup_exec ( int argc, char **argv ) { + struct nslookup_options opts; + const char *name; + const char *setting_name; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &nslookup_cmd, &opts ) ) != 0 ) + return rc; + + /* Parse setting name */ + setting_name = argv[optind]; + + /* Parse name to be resolved */ + name = argv[ optind + 1 ]; + + /* Look up name */ + if ( ( rc = nslookup ( name, setting_name ) ) != 0 ) + return rc; + + return 0; +} + +/** The "nslookup" command */ +struct command nslookup_command __command = { + .name = "nslookup", + .exec = nslookup_exec, +}; diff --git a/roms/ipxe/src/hci/commands/nvo_cmd.c b/roms/ipxe/src/hci/commands/nvo_cmd.c index a7e0f4a03..f255bbf57 100644 --- a/roms/ipxe/src/hci/commands/nvo_cmd.c +++ b/roms/ipxe/src/hci/commands/nvo_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include <stdint.h> @@ -108,7 +109,8 @@ static struct command_descriptor clear_read_cmd = */ static int set_core_exec ( int argc, char **argv, struct command_descriptor *cmd, - int ( * get_value ) ( char **args, char **value ) ) { + int ( * get_value ) ( const char *name, + char **args, char **value ) ) { struct set_core_options opts; const char *name; char *value; @@ -122,11 +124,12 @@ static int set_core_exec ( int argc, char **argv, name = argv[optind]; /* Parse setting value */ - if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 ) + if ( ( rc = get_value ( name, &argv[ optind + 1 ], &value ) ) != 0 ) goto err_get_value; /* Determine total length of command line */ - if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) { + if ( ( rc = storef_named_setting ( name, &setting_type_string, + value ) ) != 0 ) { printf ( "Could not %s \"%s\": %s\n", argv[0], name, strerror ( rc ) ); goto err_store; @@ -145,11 +148,12 @@ static int set_core_exec ( int argc, char **argv, /** * Get setting value for "set" command * + * @v name Setting name * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int set_value ( char **args, char **value ) { +static int set_value ( const char *name __unused, char **args, char **value ) { *value = concat_args ( args ); if ( ! *value ) @@ -172,11 +176,13 @@ static int set_exec ( int argc, char **argv ) { /** * Get setting value for "clear" command * + * @v name Setting name * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int clear_value ( char **args __unused, char **value ) { +static int clear_value ( const char *name __unused, char **args __unused, + char **value ) { *value = NULL; return 0; @@ -196,16 +202,30 @@ static int clear_exec ( int argc, char **argv ) { /** * Get setting value for "read" command * + * @v name Setting name + * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int read_value ( char **args __unused, char **value ) { +static int read_value ( const char *name, char **args __unused, char **value ) { + char *existing; + int rc; - *value = readline ( NULL ); - if ( ! *value ) - return -ENOMEM; + /* Read existing value */ + if ( ( rc = fetchf_named_setting_copy ( name, &existing ) ) < 0 ) + goto err_existing; - return 0; + /* Read new value */ + if ( ( rc = readline_history ( NULL, existing, NULL, value ) ) != 0 ) + goto err_new; + + /* Success */ + rc = 0; + + err_new: + free ( existing ); + err_existing: + return rc; } /** diff --git a/roms/ipxe/src/hci/commands/route_cmd.c b/roms/ipxe/src/hci/commands/route_cmd.c index f839d53f4..3b51f06b0 100644 --- a/roms/ipxe/src/hci/commands/route_cmd.c +++ b/roms/ipxe/src/hci/commands/route_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/commands/sanboot_cmd.c b/roms/ipxe/src/hci/commands/sanboot_cmd.c index 198a7322d..14055a8c4 100644 --- a/roms/ipxe/src/hci/commands/sanboot_cmd.c +++ b/roms/ipxe/src/hci/commands/sanboot_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include <stdio.h> @@ -23,6 +24,7 @@ #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 ); @@ -34,47 +36,92 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** "sanboot" options */ -struct 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[] = {}; +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, 1, 1, - "<root-path>" ); + 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" command + * 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_exec ( int argc, char **argv ) { +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 = parse_options ( argc, argv, &sanboot_cmd, &opts ) ) != 0 ) + if ( ( rc = reparse_options ( argc, argv, cmd, &opts ) ) != 0 ) goto err_parse_options; - /* Parse root path */ - root_path = argv[optind]; - uri = parse_uri ( root_path ); - if ( ! uri ) { - rc = -ENOMEM; - goto err_parse_uri; + /* 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 ) ) != 0 ) { - printf ( "Could not boot from %s: %s\n", - root_path, strerror ( rc ) ); + if ( ( rc = uriboot ( NULL, uri, opts.drive, flags ) ) != 0 ) goto err_uriboot; - } err_uriboot: uri_put ( uri ); @@ -83,8 +130,56 @@ static int sanboot_exec ( int argc, char **argv ) { 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_command __command = { - .name = "sanboot", - .exec = sanboot_exec, +struct command sanboot_commands[] __command = { + { + .name = "sanhook", + .exec = sanhook_exec, + }, + { + .name = "sanboot", + .exec = sanboot_exec, + }, + { + .name = "sanunhook", + .exec = sanunhook_exec, + }, }; diff --git a/roms/ipxe/src/hci/commands/sync_cmd.c b/roms/ipxe/src/hci/commands/sync_cmd.c new file mode 100644 index 000000000..221e87395 --- /dev/null +++ b/roms/ipxe/src/hci/commands/sync_cmd.c @@ -0,0 +1,83 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <string.h> +#include <stdio.h> +#include <getopt.h> +#include <ipxe/command.h> +#include <ipxe/parseopt.h> +#include <ipxe/timer.h> +#include <ipxe/pending.h> + +/** @file + * + * "sync" command + * + */ + +/** "sync" options */ +struct sync_options { + /** Timeout */ + unsigned int timeout; +}; + +/** "sync" option list */ +static struct option_descriptor sync_opts[] = { + OPTION_DESC ( "timeout", 't', required_argument, + struct sync_options, timeout, parse_integer ), +}; + +/** "sync" command descriptor */ +static struct command_descriptor sync_cmd = + COMMAND_DESC ( struct sync_options, sync_opts, 0, 0, + "[--timeout <timeout>]" ); + +/** + * "sync" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int sync_exec ( int argc, char **argv ) { + struct sync_options opts; + unsigned long timeout; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &sync_cmd, &opts ) ) != 0 ) + return rc; + + /* Wait for pending operations to complete */ + timeout = ( ( opts.timeout * TICKS_PER_SEC ) / 1000 ); + if ( ( rc = pending_wait ( timeout ) ) != 0 ) { + printf ( "Operations did not complete: %s\n", strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** Sync commands */ +struct command sync_command __command = { + .name = "sync", + .exec = sync_exec, +}; diff --git a/roms/ipxe/src/hci/commands/time_cmd.c b/roms/ipxe/src/hci/commands/time_cmd.c index 1dd175783..d1dd49caf 100644 --- a/roms/ipxe/src/hci/commands/time_cmd.c +++ b/roms/ipxe/src/hci/commands/time_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * March-19-2009 @ 02:44: Added sleep command. * Shao Miller <shao.miller@yrdsb.edu.on.ca>. @@ -27,7 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <unistd.h> #include <ipxe/command.h> #include <ipxe/parseopt.h> -#include <ipxe/nap.h> #include <ipxe/timer.h> /** @file @@ -57,7 +57,8 @@ static struct command_descriptor time_cmd = static int time_exec ( int argc, char **argv ) { struct time_options opts; unsigned long start; - int secs; + unsigned long elapsed; + int decisecs; int rc; /* Parse options */ @@ -66,9 +67,11 @@ static int time_exec ( int argc, char **argv ) { start = currticks(); rc = execv ( argv[1], argv + 1 ); - secs = (currticks() - start) / ticks_per_sec(); + elapsed = ( currticks() - start ); + decisecs = ( 10 * elapsed / ticks_per_sec() ); - printf ( "%s: %ds\n", argv[0], secs ); + printf ( "%s: %d.%ds\n", argv[0], + ( decisecs / 10 ), ( decisecs % 10 ) ); return rc; } @@ -78,42 +81,3 @@ struct command time_command __command = { .name = "time", .exec = time_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 long start, delay; - int rc; - - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &sleep_cmd, &opts ) ) != 0 ) - return rc; - - start = currticks(); - delay = strtoul ( argv[1], NULL, 0 ) * ticks_per_sec(); - while ( ( currticks() - start ) <= delay ) - cpu_nap(); - return 0; -} - -/** "sleep" command */ -struct command sleep_command __command = { - .name = "sleep", - .exec = sleep_exec, -}; diff --git a/roms/ipxe/src/hci/commands/vlan_cmd.c b/roms/ipxe/src/hci/commands/vlan_cmd.c index 28638ae6a..822e5dcf3 100644 --- a/roms/ipxe/src/hci/commands/vlan_cmd.c +++ b/roms/ipxe/src/hci/commands/vlan_cmd.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/editstring.c b/roms/ipxe/src/hci/editstring.c index 996528ff5..8c56d2337 100644 --- a/roms/ipxe/src/hci/editstring.c +++ b/roms/ipxe/src/hci/editstring.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -36,6 +37,7 @@ 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; /** @@ -108,6 +110,17 @@ static void backspace ( struct edit_string *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 * @@ -168,6 +181,10 @@ int edit_string ( struct edit_string *string, int key ) { /* 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 ); diff --git a/roms/ipxe/src/hci/keymap/keymap_no-latin1.c b/roms/ipxe/src/hci/keymap/keymap_no-latin1.c new file mode 100644 index 000000000..8c3e81b31 --- /dev/null +++ b/roms/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/roms/ipxe/src/hci/mucurses/ansi_screen.c b/roms/ipxe/src/hci/mucurses/ansi_screen.c index cc342f7ca..d952e5f2a 100644 --- a/roms/ipxe/src/hci/mucurses/ansi_screen.c +++ b/roms/ipxe/src/hci/mucurses/ansi_screen.c @@ -12,6 +12,8 @@ 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; @@ -20,6 +22,16 @@ static void ansiscr_reset ( struct _curses_screen *scr ) { 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 ) ) { @@ -65,8 +77,8 @@ static bool ansiscr_peek ( struct _curses_screen *scr __unused ) { } SCREEN _ansi_screen = { - .init = ansiscr_reset, - .exit = ansiscr_reset, + .init = ansiscr_init, + .exit = ansiscr_exit, .movetoyx = ansiscr_movetoyx, .putc = ansiscr_putc, .getc = ansiscr_getc, diff --git a/roms/ipxe/src/hci/mucurses/mucurses.c b/roms/ipxe/src/hci/mucurses/mucurses.c index 7c1620210..ab9a6535f 100644 --- a/roms/ipxe/src/hci/mucurses/mucurses.c +++ b/roms/ipxe/src/hci/mucurses/mucurses.c @@ -1,4 +1,3 @@ -#include <ipxe/console.h> #include <curses.h> #include "mucurses.h" diff --git a/roms/ipxe/src/hci/mucurses/widgets/editbox.c b/roms/ipxe/src/hci/mucurses/widgets/editbox.c index 5d2ba56cc..630a66e0b 100644 --- a/roms/ipxe/src/hci/mucurses/widgets/editbox.c +++ b/roms/ipxe/src/hci/mucurses/widgets/editbox.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/hci/readline.c b/roms/ipxe/src/hci/readline.c index 32793abe5..d67980b2c 100644 --- a/roms/ipxe/src/hci/readline.c +++ b/roms/ipxe/src/hci/readline.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -21,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <errno.h> #include <ipxe/console.h> #include <ipxe/keys.h> #include <ipxe/editstring.h> @@ -240,20 +242,25 @@ void history_free ( struct readline_history *history ) { * Read line from console (with history) * * @v prompt Prompt string + * @v prefill Prefill string, or NULL for no prefill * @v history History buffer, or NULL for no history * @ret line Line read from console (excluding terminating newline) + * @ret rc Return status code * * 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 ) { +int readline_history ( const char *prompt, const char *prefill, + struct readline_history *history, char **line ) { char buf[READLINE_MAX]; struct edit_string string; int key; int move_by; const char *new_string; - char *line; + int rc; + + /* Avoid returning uninitialised data on error */ + *line = NULL; /* Display prompt, if applicable */ if ( prompt ) @@ -264,6 +271,12 @@ char * readline_history ( const char *prompt, init_editstring ( &string, buf, sizeof ( buf ) ); buf[0] = '\0'; + /* Prefill string, if applicable */ + if ( prefill ) { + replace_string ( &string, prefill ); + sync_console ( &string ); + } + while ( 1 ) { /* Handle keypress */ key = edit_string ( &string, getkey ( 0 ) ); @@ -272,12 +285,11 @@ char * readline_history ( const char *prompt, switch ( key ) { case CR: case LF: - line = strdup ( buf ); - if ( ! line ) - printf ( "\nOut of memory" ); + *line = strdup ( buf ); + rc = ( ( *line ) ? 0 : -ENOMEM ); goto done; case CTRL_C: - line = NULL; + rc = -ECANCELED; goto done; case KEY_UP: move_by = 1; @@ -303,11 +315,12 @@ char * readline_history ( const char *prompt, done: putchar ( '\n' ); if ( history ) { - if ( line && line[0] ) - history_append ( history, line ); + if ( *line && (*line)[0] ) + history_append ( history, *line ); history_cleanup ( history ); } - return line; + assert ( ( rc == 0 ) ^ ( *line == NULL ) ); + return rc; } /** @@ -320,5 +333,8 @@ char * readline_history ( const char *prompt, * eventually call free() to release the storage. */ char * readline ( const char *prompt ) { - return readline_history ( prompt, NULL ); + char *line; + + readline_history ( prompt, NULL, NULL, &line ); + return line; } diff --git a/roms/ipxe/src/hci/shell.c b/roms/ipxe/src/hci/shell.c index e426ba946..b62086769 100644 --- a/roms/ipxe/src/hci/shell.c +++ b/roms/ipxe/src/hci/shell.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -85,7 +86,7 @@ int shell ( void ) { /* Read and execute commands */ do { - line = readline_history ( shell_prompt, &history ); + readline_history ( shell_prompt, NULL, &history, &line ); if ( line ) { rc = system ( line ); free ( line ); diff --git a/roms/ipxe/src/hci/tui/login_ui.c b/roms/ipxe/src/hci/tui/login_ui.c index 04aabfa8c..52ab0e360 100644 --- a/roms/ipxe/src/hci/tui/login_ui.c +++ b/roms/ipxe/src/hci/tui/login_ui.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -32,11 +33,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/editbox.h> #include <ipxe/keys.h> #include <ipxe/login_ui.h> +#include <config/colour.h> /* Colour pairs */ #define CPAIR_NORMAL 1 -#define CPAIR_LABEL 2 -#define CPAIR_EDITBOX 3 +#define CPAIR_EDIT 2 /* Screen layout */ #define USERNAME_LABEL_ROW 8 @@ -65,9 +66,8 @@ int login_ui ( void ) { /* 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_pair ( CPAIR_NORMAL, COLOR_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_EDIT, COLOR_EDIT_FG, COLOR_EDIT_BG ); init_editbox ( &username_box, username, sizeof ( username ), NULL, USERNAME_ROW, EDITBOX_COL, EDITBOX_WIDTH, 0 ); init_editbox ( &password_box, password, sizeof ( password ), NULL, @@ -75,11 +75,13 @@ int login_ui ( void ) { EDITBOX_STARS ); /* Draw initial UI */ + color_set ( CPAIR_NORMAL, NULL ); erase(); - color_set ( CPAIR_LABEL, NULL ); + attron ( A_BOLD ); mvprintw ( USERNAME_LABEL_ROW, LABEL_COL, "Username:" ); mvprintw ( PASSWORD_LABEL_ROW, LABEL_COL, "Password:" ); - color_set ( CPAIR_EDITBOX, NULL ); + attroff ( A_BOLD ); + color_set ( CPAIR_EDIT, NULL ); draw_editbox ( &username_box ); draw_editbox ( &password_box ); diff --git a/roms/ipxe/src/hci/tui/menu_ui.c b/roms/ipxe/src/hci/tui/menu_ui.c new file mode 100644 index 000000000..dfa1d2e76 --- /dev/null +++ b/roms/ipxe/src/hci/tui/menu_ui.c @@ -0,0 +1,367 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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> +#include <config/colour.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; + char buf[ MENU_COLS + 1 /* NUL */ ]; + 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_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_SELECT, COLOR_SELECT_FG, COLOR_SELECT_BG ); + init_pair ( CPAIR_SEPARATOR, COLOR_SEPARATOR_FG, COLOR_SEPARATOR_BG ); + color_set ( CPAIR_NORMAL, NULL ); + erase(); + + /* Draw initial content */ + attron ( A_BOLD ); + snprintf ( buf, sizeof ( buf ), "%s", ui.menu->title ); + mvprintw ( TITLE_ROW, ( ( COLS - strlen ( buf ) ) / 2 ), "%s", buf ); + 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/roms/ipxe/src/hci/tui/settings_ui.c b/roms/ipxe/src/hci/tui/settings_ui.c index ed076101f..403d12453 100644 --- a/roms/ipxe/src/hci/tui/settings_ui.c +++ b/roms/ipxe/src/hci/tui/settings_ui.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -28,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/editbox.h> #include <ipxe/keys.h> #include <ipxe/settings_ui.h> +#include <config/colour.h> /** @file * @@ -557,11 +559,11 @@ int settings_ui ( struct settings *settings ) { 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 ); + init_pair ( CPAIR_NORMAL, COLOR_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_SELECT, COLOR_SELECT_FG, COLOR_SELECT_BG ); + init_pair ( CPAIR_EDIT, COLOR_EDIT_FG, COLOR_EDIT_BG ); + init_pair ( CPAIR_ALERT, COLOR_ALERT_FG, COLOR_ALERT_BG ); + init_pair ( CPAIR_URL, COLOR_URL_FG, COLOR_URL_BG ); color_set ( CPAIR_NORMAL, NULL ); erase(); diff --git a/roms/ipxe/src/hci/wireless_errors.c b/roms/ipxe/src/hci/wireless_errors.c index 63c6251c6..7154df556 100644 --- a/roms/ipxe/src/hci/wireless_errors.c +++ b/roms/ipxe/src/hci/wireless_errors.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/image/efi_image.c b/roms/ipxe/src/image/efi_image.c index 0575496cb..bee966e71 100644 --- a/roms/ipxe/src/image/efi_image.c +++ b/roms/ipxe/src/image/efi_image.c @@ -13,19 +13,102 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 * @@ -34,7 +117,12 @@ FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); */ 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; @@ -47,21 +135,56 @@ static int efi_image_exec ( struct image *image ) { /* Not an EFI image */ DBGC ( image, "EFIIMAGE %p could not load: %s\n", image, efi_strerror ( efirc ) ); - return -ENOEXEC; + 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; } - rc = EFIRC_TO_RC ( efirc ); + /* 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; } diff --git a/roms/ipxe/src/image/elf.c b/roms/ipxe/src/image/elf.c index 406a8d477..51636a8e9 100644 --- a/roms/ipxe/src/image/elf.c +++ b/roms/ipxe/src/image/elf.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -38,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); typedef Elf32_Ehdr Elf_Ehdr; typedef Elf32_Phdr Elf_Phdr; typedef Elf32_Off Elf_Off; +#define ELFCLASS ELFCLASS32 /** * Load ELF segment into memory @@ -46,11 +48,14 @@ typedef Elf32_Off Elf_Off; * @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 ) { + Elf_Ehdr *ehdr, physaddr_t *entry, + physaddr_t *max ) { physaddr_t dest; + physaddr_t end; userptr_t buffer; unsigned long e_offset; int rc; @@ -78,6 +83,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, 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 ), @@ -92,6 +98,10 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, 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 ); @@ -118,9 +128,17 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, * * @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 ) { +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; @@ -129,11 +147,15 @@ int elf_load ( struct image *image, physaddr_t *entry ) { /* Read ELF header */ copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); - if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { + 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; @@ -147,7 +169,7 @@ int elf_load ( struct image *image, physaddr_t *entry ) { } copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); if ( ( rc = elf_load_segment ( image, &phdr, &ehdr, - entry ) ) != 0 ) { + entry, max ) ) != 0 ) { return rc; } } diff --git a/roms/ipxe/src/image/script.c b/roms/ipxe/src/image/script.c index 161ac682e..e83180ab5 100644 --- a/roms/ipxe/src/image/script.c +++ b/roms/ipxe/src/image/script.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -58,6 +59,7 @@ static int process_script ( struct image *image, int ( * terminate ) ( int rc ) ) { off_t eol; size_t len; + char *line; int rc; script_offset = 0; @@ -71,23 +73,23 @@ static int process_script ( struct image *image, eol = image->len; len = ( eol - script_offset ); - /* Copy line, terminate with NUL, and execute command */ - { - char cmdbuf[ len + 1 ]; + /* Allocate buffer for line */ + line = zalloc ( len + 1 /* NUL */ ); + if ( ! line ) + return -ENOMEM; - copy_from_user ( cmdbuf, image->data, - script_offset, len ); - cmdbuf[len] = '\0'; - DBG ( "$ %s\n", cmdbuf ); + /* Copy line */ + copy_from_user ( line, image->data, script_offset, len ); + DBG ( "$ %s\n", line ); - /* Move to next line */ - script_offset += ( len + 1 ); + /* Move to next line */ + script_offset += ( len + 1 ); - /* Process line */ - rc = process_line ( cmdbuf ); - if ( terminate ( rc ) ) - return rc; - } + /* Process and free line */ + rc = process_line ( line ); + free ( line ); + if ( terminate ( rc ) ) + return rc; } while ( script_offset < image->len ); @@ -221,11 +223,17 @@ static const char *goto_label; * @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 ( strcmp ( goto_label, &line[1] ) != 0 ) + + if ( strncmp ( goto_label, &line[1], len ) != 0 ) + return -ENOENT; + + if ( line[ 1 + len ] && ! isspace ( line[ 1 + len ] ) ) return -ENOENT; + return 0; } @@ -296,7 +304,7 @@ struct prompt_options { /** "prompt" option list */ static struct option_descriptor prompt_opts[] = { OPTION_DESC ( "key", 'k', required_argument, - struct prompt_options, key, parse_integer ), + struct prompt_options, key, parse_key ), OPTION_DESC ( "timeout", 't', required_argument, struct prompt_options, timeout, parse_integer ), }; diff --git a/roms/ipxe/src/image/segment.c b/roms/ipxe/src/image/segment.c index 97f6a9959..86fe42662 100644 --- a/roms/ipxe/src/image/segment.c +++ b/roms/ipxe/src/image/segment.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/include/assert.h b/roms/ipxe/src/include/assert.h index 40a00a2b1..655cbdc03 100644 --- a/roms/ipxe/src/include/assert.h +++ b/roms/ipxe/src/include/assert.h @@ -18,6 +18,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ASSERTING 1 #endif +extern unsigned int assertion_failures; + /** printf() for assertions * * This function exists so that the assert() macro can expand to @@ -43,6 +45,7 @@ assert_printf ( const char *fmt, ... ) asm ( "printf" ); #define assert( condition ) \ do { \ if ( ASSERTING && ! (condition) ) { \ + assertion_failures++; \ assert_printf ( "assert(%s) failed at %s line %d\n", \ #condition, __FILE__, __LINE__ ); \ } \ diff --git a/roms/ipxe/src/include/btext.h b/roms/ipxe/src/include/btext.h deleted file mode 100644 index 1d3f9e59b..000000000 --- a/roms/ipxe/src/include/btext.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file describes the structure passed from the BootX application - * (for MacOS) when it is used to boot Linux. - * - * Written by Benjamin Herrenschmidt. - * - * Move to LinuxBIOS by LYH yhlu@tyan.com - * - */ - - -#ifndef _BTEXT_H__ -#define _BTEXT_H__ - -#if 1 -#define u32 unsigned int -#define u16 unsigned short -#define u8 unsigned char -#endif - -/* Here are the boot informations that are passed to the bootstrap - * Note that the kernel arguments and the device tree are appended - * at the end of this structure. */ -typedef struct boot_infos -{ - - /* NEW (vers. 2) this holds the current _logical_ base addr of - the frame buffer (for use by early boot message) */ - u8* logicalDisplayBase; - - - /* Some infos about the current MacOS display */ - u32 dispDeviceRect[4]; /* left,top,right,bottom */ - u32 dispDeviceDepth; /* (8, 16 or 32) */ - u32 dispDeviceBase; /* base address (physical) */ - u32 dispDeviceRowBytes; /* rowbytes (in bytes) */ - u32 dispDeviceColorsOffset; /* Colormap (8 bits only) or 0 (*) */ - - - /* The framebuffer size (optional, currently 0) */ - u32 frameBufferSize; /* Represents a max size, can be 0. */ - - -} boot_infos_t; - -/* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index is represented - * by 3 short words containing a 16 bits (unsigned) color component. - * Later versions may contain the gamma table for direct-color devices here. - */ -#define BOOTX_COLORTABLE_SIZE (256UL*3UL*2UL) - - -/* - * Definitions for using the procedures in btext.c. - * - * Benjamin Herrenschmidt <benh@kernel.crashing.org> - */ - -extern boot_infos_t disp_bi; -extern u32 boot_text_mapped; - -#endif /* _BTEXT_H */ diff --git a/roms/ipxe/src/include/compiler.h b/roms/ipxe/src/include/compiler.h index feea5167e..ed9af237d 100644 --- a/roms/ipxe/src/include/compiler.h +++ b/roms/ipxe/src/include/compiler.h @@ -260,19 +260,9 @@ REQUEST_EXPANDED ( CONFIG_SYMBOL ); #ifndef ASSEMBLY -/** printf() for debugging - * - * This function exists so that the DBG() macros can expand to - * printf() calls without dragging the printf() prototype into scope. - * - * As far as the compiler is concerned, dbg_printf() and printf() are - * completely unrelated calls; it's only at the assembly stage that - * references to the dbg_printf symbol are collapsed into references - * to the printf symbol. - */ -extern int __attribute__ (( format ( printf, 1, 2 ) )) -dbg_printf ( const char *fmt, ... ) asm ( "printf" ); - +/** 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, @@ -339,6 +329,7 @@ int __debug_disable; unsigned long ul; \ typeof ( dispaddr ) raw; \ } da; \ + da.ul = 0; \ da.raw = dispaddr; \ dbg_hex_dump_da ( da.ul, data, len ); \ } \ @@ -370,6 +361,7 @@ int __debug_disable; unsigned long ul; \ typeof ( dispaddr ) raw; \ } da; \ + da.ul = 0; \ da.raw = dispaddr; \ dbg_md5_da ( da.ul, data, len ); \ } \ @@ -421,6 +413,7 @@ int __debug_disable; unsigned long ul; \ typeof ( id ) raw; \ } dbg_stream; \ + dbg_stream.ul = 0; \ dbg_stream.raw = id; \ dbg_autocolourise ( dbg_stream.ul ); \ } \ diff --git a/roms/ipxe/src/include/errno.h b/roms/ipxe/src/include/errno.h index a86573fc9..bd4ddaf41 100644 --- a/roms/ipxe/src/include/errno.h +++ b/roms/ipxe/src/include/errno.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef ERRNO_H diff --git a/roms/ipxe/src/include/etherboot.h b/roms/ipxe/src/include/etherboot.h index b2fbe4f67..ba79cb16a 100644 --- a/roms/ipxe/src/include/etherboot.h +++ b/roms/ipxe/src/include/etherboot.h @@ -14,7 +14,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdio.h> #include <unistd.h> #include <strings.h> -#include <ipxe/console.h> #include <ipxe/timer.h> #include <ipxe/if_arp.h> #include <ipxe/if_ether.h> diff --git a/roms/ipxe/src/include/hci/ifmgmt_cmd.h b/roms/ipxe/src/include/hci/ifmgmt_cmd.h index a7751cb28..abdb27f43 100644 --- a/roms/ipxe/src/include/hci/ifmgmt_cmd.h +++ b/roms/ipxe/src/include/hci/ifmgmt_cmd.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IFMGMT_CMD_H diff --git a/roms/ipxe/src/include/ipxe/aes.h b/roms/ipxe/src/include/ipxe/aes.h index 5d645b207..4e44f9853 100644 --- a/roms/ipxe/src/include/ipxe/aes.h +++ b/roms/ipxe/src/include/ipxe/aes.h @@ -21,6 +21,10 @@ struct aes_context { /** 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; diff --git a/roms/ipxe/src/include/ipxe/ansiesc.h b/roms/ipxe/src/include/ipxe/ansiesc.h index 35438e43a..c00af258a 100644 --- a/roms/ipxe/src/include/ipxe/ansiesc.h +++ b/roms/ipxe/src/include/ipxe/ansiesc.h @@ -113,6 +113,13 @@ struct ansiesc_context { /** 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 ); diff --git a/roms/ipxe/src/include/ipxe/arp.h b/roms/ipxe/src/include/ipxe/arp.h index f7b99c68d..00396d821 100644 --- a/roms/ipxe/src/include/ipxe/arp.h +++ b/roms/ipxe/src/include/ipxe/arp.h @@ -35,10 +35,8 @@ struct arp_net_protocol { extern struct net_protocol arp_protocol __net_protocol; -extern int arp_resolve ( struct net_device *netdev, - struct net_protocol *net_protocol, - const void *dest_net_addr, - const void *source_net_addr, - void *dest_ll_addr ); +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/roms/ipxe/src/include/ipxe/asn1.h b/roms/ipxe/src/include/ipxe/asn1.h index 85e480e87..3e73b59c7 100644 --- a/roms/ipxe/src/include/ipxe/asn1.h +++ b/roms/ipxe/src/include/ipxe/asn1.h @@ -9,26 +9,295 @@ 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 -#define ASN1_IP_ADDRESS 0x40 -#define ASN1_EXPLICIT_TAG 0xa0 -/** - * A DER-encoded ASN.1 object cursor +/** 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 */ -struct asn1_cursor { - /** Start of data */ - void *data; - /** Length of data */ - size_t len; +#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/roms/ipxe/src/include/ipxe/bigint.h b/roms/ipxe/src/include/ipxe/bigint.h new file mode 100644 index 000000000..97fbce245 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/bitbash.h b/roms/ipxe/src/include/ipxe/bitbash.h index 62b54b10f..69d5d9e3e 100644 --- a/roms/ipxe/src/include/ipxe/bitbash.h +++ b/roms/ipxe/src/include/ipxe/bitbash.h @@ -13,6 +13,18 @@ struct bit_basher; /** Bit-bashing operations */ struct bit_basher_operations { + /** + * Open bit-bashing interface (optional) + * + * @v basher Bit-bashing interface + */ + void ( * open ) ( struct bit_basher *basher ); + /** + * Close bit-bashing interface (optional) + * + * @v basher Bit-bashing interface + */ + void ( * close ) ( struct bit_basher *basher ); /** * Set/clear output bit * @@ -45,6 +57,26 @@ struct bit_basher { struct bit_basher_operations *op; }; +/** + * Open bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static inline void open_bit ( struct bit_basher *basher ) { + if ( basher->op->open ) + basher->op->open ( basher ); +} + +/** + * Close bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static inline void close_bit ( struct bit_basher *basher ) { + if ( basher->op->close ) + basher->op->close ( basher ); +} + 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 ); diff --git a/roms/ipxe/src/include/ipxe/bitops.h b/roms/ipxe/src/include/ipxe/bitops.h index 4118ef819..73e859f41 100644 --- a/roms/ipxe/src/include/ipxe/bitops.h +++ b/roms/ipxe/src/include/ipxe/bitops.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/include/ipxe/clientcert.h b/roms/ipxe/src/include/ipxe/clientcert.h new file mode 100644 index 000000000..08f62eb73 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/cms.h b/roms/ipxe/src/include/ipxe/cms.h new file mode 100644 index 000000000..eadeca4b8 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/console.h b/roms/ipxe/src/include/ipxe/console.h index 3bfa5033f..e2bf4be97 100644 --- a/roms/ipxe/src/include/ipxe/console.h +++ b/roms/ipxe/src/include/ipxe/console.h @@ -1,6 +1,7 @@ #ifndef _IPXE_CONSOLE_H #define _IPXE_CONSOLE_H +#include <stdio.h> #include <ipxe/tables.h> /** @file @@ -74,6 +75,13 @@ struct console_driver { * */ 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 */ @@ -98,10 +106,57 @@ struct console_driver { */ #define __console_driver __table_entry ( CONSOLES, 01 ) -/* Function prototypes */ +/** + * @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 void putchar ( int character ); -extern int getchar ( void ); extern int iskey ( void ); extern int getkey ( unsigned long timeout ); diff --git a/roms/ipxe/src/include/ipxe/crypto.h b/roms/ipxe/src/include/ipxe/crypto.h index 9383c076c..d7d42b66c 100644 --- a/roms/ipxe/src/include/ipxe/crypto.h +++ b/roms/ipxe/src/include/ipxe/crypto.h @@ -96,6 +96,67 @@ struct pubkey_algorithm { 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, @@ -147,10 +208,45 @@ 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; -void get_random_bytes ( void *buf, size_t len ); - #endif /* _IPXE_CRYPTO_H */ diff --git a/roms/ipxe/src/include/ipxe/dhcp.h b/roms/ipxe/src/include/ipxe/dhcp.h index 148e3d66f..b97dfe32c 100644 --- a/roms/ipxe/src/include/ipxe/dhcp.h +++ b/roms/ipxe/src/include/ipxe/dhcp.h @@ -10,6 +10,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> +#include <stdarg.h> #include <ipxe/in.h> #include <ipxe/list.h> #include <ipxe/refcnt.h> @@ -240,6 +241,39 @@ struct dhcp_client_id { /** 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 @@ -318,6 +352,21 @@ struct dhcp_client_uuid { */ #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 @@ -425,32 +474,6 @@ struct dhcp_netdev_desc { /** @} */ -/** - * 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 ) - /** Construct a DHCP option from a list of bytes */ #define DHCP_OPTION( ... ) VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__ @@ -627,15 +650,16 @@ struct dhcphdr { /** Setting block name used for BootServerDHCP responses */ #define PXEBS_SETTINGS_NAME "pxebs" -extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr, - uint16_t *flags ); +extern uint32_t dhcp_last_xid; extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, - const void *options, size_t options_len, - void *data, size_t max_len ); + 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, struct in_addr ciaddr, + 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, diff --git a/roms/ipxe/src/include/ipxe/drbg.h b/roms/ipxe/src/include/ipxe/drbg.h new file mode 100644 index 000000000..6374e7787 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/eapol.h b/roms/ipxe/src/include/ipxe/eapol.h index 3fad44284..5ca9c2815 100644 --- a/roms/ipxe/src/include/ipxe/eapol.h +++ b/roms/ipxe/src/include/ipxe/eapol.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_EAPOL_H diff --git a/roms/ipxe/src/include/ipxe/efi/Base.h b/roms/ipxe/src/include/ipxe/efi/Base.h index 999b41471..2fb4ec6f6 100644 --- a/roms/ipxe/src/include/ipxe/efi/Base.h +++ b/roms/ipxe/src/include/ipxe/efi/Base.h @@ -6,7 +6,7 @@ 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> +Copyright (c) 2006 - 2012, 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 @@ -395,6 +395,7 @@ struct _LIST_ENTRY { // 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. +// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start. // // example: // @@ -456,6 +457,13 @@ struct _LIST_ENTRY { #define VA_END(Marker) ((void)0) +// For some ARM RVCT compilers, __va_copy is not defined +#ifndef __va_copy + #define __va_copy(dest, src) ((void)((dest) = (src))) +#endif + +#define VA_COPY(Dest, Start) __va_copy (Dest, Start) + #elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS) // // Use GCC built-in macros for variable argument lists. @@ -473,6 +481,8 @@ typedef __builtin_va_list VA_LIST; #define VA_END(Marker) __builtin_va_end (Marker) +#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) + #else /// /// Variable used to traverse the list of arguments. This type can vary by @@ -528,6 +538,19 @@ typedef CHAR8 *VA_LIST; **/ #define VA_END(Marker) (Marker = (VA_LIST) 0) +/** + Initializes a VA_LIST as a copy of an existing VA_LIST. + + This macro initializes Dest as a copy of Start, as if the VA_START macro had been applied to Dest + followed by the same sequence of uses of the VA_ARG macro as had previously been used to reach + the present state of Start. + + @param Dest VA_LIST used to traverse the list of arguments. + @param Start VA_LIST used to traverse the list of arguments. + +**/ +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + #endif /// @@ -678,10 +701,22 @@ typedef UINTN *BASE_LIST; @return Minimum of two operands. **/ - #define MIN(a, b) \ (((a) < (b)) ? (a) : (b)) +/** + Return the absolute value of a signed operand. + + This macro returns the absolute value of the signed operand specified by a. + + @param a The signed operand. + + @return The absolute value of the signed operand. + +**/ +#define ABS(a) \ + (((a) < 0) ? (-(a)) : (a)) + // // Status codes common to all execution phases // @@ -884,6 +919,12 @@ typedef UINTN RETURN_STATUS; /// #define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) /// /// The string contained one or more characters that @@ -908,6 +949,12 @@ typedef UINTN RETURN_STATUS; /// #define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + /** Returns a 16-bit signature built from 2 ASCII characters. diff --git a/roms/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h b/roms/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h index 20cf407b6..89bce6ff9 100644 --- a/roms/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h +++ b/roms/ipxe/src/include/ipxe/efi/Ia32/ProcessorBind.h @@ -1,7 +1,7 @@ /** @file Processor or Compiler specific defines and types for IA-32 architecture. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2006 - 2012, 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 @@ -149,7 +149,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value. /// - typedef char INT8; + typedef signed char INT8; #else /// /// 8-byte unsigned value. @@ -196,7 +196,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #endif /// @@ -247,13 +247,17 @@ typedef INT32 INTN; /// Microsoft* compiler specific method for EFIAPI calling convention. /// #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// GCC specific method for EFIAPI calling convention. + /// + #define EFIAPI __attribute__((cdecl)) #else - #if defined(__GNUC__) - /// - /// GCC specific method for EFIAPI calling convention. - /// - #define EFIAPI __attribute__((cdecl)) - #endif + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI #endif #if defined(__GNUC__) diff --git a/roms/ipxe/src/include/ipxe/efi/Library/BaseLib.h b/roms/ipxe/src/include/ipxe/efi/Library/BaseLib.h new file mode 100644 index 000000000..af4c87434 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/efi/Library/BaseLib.h @@ -0,0 +1,7218 @@ +/** @file + Provides string functions, linked list functions, math functions, synchronization + functions, and CPU architecture-specific functions. + +Copyright (c) 2006 - 2012, 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_LIB__ +#define __BASE_LIB__ + +// +// Definitions for architecture-specific types +// +#if defined (MDE_CPU_IA32) +/// +/// The IA-32 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_IA32) + +#if defined (MDE_CPU_IPF) + +/// +/// The Itanium architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[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 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 SP; + UINT64 BR0; + UINT64 BR1; + UINT64 BR2; + UINT64 BR3; + UINT64 BR4; + UINT64 BR5; + UINT64 InitialUNAT; + UINT64 AfterSpillUNAT; + UINT64 PFS; + UINT64 BSP; + UINT64 Predicates; + UINT64 LoopCount; + UINT64 FPSR; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 + +#endif // defined (MDE_CPU_IPF) + +#if defined (MDE_CPU_X64) +/// +/// The x64 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT64 MxCsr; + UINT8 XmmBuffer[160]; ///< XMM6-XMM15. +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_X64) + +#if defined (MDE_CPU_EBC) +/// +/// The EBC context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 IP; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_EBC) + +#if defined (MDE_CPU_ARM) + +typedef struct { + UINT32 R3; ///< A copy of R13. + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R14; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_ARM) + +// +// String Services +// + +/** + Copies one Null-terminated Unicode string to another Null-terminated Unicode + string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + Copies up to a specified length from one Null-terminated Unicode string to + another Null-terminated Unicode string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. At most, Length Unicode + characters are copied from Source to Destination. If Length is 0, then + Destination is returned unmodified. If Length is greater that the number of + Unicode characters in Source, then Destination is padded with Null Unicode + characters. If Source and Destination overlap, then the results are + undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ); + + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated Unicode string + specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ); + + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated Unicode string. + @param SecondString The pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ); + + +/** + Compares up to a specified length the contents of two Null-terminated Unicode strings, + and returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString The pointer to a Null-terminated Unicode string. + @param SecondString The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ); + + +/** + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string, and returns the concatenated Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination. The Null-terminated concatenated + Unicode String is returned. If Source and Destination overlap, then the + results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + Concatenates up to a specified length one Null-terminated Unicode to the end + of another Null-terminated Unicode string, and returns the concatenated + Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination, and Destination is returned. At + most, Length Unicode characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than PcdMaximumUnicodeStringLength + Unicode characters, not including the Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to concatenate from + Source. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + +/** + Returns the first occurrence of a Null-terminated Unicode sub-string + in a Null-terminated Unicode string. + + This function scans the contents of the Null-terminated Unicode string + specified by String and returns the first occurrence of SearchString. + If SearchString is not found in String, then NULL is returned. If + the length of SearchString is zero, then String is returned. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If SearchString is NULL, then ASSERT(). + If SearchString is not aligned on a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and SearchString + or String contains more than PcdMaximumUnicodeStringLength Unicode + characters, not including the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + @param SearchString The pointer to a Null-terminated Unicode string to search for. + + @retval NULL If the SearchString does not appear in String. + @return others If there is a match. + +**/ +CHAR16 * +EFIAPI +StrStr ( + IN CONST CHAR16 *String, + IN CONST CHAR16 *SearchString + ); + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINTN, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrDecimalToUintn ( + IN CONST CHAR16 *String + ); + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINT64, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrDecimalToUint64 ( + IN CONST CHAR16 *String + ); + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character + that is a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINTN, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrHexToUintn ( + IN CONST CHAR16 *String + ); + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINT64, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrHexToUint64 ( + IN CONST CHAR16 *String + ); + +/** + Convert a Null-terminated Unicode string to a Null-terminated + ASCII string and returns the ASCII string. + + This function converts the content of the Unicode string Source + to the ASCII string Destination by copying the lower 8 bits of + each Unicode character. It returns Destination. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in + the upper 8 bits, then ASSERT(). + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and Source contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and Source contains more + than PcdMaximumAsciiStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param Source The pointer to a Null-terminated Unicode string. + @param Destination The pointer to a Null-terminated ASCII string. + + @return Destination. + +**/ +CHAR8 * +EFIAPI +UnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ); + + +/** + Copies one Null-terminated ASCII string to another Null-terminated ASCII + string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + Copies up to a specified length one Null-terminated ASCII string to another + Null-terminated ASCII string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. At most, Length ASCII characters + are copied from Source to Destination. If Length is 0, then Destination is + returned unmodified. If Length is greater that the number of ASCII characters + in Source, then Destination is padded with Null ASCII characters. If Source + and Destination overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to copy. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ); + + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ); + + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters for compare. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ); + + +/** + Concatenates one Null-terminated ASCII string to another Null-terminated + ASCII string, and returns the concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents of + Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination. The Null-terminated concatenated ASCII + String is returned. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + Concatenates up to a specified length one Null-terminated ASCII string to + the end of another Null-terminated ASCII string, and returns the + concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents + of Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination, and Destination is returned. At most, + Length ASCII characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, not including the Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to concatenate from + Source. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + + +/** + Returns the first occurrence of a Null-terminated ASCII sub-string + in a Null-terminated ASCII string. + + This function scans the contents of the ASCII string specified by String + and returns the first occurrence of SearchString. If SearchString is not + found in String, then NULL is returned. If the length of SearchString is zero, + then String is returned. + + If String is NULL, then ASSERT(). + If SearchString is NULL, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and SearchString or + String contains more than PcdMaximumAsciiStringLength Unicode characters + not including the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + @param SearchString The pointer to a Null-terminated ASCII string to search for. + + @retval NULL If the SearchString does not appear in String. + @retval others If there is a match return the first occurrence of SearchingString. + If the length of SearchString is zero,return String. + +**/ +CHAR8 * +EFIAPI +AsciiStrStr ( + IN CONST CHAR8 *String, + IN CONST CHAR8 *SearchString + ); + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINTN, then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval The value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrDecimalToUintn ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINT64, then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrDecimalToUint64 ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINTN, + then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrHexToUintn ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINT64, + then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrHexToUint64 ( + IN CONST CHAR8 *String + ); + + +/** + Convert one Null-terminated ASCII string to a Null-terminated + Unicode string and returns the Unicode string. + + This function converts the contents of the ASCII string Source to the Unicode + string Destination, and returns Destination. The function terminates the + Unicode string Destination by appending a Null-terminator character at the end. + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param Source The pointer to a Null-terminated ASCII string. + @param Destination The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +AsciiStrToUnicodeStr ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination + ); + + +/** + Converts an 8-bit value to an 8-bit BCD value. + + Converts the 8-bit value specified by Value to BCD. The BCD value is + returned. + + If Value >= 100, then ASSERT(). + + @param Value The 8-bit value to convert to BCD. Range 0..99. + + @return The BCD value. + +**/ +UINT8 +EFIAPI +DecimalToBcd8 ( + IN UINT8 Value + ); + + +/** + Converts an 8-bit BCD value to an 8-bit value. + + Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit + value is returned. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Value The 8-bit BCD value to convert to an 8-bit value. + + @return The 8-bit value is returned. + +**/ +UINT8 +EFIAPI +BcdToDecimal8 ( + IN UINT8 Value + ); + + +// +// Linked List Functions and Macros +// + +/** + Initializes the head node of a doubly linked list that is declared as a + global variable in a module. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this macro, the other linked list functions + may be used to add and remove nodes from the linked list. This macro results + in smaller executables by initializing the linked list in the data section, + instead if calling the InitializeListHead() function to perform the + equivalent operation. + + @param ListHead The head note of a list to initialize. + +**/ +#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead) {&(ListHead), &(ListHead)} + + +/** + Initializes the head node of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN OUT LIST_ENTRY *ListHead + ); + + +/** + Adds a node to the beginning of a doubly linked list, and returns the pointer + to the head node of the doubly linked list. + + Adds the node Entry at the beginning of the doubly linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ); + + +/** + Adds a node to the end of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Adds the node Entry to the end of the doubly linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ); + + +/** + Retrieves the first node of a doubly linked list. + + Returns the first node of a doubly linked list. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + + @return The first node of a doubly linked list. + @retval NULL The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ); + + +/** + Retrieves the next node of a doubly linked list. + + Returns the node of a doubly linked list that follows Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return The pointer to the next node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Retrieves the previous node of a doubly linked list. + + Returns the node of a doubly linked list that precedes Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return The pointer to the previous node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetPreviousNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Checks to see if a doubly linked list is empty or not. + + Checks to see if the doubly linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *ListHead + ); + + +/** + Determines if a node in a doubly linked list is the head node of a the same + doubly linked list. This function is typically used to terminate a loop that + traverses all the nodes in a doubly linked list starting with the head node. + + Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the + nodes in the doubly linked list specified by List. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), + then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List the and Node is not equal + to List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the head of the doubly-linked list pointed by List. + @retval FALSE Node is not the head of the doubly-linked list pointed by List. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Determines if a node the last node in a doubly linked list. + + Returns TRUE if Node is the last node in the doubly linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Swaps the location of two nodes in a doubly linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + SecondEntry is returned after the nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If PcdVerifyNodeInList is TRUE and SecondEntry and FirstEntry are not in the + same linked list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing the FirstEntry and SecondEntry nodes, including + the FirstEntry and SecondEntry nodes, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + + @return SecondEntry. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN OUT LIST_ENTRY *FirstEntry, + IN OUT LIST_ENTRY *SecondEntry + ); + + +/** + Removes a node from a doubly linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing Entry, including the Entry node, is greater than + or equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param Entry A pointer to a node in a linked list. + + @return Entry. + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ); + +// +// Math Services +// + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ); + + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ); + + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ); + + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ); + + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ); + + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ); + + +/** + Switches the endianness of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 16-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Value + ); + + +/** + Switches the endianness of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 32-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Value + ); + + +/** + Switches the endianness of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 64-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Value + ); + + +/** + Multiples a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + + +/** + Multiples a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + + +/** + Multiples a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiples the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ); + + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ); + + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + It is the caller's responsibility to not call this function with a Divisor of 0. + If Divisor is 0, then the quotient and remainder should be assumed to be + the largest negative integer. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ); + + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + + @return The 16-bit value read from Buffer. + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ); + + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return The 16-bit value to write to Buffer. + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ); + + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + + @return The 24-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ); + + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The 24-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ); + + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + + @return The 32-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ); + + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return The 32-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ); + + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + + @return The 64-bit value read from Buffer. + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ); + + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return The 64-bit value to write to Buffer. + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ); + + +// +// Bit Field Functions +// + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +// +// Base Library Checksum Functions +// + +/** + Returns the sum of all elements in a buffer in unit of UINT8. + During calculation, the carry bits are dropped. + + This function calculates the sum of all elements in a buffer + in unit of UINT8. The carry bits in result of addition are dropped. + The result is returned as UINT8. If Length is Zero, then Zero is + returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT8 +EFIAPI +CalculateSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer + of 8-bit values. + + This function first calculates the sum of the 8-bit values in the + buffer specified by Buffer and Length. The carry bits in the result + of addition are dropped. Then, the two's complement of the sum is + returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT8 +EFIAPI +CalculateCheckSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 16-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT16 +EFIAPI +CalculateSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 16-bit values. + + This function first calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT16 +EFIAPI +CalculateCheckSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 32-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 32-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT32 +EFIAPI +CalculateSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 32-bit values. + + This function first calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT32 +EFIAPI +CalculateCheckSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 64-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 64-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT64 +EFIAPI +CalculateSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 64-bit values. + + This function first calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT64 +EFIAPI +CalculateCheckSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ); + + +// +// Base Library CPU Functions +// + +/** + Function entry point used when a stack switch is requested with SwitchStack() + + @param Context1 Context1 parameter passed into SwitchStack(). + @param Context2 Context2 parameter passed into SwitchStack(). + +**/ +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT)( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ); + + +/** + Saves the current CPU context that can be restored with a call to LongJump() + and returns 0. + + Saves the current CPU context in the buffer specified by JumpBuffer and + returns 0. The initial call to SetJump() must always return 0. Subsequent + calls to LongJump() cause a non-zero value to be returned by SetJump(). + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + NOTE: The structure BASE_LIBRARY_JUMP_BUFFER is CPU architecture specific. + The same structure must never be used for more than one CPU architecture context. + For example, a BASE_LIBRARY_JUMP_BUFFER allocated by an IA-32 module must never be used from an x64 module. + SetJump()/LongJump() is not currently supported for the EBC processor type. + + @param JumpBuffer A pointer to CPU context buffer. + + @retval 0 Indicates a return from SetJump(). + +**/ +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ); + + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. This + function never returns to the caller. Instead is resumes execution based on + the state of JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + If Value is 0, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is + restored and must be non-zero. + +**/ +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ); + + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ); + + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ); + + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ); + + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ); + + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE if interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ); + + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ); + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ); + + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. This function + supports a variable number of arguments following the NewStack parameter. + These additional arguments are ignored on IA-32, x64, and EBC architectures. + Itanium processors expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param ... This variable argument list is ignored for IA-32, x64, and + EBC architectures. For Itanium processors, this variable + argument list is expected to contain a single parameter of + type VOID * that specifies the new backing store pointer. + + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + ... + ); + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ); + + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ); + +#if defined (MDE_CPU_IPF) + +/** + Flush a range of cache lines in the cache coherency domain of the calling + CPU. + + Flushes the cache lines specified by Address and Length. If Address is not aligned + on a cache line boundary, then entire cache line containing Address is flushed. + If Address + Length is not aligned on a cache line boundary, then the entire cache + line containing Address + Length - 1 is flushed. This function may choose to flush + the entire cache if that is more efficient than flushing the specified range. If + Length is 0, the no cache lines are flushed. Address is returned. + This function is only available on Itanium processors. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +AsmFlushCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + + +/** + Executes an FC instruction. + Executes an FC instruction on the cache line specified by Address. + The cache line size affected is at least 32-bytes (aligned on a 32-byte boundary). + An implementation may flush a larger region. This function is only available on Itanium processors. + + @param Address The Address of cache line to be flushed. + + @return The address of FC instruction executed. + +**/ +UINT64 +EFIAPI +AsmFc ( + IN UINT64 Address + ); + + +/** + Executes an FC.I instruction. + Executes an FC.I instruction on the cache line specified by Address. + The cache line size affected is at least 32-bytes (aligned on a 32-byte boundary). + An implementation may flush a larger region. This function is only available on Itanium processors. + + @param Address The Address of cache line to be flushed. + + @return The address of the FC.I instruction executed. + +**/ +UINT64 +EFIAPI +AsmFci ( + IN UINT64 Address + ); + + +/** + Reads the current value of a Processor Identifier Register (CPUID). + + Reads and returns the current value of Processor Identifier Register specified by Index. + The Index of largest implemented CPUID (One less than the number of implemented CPUID + registers) is determined by CPUID [3] bits {7:0}. + No parameter checking is performed on Index. If the Index value is beyond the + implemented CPUID register range, a Reserved Register/Field fault may occur. The caller + must either guarantee that Index is valid, or the caller must set up fault handlers to + catch the faults. This function is only available on Itanium processors. + + @param Index The 8-bit Processor Identifier Register index to read. + + @return The current value of Processor Identifier Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadCpuid ( + IN UINT8 Index + ); + + +/** + Reads the current value of 64-bit Processor Status Register (PSR). + This function is only available on Itanium processors. + + @return The current value of PSR. + +**/ +UINT64 +EFIAPI +AsmReadPsr ( + VOID + ); + + +/** + Writes the current value of 64-bit Processor Status Register (PSR). + + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of PSR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PSR. + + @return The 64-bit value written to the PSR. + +**/ +UINT64 +EFIAPI +AsmWritePsr ( + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Kernel Register #0 (KR0). + + Reads and returns the current value of KR0. + This function is only available on Itanium processors. + + @return The current value of KR0. + +**/ +UINT64 +EFIAPI +AsmReadKr0 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #1 (KR1). + + Reads and returns the current value of KR1. + This function is only available on Itanium processors. + + @return The current value of KR1. + +**/ +UINT64 +EFIAPI +AsmReadKr1 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #2 (KR2). + + Reads and returns the current value of KR2. + This function is only available on Itanium processors. + + @return The current value of KR2. + +**/ +UINT64 +EFIAPI +AsmReadKr2 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #3 (KR3). + + Reads and returns the current value of KR3. + This function is only available on Itanium processors. + + @return The current value of KR3. + +**/ +UINT64 +EFIAPI +AsmReadKr3 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #4 (KR4). + + Reads and returns the current value of KR4. + This function is only available on Itanium processors. + + @return The current value of KR4. + +**/ +UINT64 +EFIAPI +AsmReadKr4 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #5 (KR5). + + Reads and returns the current value of KR5. + This function is only available on Itanium processors. + + @return The current value of KR5. + +**/ +UINT64 +EFIAPI +AsmReadKr5 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #6 (KR6). + + Reads and returns the current value of KR6. + This function is only available on Itanium processors. + + @return The current value of KR6. + +**/ +UINT64 +EFIAPI +AsmReadKr6 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #7 (KR7). + + Reads and returns the current value of KR7. + This function is only available on Itanium processors. + + @return The current value of KR7. + +**/ +UINT64 +EFIAPI +AsmReadKr7 ( + VOID + ); + + +/** + Write the current value of 64-bit Kernel Register #0 (KR0). + + Writes the current value of KR0. The 64-bit value written to + the KR0 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR0. + + @return The 64-bit value written to the KR0. + +**/ +UINT64 +EFIAPI +AsmWriteKr0 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #1 (KR1). + + Writes the current value of KR1. The 64-bit value written to + the KR1 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR1. + + @return The 64-bit value written to the KR1. + +**/ +UINT64 +EFIAPI +AsmWriteKr1 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #2 (KR2). + + Writes the current value of KR2. The 64-bit value written to + the KR2 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR2. + + @return The 64-bit value written to the KR2. + +**/ +UINT64 +EFIAPI +AsmWriteKr2 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #3 (KR3). + + Writes the current value of KR3. The 64-bit value written to + the KR3 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR3. + + @return The 64-bit value written to the KR3. + +**/ +UINT64 +EFIAPI +AsmWriteKr3 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #4 (KR4). + + Writes the current value of KR4. The 64-bit value written to + the KR4 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR4. + + @return The 64-bit value written to the KR4. + +**/ +UINT64 +EFIAPI +AsmWriteKr4 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #5 (KR5). + + Writes the current value of KR5. The 64-bit value written to + the KR5 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR5. + + @return The 64-bit value written to the KR5. + +**/ +UINT64 +EFIAPI +AsmWriteKr5 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #6 (KR6). + + Writes the current value of KR6. The 64-bit value written to + the KR6 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR6. + + @return The 64-bit value written to the KR6. + +**/ +UINT64 +EFIAPI +AsmWriteKr6 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #7 (KR7). + + Writes the current value of KR7. The 64-bit value written to + the KR7 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR7. + + @return The 64-bit value written to the KR7. + +**/ +UINT64 +EFIAPI +AsmWriteKr7 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Interval Timer Counter Register (ITC). + + Reads and returns the current value of ITC. + This function is only available on Itanium processors. + + @return The current value of ITC. + +**/ +UINT64 +EFIAPI +AsmReadItc ( + VOID + ); + + +/** + Reads the current value of Interval Timer Vector Register (ITV). + + Reads and returns the current value of ITV. + This function is only available on Itanium processors. + + @return The current value of ITV. + +**/ +UINT64 +EFIAPI +AsmReadItv ( + VOID + ); + + +/** + Reads the current value of Interval Timer Match Register (ITM). + + Reads and returns the current value of ITM. + This function is only available on Itanium processors. + + @return The current value of ITM. +**/ +UINT64 +EFIAPI +AsmReadItm ( + VOID + ); + + +/** + Writes the current value of 64-bit Interval Timer Counter Register (ITC). + + Writes the current value of ITC. The 64-bit value written to the ITC is returned. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITC. + + @return The 64-bit value written to the ITC. + +**/ +UINT64 +EFIAPI +AsmWriteItc ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interval Timer Match Register (ITM). + + Writes the current value of ITM. The 64-bit value written to the ITM is returned. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITM. + + @return The 64-bit value written to the ITM. + +**/ +UINT64 +EFIAPI +AsmWriteItm ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interval Timer Vector Register (ITV). + + Writes the current value of ITV. The 64-bit value written to the ITV is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of ITV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITV. + + @return The 64-bit value written to the ITV. + +**/ +UINT64 +EFIAPI +AsmWriteItv ( + IN UINT64 Value + ); + + +/** + Reads the current value of Default Control Register (DCR). + + Reads and returns the current value of DCR. This function is only available on Itanium processors. + + @return The current value of DCR. + +**/ +UINT64 +EFIAPI +AsmReadDcr ( + VOID + ); + + +/** + Reads the current value of Interruption Vector Address Register (IVA). + + Reads and returns the current value of IVA. This function is only available on Itanium processors. + + @return The current value of IVA. +**/ +UINT64 +EFIAPI +AsmReadIva ( + VOID + ); + + +/** + Reads the current value of Page Table Address Register (PTA). + + Reads and returns the current value of PTA. This function is only available on Itanium processors. + + @return The current value of PTA. + +**/ +UINT64 +EFIAPI +AsmReadPta ( + VOID + ); + + +/** + Writes the current value of 64-bit Default Control Register (DCR). + + Writes the current value of DCR. The 64-bit value written to the DCR is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of DCR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to DCR. + + @return The 64-bit value written to the DCR. + +**/ +UINT64 +EFIAPI +AsmWriteDcr ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interruption Vector Address Register (IVA). + + Writes the current value of IVA. The 64-bit value written to the IVA is returned. + The size of vector table is 32 K bytes and is 32 K bytes aligned + the low 15 bits of Value is ignored when written. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to IVA. + + @return The 64-bit value written to the IVA. + +**/ +UINT64 +EFIAPI +AsmWriteIva ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Page Table Address Register (PTA). + + Writes the current value of PTA. The 64-bit value written to the PTA is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of DCR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PTA. + + @return The 64-bit value written to the PTA. +**/ +UINT64 +EFIAPI +AsmWritePta ( + IN UINT64 Value + ); + + +/** + Reads the current value of Local Interrupt ID Register (LID). + + Reads and returns the current value of LID. This function is only available on Itanium processors. + + @return The current value of LID. + +**/ +UINT64 +EFIAPI +AsmReadLid ( + VOID + ); + + +/** + Reads the current value of External Interrupt Vector Register (IVR). + + Reads and returns the current value of IVR. This function is only available on Itanium processors. + + @return The current value of IVR. + +**/ +UINT64 +EFIAPI +AsmReadIvr ( + VOID + ); + + +/** + Reads the current value of Task Priority Register (TPR). + + Reads and returns the current value of TPR. This function is only available on Itanium processors. + + @return The current value of TPR. + +**/ +UINT64 +EFIAPI +AsmReadTpr ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #0 (IRR0). + + Reads and returns the current value of IRR0. This function is only available on Itanium processors. + + @return The current value of IRR0. + +**/ +UINT64 +EFIAPI +AsmReadIrr0 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #1 (IRR1). + + Reads and returns the current value of IRR1. This function is only available on Itanium processors. + + @return The current value of IRR1. + +**/ +UINT64 +EFIAPI +AsmReadIrr1 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #2 (IRR2). + + Reads and returns the current value of IRR2. This function is only available on Itanium processors. + + @return The current value of IRR2. + +**/ +UINT64 +EFIAPI +AsmReadIrr2 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #3 (IRR3). + + Reads and returns the current value of IRR3. This function is only available on Itanium processors. + + @return The current value of IRR3. + +**/ +UINT64 +EFIAPI +AsmReadIrr3 ( + VOID + ); + + +/** + Reads the current value of Performance Monitor Vector Register (PMV). + + Reads and returns the current value of PMV. This function is only available on Itanium processors. + + @return The current value of PMV. + +**/ +UINT64 +EFIAPI +AsmReadPmv ( + VOID + ); + + +/** + Reads the current value of Corrected Machine Check Vector Register (CMCV). + + Reads and returns the current value of CMCV. This function is only available on Itanium processors. + + @return The current value of CMCV. + +**/ +UINT64 +EFIAPI +AsmReadCmcv ( + VOID + ); + + +/** + Reads the current value of Local Redirection Register #0 (LRR0). + + Reads and returns the current value of LRR0. This function is only available on Itanium processors. + + @return The current value of LRR0. + +**/ +UINT64 +EFIAPI +AsmReadLrr0 ( + VOID + ); + + +/** + Reads the current value of Local Redirection Register #1 (LRR1). + + Reads and returns the current value of LRR1. This function is only available on Itanium processors. + + @return The current value of LRR1. + +**/ +UINT64 +EFIAPI +AsmReadLrr1 ( + VOID + ); + + +/** + Writes the current value of 64-bit Page Local Interrupt ID Register (LID). + + Writes the current value of LID. The 64-bit value written to the LID is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of LID must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LID. + + @return The 64-bit value written to the LID. + +**/ +UINT64 +EFIAPI +AsmWriteLid ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Task Priority Register (TPR). + + Writes the current value of TPR. The 64-bit value written to the TPR is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of TPR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to TPR. + + @return The 64-bit value written to the TPR. + +**/ +UINT64 +EFIAPI +AsmWriteTpr ( + IN UINT64 Value + ); + + +/** + Performs a write operation on End OF External Interrupt Register (EOI). + + Writes a value of 0 to the EOI Register. This function is only available on Itanium processors. + +**/ +VOID +EFIAPI +AsmWriteEoi ( + VOID + ); + + +/** + Writes the current value of 64-bit Performance Monitor Vector Register (PMV). + + Writes the current value of PMV. The 64-bit value written to the PMV is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of PMV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PMV. + + @return The 64-bit value written to the PMV. + +**/ +UINT64 +EFIAPI +AsmWritePmv ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Corrected Machine Check Vector Register (CMCV). + + Writes the current value of CMCV. The 64-bit value written to the CMCV is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of CMCV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to CMCV. + + @return The 64-bit value written to the CMCV. + +**/ +UINT64 +EFIAPI +AsmWriteCmcv ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Local Redirection Register #0 (LRR0). + + Writes the current value of LRR0. The 64-bit value written to the LRR0 is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of LRR0 must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LRR0. + + @return The 64-bit value written to the LRR0. + +**/ +UINT64 +EFIAPI +AsmWriteLrr0 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Local Redirection Register #1 (LRR1). + + Writes the current value of LRR1. The 64-bit value written to the LRR1 is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of LRR1 must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LRR1. + + @return The 64-bit value written to the LRR1. + +**/ +UINT64 +EFIAPI +AsmWriteLrr1 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Instruction Breakpoint Register (IBR). + + The Instruction Breakpoint Registers are used in pairs. The even numbered + registers contain breakpoint addresses, and the odd numbered registers contain + breakpoint mask conditions. At least four instruction registers pairs are implemented + on all processor models. Implemented registers are contiguous starting with + register 0. No parameter checking is performed on Index, and if the Index value + is beyond the implemented IBR register range, a Reserved Register/Field fault may + occur. The caller must either guarantee that Index is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Instruction Breakpoint Register index to read. + + @return The current value of Instruction Breakpoint Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadIbr ( + IN UINT8 Index + ); + + +/** + Reads the current value of Data Breakpoint Register (DBR). + + The Data Breakpoint Registers are used in pairs. The even numbered registers + contain breakpoint addresses, and odd numbered registers contain breakpoint + mask conditions. At least four data registers pairs are implemented on all processor + models. Implemented registers are contiguous starting with register 0. + No parameter checking is performed on Index. If the Index value is beyond + the implemented DBR register range, a Reserved Register/Field fault may occur. + The caller must either guarantee that Index is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Data Breakpoint Register index to read. + + @return The current value of Data Breakpoint Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadDbr ( + IN UINT8 Index + ); + + +/** + Reads the current value of Performance Monitor Configuration Register (PMC). + + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow + status registers (PMC [0]... PMC [3]). Processor implementations may provide + additional implementation-dependent PMC and PMD to increase the number of + 'generic' performance counters (PMC/PMD pairs). The remainder of PMC and PMD + register set is implementation dependent. No parameter checking is performed + on Index. If the Index value is beyond the implemented PMC register range, + zero value will be returned. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Configuration Register index to read. + + @return The current value of Performance Monitor Configuration Register + specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT8 Index + ); + + +/** + Reads the current value of Performance Monitor Data Register (PMD). + + All processor implementations provide at least 4 performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and 4 performance monitor counter + overflow status registers (PMC [0]... PMC [3]). Processor implementations may + provide additional implementation-dependent PMC and PMD to increase the number + of 'generic' performance counters (PMC/PMD pairs). The remainder of PMC and PMD + register set is implementation dependent. No parameter checking is performed + on Index. If the Index value is beyond the implemented PMD register range, + zero value will be returned. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Data Register index to read. + + @return The current value of Performance Monitor Data Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmd ( + IN UINT8 Index + ); + + +/** + Writes the current value of 64-bit Instruction Breakpoint Register (IBR). + + Writes current value of Instruction Breakpoint Register specified by Index. + The Instruction Breakpoint Registers are used in pairs. The even numbered + registers contain breakpoint addresses, and odd numbered registers contain + breakpoint mask conditions. At least four instruction registers pairs are implemented + on all processor models. Implemented registers are contiguous starting with + register 0. No parameter checking is performed on Index. If the Index value + is beyond the implemented IBR register range, a Reserved Register/Field fault may + occur. The caller must either guarantee that Index is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Instruction Breakpoint Register index to write. + @param Value The 64-bit value to write to IBR. + + @return The 64-bit value written to the IBR. + +**/ +UINT64 +EFIAPI +AsmWriteIbr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Data Breakpoint Register (DBR). + + Writes current value of Data Breakpoint Register specified by Index. + The Data Breakpoint Registers are used in pairs. The even numbered registers + contain breakpoint addresses, and odd numbered registers contain breakpoint + mask conditions. At least four data registers pairs are implemented on all processor + models. Implemented registers are contiguous starting with register 0. No parameter + checking is performed on Index. If the Index value is beyond the implemented + DBR register range, a Reserved Register/Field fault may occur. The caller must + either guarantee that Index is valid, or the caller must set up fault handlers to + catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Data Breakpoint Register index to write. + @param Value The 64-bit value to write to DBR. + + @return The 64-bit value written to the DBR. + +**/ +UINT64 +EFIAPI +AsmWriteDbr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Performance Monitor Configuration Register (PMC). + + Writes current value of Performance Monitor Configuration Register specified by Index. + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow status + registers (PMC [0]... PMC [3]). Processor implementations may provide additional + implementation-dependent PMC and PMD to increase the number of 'generic' performance + counters (PMC/PMD pairs). The remainder of PMC and PMD register set is implementation + dependent. No parameter checking is performed on Index. If the Index value is + beyond the implemented PMC register range, the write is ignored. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Configuration Register index to write. + @param Value The 64-bit value to write to PMC. + + @return The 64-bit value written to the PMC. + +**/ +UINT64 +EFIAPI +AsmWritePmc ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Performance Monitor Data Register (PMD). + + Writes current value of Performance Monitor Data Register specified by Index. + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow + status registers (PMC [0]... PMC [3]). Processor implementations may provide + additional implementation-dependent PMC and PMD to increase the number of 'generic' + performance counters (PMC/PMD pairs). The remainder of PMC and PMD register set + is implementation dependent. No parameter checking is performed on Index. If the + Index value is beyond the implemented PMD register range, the write is ignored. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Data Register index to write. + @param Value The 64-bit value to write to PMD. + + @return The 64-bit value written to the PMD. + +**/ +UINT64 +EFIAPI +AsmWritePmd ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Global Pointer (GP). + + Reads and returns the current value of GP. + This function is only available on Itanium processors. + + @return The current value of GP. + +**/ +UINT64 +EFIAPI +AsmReadGp ( + VOID + ); + + +/** + Write the current value of 64-bit Global Pointer (GP). + + Writes the current value of GP. The 64-bit value written to the GP is returned. + No parameter checking is performed on Value. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to GP. + + @return The 64-bit value written to the GP. + +**/ +UINT64 +EFIAPI +AsmWriteGp ( + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Stack Pointer (SP). + + Reads and returns the current value of SP. + This function is only available on Itanium processors. + + @return The current value of SP. + +**/ +UINT64 +EFIAPI +AsmReadSp ( + VOID + ); + + +/// +/// Valid Index value for AsmReadControlRegister(). +/// +#define IPF_CONTROL_REGISTER_DCR 0 +#define IPF_CONTROL_REGISTER_ITM 1 +#define IPF_CONTROL_REGISTER_IVA 2 +#define IPF_CONTROL_REGISTER_PTA 8 +#define IPF_CONTROL_REGISTER_IPSR 16 +#define IPF_CONTROL_REGISTER_ISR 17 +#define IPF_CONTROL_REGISTER_IIP 19 +#define IPF_CONTROL_REGISTER_IFA 20 +#define IPF_CONTROL_REGISTER_ITIR 21 +#define IPF_CONTROL_REGISTER_IIPA 22 +#define IPF_CONTROL_REGISTER_IFS 23 +#define IPF_CONTROL_REGISTER_IIM 24 +#define IPF_CONTROL_REGISTER_IHA 25 +#define IPF_CONTROL_REGISTER_LID 64 +#define IPF_CONTROL_REGISTER_IVR 65 +#define IPF_CONTROL_REGISTER_TPR 66 +#define IPF_CONTROL_REGISTER_EOI 67 +#define IPF_CONTROL_REGISTER_IRR0 68 +#define IPF_CONTROL_REGISTER_IRR1 69 +#define IPF_CONTROL_REGISTER_IRR2 70 +#define IPF_CONTROL_REGISTER_IRR3 71 +#define IPF_CONTROL_REGISTER_ITV 72 +#define IPF_CONTROL_REGISTER_PMV 73 +#define IPF_CONTROL_REGISTER_CMCV 74 +#define IPF_CONTROL_REGISTER_LRR0 80 +#define IPF_CONTROL_REGISTER_LRR1 81 + +/** + Reads a 64-bit control register. + + Reads and returns the control register specified by Index. The valid Index valued + are defined above in "Related Definitions". + If Index is invalid then 0xFFFFFFFFFFFFFFFF is returned. This function is only + available on Itanium processors. + + @param Index The index of the control register to read. + + @return The control register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadControlRegister ( + IN UINT64 Index + ); + + +/// +/// Valid Index value for AsmReadApplicationRegister(). +/// +#define IPF_APPLICATION_REGISTER_K0 0 +#define IPF_APPLICATION_REGISTER_K1 1 +#define IPF_APPLICATION_REGISTER_K2 2 +#define IPF_APPLICATION_REGISTER_K3 3 +#define IPF_APPLICATION_REGISTER_K4 4 +#define IPF_APPLICATION_REGISTER_K5 5 +#define IPF_APPLICATION_REGISTER_K6 6 +#define IPF_APPLICATION_REGISTER_K7 7 +#define IPF_APPLICATION_REGISTER_RSC 16 +#define IPF_APPLICATION_REGISTER_BSP 17 +#define IPF_APPLICATION_REGISTER_BSPSTORE 18 +#define IPF_APPLICATION_REGISTER_RNAT 19 +#define IPF_APPLICATION_REGISTER_FCR 21 +#define IPF_APPLICATION_REGISTER_EFLAG 24 +#define IPF_APPLICATION_REGISTER_CSD 25 +#define IPF_APPLICATION_REGISTER_SSD 26 +#define IPF_APPLICATION_REGISTER_CFLG 27 +#define IPF_APPLICATION_REGISTER_FSR 28 +#define IPF_APPLICATION_REGISTER_FIR 29 +#define IPF_APPLICATION_REGISTER_FDR 30 +#define IPF_APPLICATION_REGISTER_CCV 32 +#define IPF_APPLICATION_REGISTER_UNAT 36 +#define IPF_APPLICATION_REGISTER_FPSR 40 +#define IPF_APPLICATION_REGISTER_ITC 44 +#define IPF_APPLICATION_REGISTER_PFS 64 +#define IPF_APPLICATION_REGISTER_LC 65 +#define IPF_APPLICATION_REGISTER_EC 66 + +/** + Reads a 64-bit application register. + + Reads and returns the application register specified by Index. The valid Index + valued are defined above in "Related Definitions". + If Index is invalid then 0xFFFFFFFFFFFFFFFF is returned. This function is only + available on Itanium processors. + + @param Index The index of the application register to read. + + @return The application register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadApplicationRegister ( + IN UINT64 Index + ); + + +/** + Reads the current value of a Machine Specific Register (MSR). + + Reads and returns the current value of the Machine Specific Register specified by Index. No + parameter checking is performed on Index, and if the Index value is beyond the implemented MSR + register range, a Reserved Register/Field fault may occur. The caller must either guarantee that + Index is valid, or the caller must set up fault handlers to catch the faults. This function is + only available on Itanium processors. + + @param Index The 8-bit Machine Specific Register index to read. + + @return The current value of the Machine Specific Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr ( + IN UINT8 Index + ); + + +/** + Writes the current value of a Machine Specific Register (MSR). + + Writes Value to the Machine Specific Register specified by Index. Value is returned. No + parameter checking is performed on Index, and if the Index value is beyond the implemented MSR + register range, a Reserved Register/Field fault may occur. The caller must either guarantee that + Index is valid, or the caller must set up fault handlers to catch the faults. This function is + only available on Itanium processors. + + @param Index The 8-bit Machine Specific Register index to write. + @param Value The 64-bit value to write to the Machine Specific Register. + + @return The 64-bit value to write to the Machine Specific Register. + +**/ +UINT64 +EFIAPI +AsmWriteMsr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Determines if the CPU is currently executing in virtual, physical, or mixed mode. + + Determines the current execution mode of the CPU. + If the CPU is in virtual mode(PSR.RT=1, PSR.DT=1, PSR.IT=1), then 1 is returned. + If the CPU is in physical mode(PSR.RT=0, PSR.DT=0, PSR.IT=0), then 0 is returned. + If the CPU is not in physical mode or virtual mode, then it is in mixed mode, + and -1 is returned. + This function is only available on Itanium processors. + + @retval 1 The CPU is in virtual mode. + @retval 0 The CPU is in physical mode. + @retval -1 The CPU is in mixed mode. + +**/ +INT64 +EFIAPI +AsmCpuVirtual ( + VOID + ); + + +/** + Makes a PAL procedure call. + + This is a wrapper function to make a PAL procedure call. Based on the Index + value this API will make static or stacked PAL call. The following table + describes the usage of PAL Procedure Index Assignment. Architected procedures + may be designated as required or optional. If a PAL procedure is specified + as optional, a unique return code of 0xFFFFFFFFFFFFFFFF is returned in the + Status field of the PAL_CALL_RETURN structure. + This indicates that the procedure is not present in this PAL implementation. + It is the caller's responsibility to check for this return code after calling + any optional PAL procedure. + No parameter checking is performed on the 5 input parameters, but there are + some common rules that the caller should follow when making a PAL call. Any + address passed to PAL as buffers for return parameters must be 8-byte aligned. + Unaligned addresses may cause undefined results. For those parameters defined + as reserved or some fields defined as reserved must be zero filled or the invalid + argument return value may be returned or undefined result may occur during the + execution of the procedure. If the PalEntryPoint does not point to a valid + PAL entry point then the system behavior is undefined. This function is only + available on Itanium processors. + + @param PalEntryPoint The PAL procedure calls entry point. + @param Index The PAL procedure Index number. + @param Arg2 The 2nd parameter for PAL procedure calls. + @param Arg3 The 3rd parameter for PAL procedure calls. + @param Arg4 The 4th parameter for PAL procedure calls. + + @return structure returned from the PAL Call procedure, including the status and return value. + +**/ +PAL_CALL_RETURN +EFIAPI +AsmPalCall ( + IN UINT64 PalEntryPoint, + IN UINT64 Index, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); +#endif + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +/// +/// IA32 and x64 Specific Functions. +/// Byte packed structure for 16-bit Real Mode EFLAGS. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + } Bits; + UINT16 Uint16; +} IA32_FLAGS16; + +/// +/// Byte packed structure for EFLAGS/RFLAGS. +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + UINT32 RF:1; ///< Resume Flag. + UINT32 VM:1; ///< Virtual 8086 Mode. + UINT32 AC:1; ///< Alignment Check. + UINT32 VIF:1; ///< Virtual Interrupt Flag. + UINT32 VIP:1; ///< Virtual Interrupt Pending. + UINT32 ID:1; ///< ID Flag. + UINT32 Reserved_4:10; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_EFLAGS32; + +/// +/// Byte packed structure for Control Register 0 (CR0). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 PE:1; ///< Protection Enable. + UINT32 MP:1; ///< Monitor Coprocessor. + UINT32 EM:1; ///< Emulation. + UINT32 TS:1; ///< Task Switched. + UINT32 ET:1; ///< Extension Type. + UINT32 NE:1; ///< Numeric Error. + UINT32 Reserved_0:10; ///< Reserved. + UINT32 WP:1; ///< Write Protect. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AM:1; ///< Alignment Mask. + UINT32 Reserved_2:10; ///< Reserved. + UINT32 NW:1; ///< Mot Write-through. + UINT32 CD:1; ///< Cache Disable. + UINT32 PG:1; ///< Paging. + } Bits; + UINTN UintN; +} IA32_CR0; + +/// +/// Byte packed structure for Control Register 4 (CR4). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 VME:1; ///< Virtual-8086 Mode Extensions. + UINT32 PVI:1; ///< Protected-Mode Virtual Interrupts. + UINT32 TSD:1; ///< Time Stamp Disable. + UINT32 DE:1; ///< Debugging Extensions. + UINT32 PSE:1; ///< Page Size Extensions. + UINT32 PAE:1; ///< Physical Address Extension. + UINT32 MCE:1; ///< Machine Check Enable. + UINT32 PGE:1; ///< Page Global Enable. + UINT32 PCE:1; ///< Performance Monitoring Counter + ///< Enable. + UINT32 OSFXSR:1; ///< Operating System Support for + ///< FXSAVE and FXRSTOR instructions + UINT32 OSXMMEXCPT:1; ///< Operating System Support for + ///< Unmasked SIMD Floating Point + ///< Exceptions. + UINT32 Reserved_0:2; ///< Reserved. + UINT32 VMXE:1; ///< VMX Enable + UINT32 Reserved_1:18; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_CR4; + +/// +/// Byte packed structure for a segment descriptor in a GDT/LDT. +/// +typedef union { + struct { + UINT32 LimitLow:16; + UINT32 BaseLow:16; + UINT32 BaseMid:8; + UINT32 Type:4; + UINT32 S:1; + UINT32 DPL:2; + UINT32 P:1; + UINT32 LimitHigh:4; + UINT32 AVL:1; + UINT32 L:1; + UINT32 DB:1; + UINT32 G:1; + UINT32 BaseHigh:8; + } Bits; + UINT64 Uint64; +} IA32_SEGMENT_DESCRIPTOR; + +/// +/// Byte packed structure for an IDTR, GDTR, LDTR descriptor. +/// +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; +} IA32_DESCRIPTOR; +#pragma pack () + +#define IA32_IDT_GATE_TYPE_TASK 0x85 +#define IA32_IDT_GATE_TYPE_INTERRUPT_16 0x86 +#define IA32_IDT_GATE_TYPE_TRAP_16 0x87 +#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E +#define IA32_IDT_GATE_TYPE_TRAP_32 0x8F + + +#if defined (MDE_CPU_IA32) +/// +/// Byte packed structure for an IA-32 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + } Bits; + UINT64 Uint64; +} IA32_IDT_GATE_DESCRIPTOR; + +#endif + +#if defined (MDE_CPU_X64) +/// +/// Byte packed structure for an x64 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + UINT32 OffsetUpper:32; ///< Offset bits 63..32. + UINT32 Reserved_1:32; ///< Reserved. + } Bits; + struct { + UINT64 Uint64; + UINT64 Uint64_1; + } Uint128; +} IA32_IDT_GATE_DESCRIPTOR; + +#endif + +/// +/// Byte packed structure for an FP/SSE/SSE2 context. +/// +typedef struct { + UINT8 Buffer[512]; +} IA32_FX_BUFFER; + +/// +/// Structures for the 16-bit real mode thunks. +/// +typedef struct { + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT8 BL; + UINT8 BH; + UINT16 Reserved5; + UINT8 DL; + UINT8 DH; + UINT16 Reserved6; + UINT8 CL; + UINT8 CH; + UINT16 Reserved7; + UINT8 AL; + UINT8 AH; + UINT16 Reserved8; +} IA32_BYTE_REGS; + +typedef struct { + UINT16 DI; + UINT16 Reserved1; + UINT16 SI; + UINT16 Reserved2; + UINT16 BP; + UINT16 Reserved3; + UINT16 SP; + UINT16 Reserved4; + UINT16 BX; + UINT16 Reserved5; + UINT16 DX; + UINT16 Reserved6; + UINT16 CX; + UINT16 Reserved7; + UINT16 AX; + UINT16 Reserved8; +} IA32_WORD_REGS; + +typedef struct { + UINT32 EDI; + UINT32 ESI; + UINT32 EBP; + UINT32 ESP; + UINT32 EBX; + UINT32 EDX; + UINT32 ECX; + UINT32 EAX; + UINT16 DS; + UINT16 ES; + UINT16 FS; + UINT16 GS; + IA32_EFLAGS32 EFLAGS; + UINT32 Eip; + UINT16 CS; + UINT16 SS; +} IA32_DWORD_REGS; + +typedef union { + IA32_DWORD_REGS E; + IA32_WORD_REGS X; + IA32_BYTE_REGS H; +} IA32_REGISTER_SET; + +/// +/// Byte packed structure for an 16-bit real mode thunks. +/// +typedef struct { + IA32_REGISTER_SET *RealModeState; + VOID *RealModeBuffer; + UINT32 RealModeBufferSize; + UINT32 ThunkAttributes; +} THUNK_CONTEXT; + +#define THUNK_ATTRIBUTE_BIG_REAL_MODE 0x00000001 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 0x00000002 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL 0x00000004 + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and x64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ); + + +/** + Retrieves CPUID information using an extended leaf identifier. + + Executes the CPUID instruction with EAX set to the value specified by Index + and ECX set to the value specified by SubIndex. This function always returns + Index. This function is only available on IA-32 and x64. + + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + + @param Index The 32-bit value to load into EAX prior to invoking the + CPUID instruction. + @param SubIndex The 32-bit value to load into ECX prior to invoking the + CPUID instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ); + + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmDisableCache ( + VOID + ); + + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmEnableCache ( + VOID + ); + + +/** + Returns the lower 32-bits of a Machine Specific Register(MSR). + + Reads and returns the lower 32-bits of the MSR specified by Index. + No parameter checking is performed on Index, and some Index values may cause + CPU exceptions. The caller must either guarantee that Index is valid, or the + caller must set up exception handlers to catch the exceptions. This function + is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The lower 32 bits of the MSR identified by Index. + +**/ +UINT32 +EFIAPI +AsmReadMsr32 ( + IN UINT32 Index + ); + + +/** + Writes a 32-bit value to a Machine Specific Register(MSR), and returns the value. + The upper 32-bits of the MSR are set to zero. + + Writes the 32-bit value specified by Value to the MSR specified by Index. The + upper 32-bits of the MSR write are set to zero. The 32-bit value written to + the MSR is returned. No parameter checking is performed on Index or Value, + and some of these may cause CPU exceptions. The caller must either guarantee + that Index and Value are valid, or the caller must establish proper exception + handlers. This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 32-bit value to write to the MSR. + + @return Value + +**/ +UINT32 +EFIAPI +AsmWriteMsr32 ( + IN UINT32 Index, + IN UINT32 Value + ); + + +/** + Reads a 64-bit MSR, performs a bitwise OR on the lower 32-bits, and + writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the lower 32-bits of the read result and the value specified by + OrData, and writes the result to the 64-bit MSR specified by Index. The lower + 32-bits of the value written to the MSR is returned. No parameter checking is + performed on Index or OrData, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and OrData are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrOr32 ( + IN UINT32 Index, + IN UINT32 OrData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND on the lower 32-bits, and writes + the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData, and + writes the result to the 64-bit MSR specified by Index. The lower 32-bits of + the value written to the MSR is returned. No parameter checking is performed + on Index or AndData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index and AndData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAnd32 ( + IN UINT32 Index, + IN UINT32 AndData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise OR + on the lower 32-bits, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData + preserving the upper 32-bits, performs a bitwise OR between the + result of the AND operation and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Address. The lower 32-bits of the value + written to the MSR is returned. No parameter checking is performed on Index, + AndData, or OrData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index, AndData, and OrData are valid, or the + caller must establish proper exception handlers. This function is only + available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAndThenOr32 ( + IN UINT32 Index, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Reads a bit field of an MSR. + + Reads the bit field in the lower 32-bits of a 64-bit MSR. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. The caller must either guarantee that Index is valid, or the caller + must set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read from the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldRead32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in the lower 32-bits of a 64-bit MSR. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination MSR are preserved. The lower 32-bits of the MSR written is + returned. The caller must either guarantee that Index and the data written + is valid, or the caller must set up exception handlers to catch the exceptions. + This function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldWrite32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The lower 32-bits of the value + written to the MSR are returned. Extra left bits in OrData are stripped. The + caller must either guarantee that Index and the data written is valid, or + the caller must set up exception handlers to catch the exceptions. This + function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The lower 32-bits of the value written to the + MSR are returned. Extra left bits in AndData are stripped. The caller must + either guarantee that Index and the data written is valid, or the caller must + set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAnd32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by a + bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + lower 32-bits of the value written to the MSR are returned. Extra left bits + in both AndData and OrData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAndThenOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ); + + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ); + + +/** + Reads a 64-bit MSR, performs a bitwise OR, and writes the result + back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. No parameter checking is performed on Index or OrData, and some of + these may cause CPU exceptions. The caller must either guarantee that Index + and OrData are valid, or the caller must establish proper exception handlers. + This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND, and writes the result back to the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by OrData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. No + parameter checking is performed on Index or OrData, and some of these may + cause CPU exceptions. The caller must either guarantee that Index and OrData + are valid, or the caller must establish proper exception handlers. This + function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between read + result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit MSR specified by Index. The value written + to the MSR is returned. No parameter checking is performed on Index, AndData, + or OrData, and some of these may cause CPU exceptions. The caller must either + guarantee that Index, AndData, and OrData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ); + + +/** + Reads a bit field of an MSR. + + Reads the bit field in the 64-bit MSR. The bit field is specified by the + StartBit and the EndBit. The value of the bit field is returned. The caller + must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read from the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldRead64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in a 64-bit MSR. The bit field is specified by + the StartBit and the EndBit. All other bits in the destination MSR are + preserved. The MSR written is returned. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. Extra left bits in OrData are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. + Extra left bits in AndData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAnd64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by + a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + value written to the MSR is returned. Extra left bits in both AndData and + OrData are stripped. The caller must either guarantee that Index and the data + written is valid, or the caller must set up exception handlers to catch the + exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAndThenOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and x64. This returns a 32-bit value on IA-32 and a + 64-bit value on x64. + + @return EFLAGS on IA-32 or RFLAGS on x64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ); + + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ); + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ); + + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ); + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ); + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ); + + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ); + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ); + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ); + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ); + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ); + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ); + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ); + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ); + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ); + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ); + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ); + + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ); + + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ); + + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ); + + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ); + + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ); + + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ); + + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ); + + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ); + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ); + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ); + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ); + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ); + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ); + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ); + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ); + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ); + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ); + + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ); + + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ); + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and x64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ); + + +/** + Writes the current Local Descriptor Table Register (LDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and x64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ); + + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + OUT IA32_FX_BUFFER *Buffer + ); + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + If Buffer was not saved with AsmFxSave(), then ASSERT(). + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and x64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and x64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and x64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and x64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and x64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and x64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and x64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and x64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ); + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and x64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ); + + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and x64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ); + + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ); + + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ); + + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ); + + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ); + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and x64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress. +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ); + + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ); + + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ); + + +// +// 16-bit thunking services +// + +/** + Retrieves the properties for 16-bit thunk functions. + + Computes the size of the buffer and stack below 1MB required to use the + AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This + buffer size is returned in RealModeBufferSize, and the stack size is returned + in ExtraStackSize. If parameters are passed to the 16-bit real mode code, + then the actual minimum stack size is ExtraStackSize plus the maximum number + of bytes that need to be passed to the 16-bit real mode code. + + If RealModeBufferSize is NULL, then ASSERT(). + If ExtraStackSize is NULL, then ASSERT(). + + @param RealModeBufferSize A pointer to the size of the buffer below 1MB + required to use the 16-bit thunk functions. + @param ExtraStackSize A pointer to the extra size of stack below 1MB + that the 16-bit thunk functions require for + temporary storage in the transition to and from + 16-bit real mode. + +**/ +VOID +EFIAPI +AsmGetThunk16Properties ( + OUT UINT32 *RealModeBufferSize, + OUT UINT32 *ExtraStackSize + ); + + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is used. + This function must be called with interrupts disabled. + + The register state from the RealModeState field of ThunkContext is restored just prior + to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState, + which is used to set the interrupt state when a 16-bit real mode entry point is called. + Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState. + The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to + the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function. + The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction, + so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment + and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry + point must exit with a RETF instruction. The register state is captured into RealModeState immediately + after the RETF instruction is executed. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure + the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode. + This includes the base vectors, the interrupt masks, and the edge/level trigger mode. + + If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code + is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits. + + If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to + disable the A20 mask. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in + ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails, + then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in + ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then ASSERT(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + +#endif +#endif + + diff --git a/roms/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h b/roms/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h index 6c4f44b90..e007cab83 100644 --- a/roms/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h +++ b/roms/ipxe/src/include/ipxe/efi/Pi/PiDxeCis.h @@ -1,7 +1,7 @@ /** @file Include file matches things in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +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 @@ -11,7 +11,7 @@ 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 + PI Version 1.2 **/ @@ -371,7 +371,8 @@ EFI_STATUS 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. - + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. **/ typedef EFI_STATUS @@ -656,8 +657,10 @@ EFI_STATUS // // DXE Services Table // -#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL -#define DXE_SERVICES_REVISION ((1<<16) | (00)) +#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL +#define DXE_SPECIFICATION_MAJOR_REVISION 1 +#define DXE_SPECIFICATION_MINOR_REVISION 20 +#define DXE_SERVICES_REVISION ((DXE_SPECIFICATION_MAJOR_REVISION<<16) | (DXE_SPECIFICATION_MINOR_REVISION)) typedef struct { /// diff --git a/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h b/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h index 6909018bc..f6cf9574d 100644 --- a/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h +++ b/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareFile.h @@ -1,7 +1,7 @@ /** @file The firmware file related definitions in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +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 @@ -36,8 +36,7 @@ typedef union { /// /// 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. + /// checksum of the file data. /// 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 @@ -176,9 +175,18 @@ typedef struct { /// 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; + UINT32 ExtendedSize; } EFI_FFS_FILE_HEADER2; +#define IS_FFS_FILE2(FfsFileHeaderPtr) \ + (((((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Attributes) & FFS_ATTRIB_LARGE_FILE) == FFS_ATTRIB_LARGE_FILE) + +#define FFS_FILE_SIZE(FfsFileHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Size) & 0x00ffffff)) + +#define FFS_FILE2_SIZE(FfsFileHeaderPtr) \ + (((EFI_FFS_FILE_HEADER2 *) (UINTN) FfsFileHeaderPtr)->ExtendedSize) + typedef UINT8 EFI_SECTION_TYPE; /// @@ -473,8 +481,14 @@ typedef struct { CHAR16 VersionString[1]; } EFI_VERSION_SECTION2; +#define IS_SECTION2(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff) == 0x00ffffff) + #define SECTION_SIZE(SectionHeaderPtr) \ - ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff)) + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff)) + +#define SECTION2_SIZE(SectionHeaderPtr) \ + (((EFI_COMMON_SECTION_HEADER2 *) (UINTN) SectionHeaderPtr)->ExtendedSize) #pragma pack() diff --git a/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h b/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h index 813fab228..4863e146d 100644 --- a/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h +++ b/roms/ipxe/src/include/ipxe/efi/Pi/PiFirmwareVolume.h @@ -11,7 +11,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @par Revision Reference: - PI Version 1.2B + PI Version 1.2C **/ @@ -75,7 +75,7 @@ typedef UINT32 EFI_FVB_ATTRIBUTES_2; #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_512K 0x00130000 #define EFI_FVB2_ALIGNMENT_1M 0x00140000 #define EFI_FVB2_ALIGNMENT_2M 0x00150000 #define EFI_FVB2_ALIGNMENT_4M 0x00160000 @@ -207,13 +207,15 @@ typedef struct { /// /// An array of GUIDs, each GUID representing an OEM file type. /// - EFI_GUID Types[1]; + /// 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. +/// This extension header EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE provides a vendor specific +/// GUID FormatType type which includes a length and a successive series of data bytes. /// typedef struct { /// @@ -227,7 +229,8 @@ typedef struct { /// /// An arry of bytes of length Length. /// - UINT8 Data[1]; + /// UINT8 Data[1]; + /// } EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE; #endif diff --git a/roms/ipxe/src/include/ipxe/efi/Pi/PiHob.h b/roms/ipxe/src/include/ipxe/efi/Pi/PiHob.h index cd196cb30..c68ea3002 100644 --- a/roms/ipxe/src/include/ipxe/efi/Pi/PiHob.h +++ b/roms/ipxe/src/include/ipxe/efi/Pi/PiHob.h @@ -1,7 +1,7 @@ /** @file HOB related definitions in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +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 @@ -251,21 +251,21 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; // // These types can be ORed together as needed. // -// The first three enumerations describe settings +// The following attributes are used to describe settings // -#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 -#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 -#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 // -// The rest of the settings describe capabilities +// The rest of the attributes are used to 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 @@ -274,6 +274,9 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; #define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 #define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 #define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000 /// /// Describes the resource properties of all fixed, diff --git a/roms/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h b/roms/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h index 6133f00c4..4c720529f 100644 --- a/roms/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h +++ b/roms/ipxe/src/include/ipxe/efi/Pi/PiStatusCode.h @@ -22,7 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. FILE_LICENCE ( BSD3 ); // -// Required for IA32 and IPF defines for CPU exception types +// Required for IA32, X64, IPF, ARM and EBC defines for CPU exception types // #include <ipxe/efi/Protocol/DebugSupport.h> @@ -713,6 +713,9 @@ typedef struct { #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) +#define EFI_SOFTWARE_X64_EXCEPTION (EFI_SOFTWARE | 0x00130000) +#define EFI_SOFTWARE_ARM_EXCEPTION (EFI_SOFTWARE | 0x00140000) + ///@} /// @@ -753,7 +756,6 @@ typedef struct { /// /// 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) @@ -808,6 +810,14 @@ typedef struct { #define EFI_SW_RT_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) ///@} +// +// Software Class X64 Exception Subclass Progress Code definitions. +// + +// +// Software Class ARM Exception Subclass Progress Code definitions. +// + // // Software Class EBC Exception Subclass Progress Code definitions. // @@ -987,7 +997,6 @@ typedef struct { /// /// 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) @@ -1123,8 +1132,65 @@ typedef struct { // Software Class EFI Runtime Service Subclass Error Code definitions. // -// -// Software Class EFI DXE Service Subclass Error Code definitions. -// +/// +/// Software Class EFI DXE Service Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DXE_BS_PC_VERIFYING_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000006) +///@} + +/// +/// Software Class DXE RT Driver Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_DXE_RT_PC_S0 (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_RT_PC_S1 (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_RT_PC_S2 (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_RT_PC_S3 (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_RT_PC_S4 (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_RT_PC_S5 (EFI_SUBCLASS_SPECIFIC | 0x00000005) +///@} + +/// +/// Software Class X64 Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_X64_DIVIDE_ERROR EXCEPT_X64_DIVIDE_ERROR +#define EFI_SW_EC_X64_DEBUG EXCEPT_X64_DEBUG +#define EFI_SW_EC_X64_NMI EXCEPT_X64_NMI +#define EFI_SW_EC_X64_BREAKPOINT EXCEPT_X64_BREAKPOINT +#define EFI_SW_EC_X64_OVERFLOW EXCEPT_X64_OVERFLOW +#define EFI_SW_EC_X64_BOUND EXCEPT_X64_BOUND +#define EFI_SW_EC_X64_INVALID_OPCODE EXCEPT_X64_INVALID_OPCODE +#define EFI_SW_EC_X64_DOUBLE_FAULT EXCEPT_X64_DOUBLE_FAULT +#define EFI_SW_EC_X64_INVALID_TSS EXCEPT_X64_INVALID_TSS +#define EFI_SW_EC_X64_SEG_NOT_PRESENT EXCEPT_X64_SEG_NOT_PRESENT +#define EFI_SW_EC_X64_STACK_FAULT EXCEPT_X64_STACK_FAULT +#define EFI_SW_EC_X64_GP_FAULT EXCEPT_X64_GP_FAULT +#define EFI_SW_EC_X64_PAGE_FAULT EXCEPT_X64_PAGE_FAULT +#define EFI_SW_EC_X64_FP_ERROR EXCEPT_X64_FP_ERROR +#define EFI_SW_EC_X64_ALIGNMENT_CHECK EXCEPT_X64_ALIGNMENT_CHECK +#define EFI_SW_EC_X64_MACHINE_CHECK EXCEPT_X64_MACHINE_CHECK +#define EFI_SW_EC_X64_SIMD EXCEPT_X64_SIMD +///@} + +/// +/// Software Class ARM Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_ARM_RESET EXCEPT_ARM_RESET +#define EFI_SW_EC_ARM_UNDEFINED_INSTRUCTION EXCEPT_ARM_UNDEFINED_INSTRUCTION +#define EFI_SW_EC_ARM_SOFTWARE_INTERRUPT EXCEPT_ARM_SOFTWARE_INTERRUPT +#define EFI_SW_EC_ARM_PREFETCH_ABORT EXCEPT_ARM_PREFETCH_ABORT +#define EFI_SW_EC_ARM_DATA_ABORT EXCEPT_ARM_DATA_ABORT +#define EFI_SW_EC_ARM_RESERVED EXCEPT_ARM_RESERVED +#define EFI_SW_EC_ARM_IRQ EXCEPT_ARM_IRQ +#define EFI_SW_EC_ARM_FIQ EXCEPT_ARM_FIQ +///@} #endif diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h b/roms/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h index 978ede5ab..82d8b2561 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/ComponentName2.h @@ -3,7 +3,7 @@ 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> + 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 @@ -121,8 +121,7 @@ EFI_STATUS driver specified by This was returned in DriverName. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid - EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/Cpu.h b/roms/ipxe/src/include/ipxe/efi/Protocol/Cpu.h index ebcaf5f10..665924e88 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/Cpu.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/Cpu.h @@ -3,7 +3,7 @@ This code abstracts the DXE core from processor implementation details. - Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR> + 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 @@ -246,6 +246,8 @@ EFI_STATUS @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. + Attributes specified an illegal combination of attributes that + cannot be set together. @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 diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h b/roms/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h index 5c6787080..cc4c927df 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/DevicePath.h @@ -5,7 +5,7 @@ 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> +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 @@ -348,6 +348,26 @@ typedef struct { UINT64 Lun; } FIBRECHANNEL_DEVICE_PATH; +/// +/// Fibre Channel Ex SubType. +/// +#define MSG_FIBRECHANNELEX_DP 0x15 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 8 byte array containing Fibre Channel End Device Port Name. + /// + UINT8 WWN[8]; + /// + /// 8 byte array containing Fibre Channel Logical Unit Number. + /// + UINT8 Lun[8]; +} FIBRECHANNELEX_DEVICE_PATH; + /// /// 1394 Device Path SubType /// @@ -543,6 +563,14 @@ typedef struct { /// 0x01 - The Source IP Address is statically bound. /// BOOLEAN StaticIpAddress; + /// + /// The gateway IP address + /// + EFI_IPv4_ADDRESS GatewayIpAddress; + /// + /// The subnet mask + /// + EFI_IPv4_ADDRESS SubnetMask; } IPv4_DEVICE_PATH; /// @@ -572,10 +600,21 @@ typedef struct { /// UINT16 Protocol; /// - /// 0x00 - The Source IP Address was assigned though DHCP. - /// 0x01 - The Source IP Address is statically bound. + /// 0x00 - The Local IP Address was manually configured. + /// 0x01 - The Local IP Address is assigned through IPv6 + /// stateless auto-configuration. + /// 0x02 - The Local IP Address is assigned through IPv6 + /// stateful configuration. /// - BOOLEAN StaticIpAddress; + UINT8 IpAddressOrigin; + /// + /// The prefix length + /// + UINT8 PrefixLength; + /// + /// The gateway IP address + /// + EFI_IPv6_ADDRESS GatewayIpAddress; } IPv6_DEVICE_PATH; /// @@ -692,9 +731,9 @@ typedef struct { #define UART_FLOW_CONTROL_HARDWARE 0x00000001 #define UART_FLOW_CONTROL_XON_XOFF 0x00000010 -#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID /// -/// Serial Attached SCSI (SAS) devices. +/// Serial Attached SCSI (SAS) Device Path. /// typedef struct { EFI_DEVICE_PATH_PROTOCOL Header; @@ -724,6 +763,30 @@ typedef struct { UINT16 RelativeTargetPort; } SAS_DEVICE_PATH; +/// +/// Serial Attached SCSI (SAS) Ex Device Path SubType +/// +#define MSG_SASEX_DP 0x16 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port. + /// + UINT8 SasAddress[8]; + /// + /// 8-byte array of the SAS Logical Unit Number. + /// + UINT8 Lun[8]; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SASEX_DEVICE_PATH; + /// /// iSCSI Device Path SubType /// @@ -897,7 +960,7 @@ typedef struct { } MEDIA_PROTOCOL_DEVICE_PATH; /// -/// PIWG Firmware Volume Device Path SubType. +/// PIWG Firmware File SubType. /// #define MEDIA_PIWG_FW_FILE_DP 0x06 @@ -967,7 +1030,7 @@ typedef struct { /// UINT16 StatusFlag; /// - /// ASCIIZ string that describes the boot device to a user. + /// Null-terminated ASCII string that describes the boot device to a user. /// CHAR8 String[1]; } BBS_BBS_DEVICE_PATH; @@ -989,78 +1052,100 @@ typedef struct { /// 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_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; + ACPI_ADR_DEVICE_PATH AcpiAdr; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + FIBRECHANNELEX_DEVICE_PATH FibreChannelEx; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + USB_WWID_DEVICE_PATH UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicUnit; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + VLAN_DEVICE_PATH Vlan; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + UART_FLOW_CONTROL_DEVICE_PATH UartFlowControl; + SAS_DEVICE_PATH Sas; + SASEX_DEVICE_PATH SasEx; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FirmwareFile; + 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_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; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + ISCSI_DEVICE_PATH *Iscsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + FIBRECHANNELEX_DEVICE_PATH *FibreChannelEx; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + USB_WWID_DEVICE_PATH *UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicUnit; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + VLAN_DEVICE_PATH *Vlan; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + SAS_DEVICE_PATH *Sas; + SASEX_DEVICE_PATH *SasEx; + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH *FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; } EFI_DEV_PATH_PTR; #pragma pack() diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h b/roms/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h index 6befec63a..12873c31f 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/FormBrowser2.h @@ -61,6 +61,10 @@ typedef UINTN EFI_BROWSER_ACTION_REQUEST; #define EFI_BROWSER_ACTION_REQUEST_RESET 1 #define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2 #define EFI_BROWSER_ACTION_REQUEST_EXIT 3 +#define EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT 4 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT 5 +#define EFI_BROWSER_ACTION_REQUEST_FORM_APPLY 6 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD 7 /** diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h b/roms/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h index 2bef5cbc8..929d9cd28 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/HiiConfigAccess.h @@ -36,6 +36,12 @@ typedef UINTN EFI_BROWSER_ACTION; #define EFI_BROWSER_ACTION_RETRIEVE 2 #define EFI_BROWSER_ACTION_FORM_OPEN 3 #define EFI_BROWSER_ACTION_FORM_CLOSE 4 +#define EFI_BROWSER_ACTION_DEFAULT_STANDARD 0x1000 +#define EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING 0x1001 +#define EFI_BROWSER_ACTION_DEFAULT_SAFE 0x1002 +#define EFI_BROWSER_ACTION_DEFAULT_PLATFORM 0x2000 +#define EFI_BROWSER_ACTION_DEFAULT_HARDWARE 0x3000 +#define EFI_BROWSER_ACTION_DEFAULT_FIRMWARE 0x4000 /** diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/LoadFile.h b/roms/ipxe/src/include/ipxe/efi/Protocol/LoadFile.h new file mode 100644 index 000000000..99387e89f --- /dev/null +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/LoadFile.h @@ -0,0 +1,90 @@ +/** @file + Load File protocol as defined in the UEFI 2.0 specification. + + The load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + UEFI 2.0 can boot from any device that produces a LoadFile 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. + +**/ + +#ifndef __EFI_LOAD_FILE_PROTOCOL_H__ +#define __EFI_LOAD_FILE_PROTOCOL_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { \ + 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +/// +/// Protocol Guid defined by EFI1.1. +/// +#define LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL_GUID + +typedef struct _EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL; + +/// +/// Backward-compatible with EFI1.1 +/// +typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_INTERFACE; + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy If TRUE, indicates that the request originates from the + boot manager is attempting to load FilePath as a boot + selection. If FALSE, then FilePath must match as exact file + to be loaded. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_ABORTED The file load process was manually cancelled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE)( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ); + +/// +/// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices. +/// +struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +}; + +extern EFI_GUID gEfiLoadFileProtocolGuid; + +#endif diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h b/roms/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h index ac86e972e..29319069f 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h @@ -1,7 +1,7 @@ /** @file EFI Network Interface Identifier Protocol. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +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 @@ -87,6 +87,29 @@ typedef enum { EfiNetworkInterfaceUndi = 1 } EFI_NETWORK_INTERFACE_TYPE; +/// +/// Forward reference for pure ANSI compatability. +/// +typedef struct undiconfig_table UNDI_CONFIG_TABLE; + +/// +/// The format of the configuration table for UNDI +/// +struct undiconfig_table { + UINT32 NumberOfInterfaces; ///< The number of NIC devices + ///< that this UNDI controls. + UINT32 reserved; + UNDI_CONFIG_TABLE *nextlink; ///< A pointer to the next UNDI + ///< configuration table. + /// + /// The length of this array is given in the NumberOfInterfaces field. + /// + struct { + VOID *NII_InterfacePointer; ///< Pointer to the NII interface structure. + VOID *DevicePathPointer; ///< Pointer to the device path for this NIC. + } NII_entry[1]; +}; + extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31; diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h b/roms/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h index e8feea0c4..b9c80f589 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h @@ -5,7 +5,7 @@ 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> + 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 @@ -21,6 +21,8 @@ FILE_LICENCE ( BSD3 ); +#include <ipxe/efi/Library/BaseLib.h> + #define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ { \ 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ @@ -108,7 +110,11 @@ typedef enum { #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))) + (UINT64) ( \ + (((UINTN) bus) << 24) | \ + (((UINTN) dev) << 16) | \ + (((UINTN) func) << 8) | \ + (((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32)))) typedef struct { UINT8 Register; diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h b/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h index a89a9b4fa..571ecaf30 100644 --- a/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextIn.h @@ -4,7 +4,7 @@ Abstraction of a very simple input device like a keyboard or serial terminal. - Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR> + 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 @@ -78,8 +78,6 @@ typedef struct { #define SCAN_F8 0x0012 #define SCAN_F9 0x0013 #define SCAN_F10 0x0014 -#define SCAN_F11 0x0015 -#define SCAN_F12 0x0016 #define SCAN_ESC 0x0017 /** diff --git a/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextInEx.h b/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextInEx.h new file mode 100644 index 000000000..71d3463bf --- /dev/null +++ b/roms/ipxe/src/include/ipxe/efi/Protocol/SimpleTextInEx.h @@ -0,0 +1,327 @@ +/** @file + Simple Text Input Ex protocol from the UEFI 2.0 specification. + + This protocol defines an extension to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL + which exposes much more state and modifier information from the input device, + also allows one to register a notification for a particular keystroke. + + 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. + +**/ + +#ifndef __SIMPLE_TEXT_IN_EX_H__ +#define __SIMPLE_TEXT_IN_EX_H__ + +FILE_LICENCE ( BSD3 ); + +#include <ipxe/efi/Protocol/SimpleTextIn.h> + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } + + +typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +/** + The Reset() function resets the input device hardware. As part + of initialization process, the firmware/device will make a quick + but reasonable attempt to verify that the device is functioning. + If the ExtendedVerification flag is TRUE the firmware may take + an extended amount of time to verify the device is operating on + reset. Otherwise the reset operation is to occur as quickly as + possible. The hardware verification process is not defined by + this specification and is left up to the platform firmware or + driver to implement. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param ExtendedVerification Indicates that the driver may + perform a more exhaustive + verification operation of the + device during reset. + + + @retval EFI_SUCCESS The device was reset. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + + +/// +/// EFI_KEY_TOGGLE_STATE. The toggle states are defined. +/// They are: EFI_TOGGLE_STATE_VALID, EFI_SCROLL_LOCK_ACTIVE +/// EFI_NUM_LOCK_ACTIVE, EFI_CAPS_LOCK_ACTIVE +/// +typedef UINT8 EFI_KEY_TOGGLE_STATE; + +typedef struct _EFI_KEY_STATE { + /// + /// Reflects the currently pressed shift + /// modifiers for the input device. The + /// returned value is valid only if the high + /// order bit has been set. + /// + UINT32 KeyShiftState; + /// + /// Reflects the current internal state of + /// various toggled attributes. The returned + /// value is valid only if the high order + /// bit has been set. + /// + EFI_KEY_TOGGLE_STATE KeyToggleState; +} EFI_KEY_STATE; + +typedef struct { + /// + /// The EFI scan code and Unicode value returned from the input device. + /// + EFI_INPUT_KEY Key; + /// + /// The current state of various toggled attributes as well as input modifier values. + /// + EFI_KEY_STATE KeyState; +} EFI_KEY_DATA; + +// +// Any Shift or Toggle State that is valid should have +// high order bit set. +// +// Shift state +// +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_SHIFT_PRESSED 0x00000001 +#define EFI_LEFT_SHIFT_PRESSED 0x00000002 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 +#define EFI_RIGHT_LOGO_PRESSED 0x00000040 +#define EFI_LEFT_LOGO_PRESSED 0x00000080 +#define EFI_MENU_KEY_PRESSED 0x00000100 +#define EFI_SYS_REQ_PRESSED 0x00000200 + +// +// Toggle state +// +#define EFI_TOGGLE_STATE_VALID 0x80 +#define EFI_KEY_STATE_EXPOSED 0x40 +#define EFI_SCROLL_LOCK_ACTIVE 0x01 +#define EFI_NUM_LOCK_ACTIVE 0x02 +#define EFI_CAPS_LOCK_ACTIVE 0x04 + +// +// EFI Scan codes +// +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_PAUSE 0x0048 +#define SCAN_F13 0x0068 +#define SCAN_F14 0x0069 +#define SCAN_F15 0x006A +#define SCAN_F16 0x006B +#define SCAN_F17 0x006C +#define SCAN_F18 0x006D +#define SCAN_F19 0x006E +#define SCAN_F20 0x006F +#define SCAN_F21 0x0070 +#define SCAN_F22 0x0071 +#define SCAN_F23 0x0072 +#define SCAN_F24 0x0073 +#define SCAN_MUTE 0x007F +#define SCAN_VOLUME_UP 0x0080 +#define SCAN_VOLUME_DOWN 0x0081 +#define SCAN_BRIGHTNESS_UP 0x0100 +#define SCAN_BRIGHTNESS_DOWN 0x0101 +#define SCAN_SUSPEND 0x0102 +#define SCAN_HIBERNATE 0x0103 +#define SCAN_TOGGLE_DISPLAY 0x0104 +#define SCAN_RECOVERY 0x0105 +#define SCAN_EJECT 0x0106 + +/** + The function reads the next keystroke from the input device. If + there is no pending keystroke the function returns + EFI_NOT_READY. If there is a pending keystroke, then + KeyData.Key.ScanCode is the EFI scan code defined in Error! + Reference source not found. The KeyData.Key.UnicodeChar is the + actual printable character or is zero if the key does not + represent a printable character (control key, function key, + etc.). The KeyData.KeyState is shift state for the character + reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode . + When interpreting the data from this function, it should be + noted that if a class of printable characters that are + normally adjusted by shift modifiers (e.g. Shift Key + "f" + key) would be presented solely as a KeyData.Key.UnicodeChar + without the associated shift state. So in the previous example + of a Shift Key + "f" key being pressed, the only pertinent + data returned would be KeyData.Key.UnicodeChar with the value + of "F". This of course would not typically be the case for + non-printable characters such as the pressing of the Right + Shift Key + F10 key since the corresponding returned data + would be reflected both in the KeyData.KeyState.KeyShiftState + and KeyData.Key.ScanCode values. UEFI drivers which implement + the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return + KeyData.Key and KeyData.KeyState values. These drivers must + always return the most current state of + KeyData.KeyState.KeyShiftState and + KeyData.KeyState.KeyToggleState. It should also be noted that + certain input devices may not be able to produce shift or toggle + state information, and in those cases the high order bit in the + respective Toggle and Shift state fields should not be active. + + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke state data for the key that was + pressed. + + + @retval EFI_SUCCESS The keystroke information was + returned. + + @retval EFI_NOT_READY There was no keystroke data available. + EFI_DEVICE_ERROR The keystroke + information was not returned due to + hardware errors. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +); + +/** + The SetState() function allows the input device hardware to + have state settings adjusted. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to + set the state for the input device. + + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not have the + setting adjusted. + + @retval EFI_UNSUPPORTED The device does not support the + ability to have its state set. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_STATE)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +/// +/// The function will be called when the key sequence is typed specified by KeyData. +/// +typedef +EFI_STATUS +(EFIAPI *EFI_KEY_NOTIFY_FUNCTION)( + IN EFI_KEY_DATA *KeyData +); + +/** + The RegisterKeystrokeNotify() function registers a function + which will be called when a specified keystroke will occur. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. + + @param KeyNotificationFunction Points to the function to be + called when the key sequence + is typed specified by KeyData. + + + @param NotifyHandle Points to the unique handle assigned to + the registered notification. + + @retval EFI_SUCCESS The device state was set + appropriately. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + data structures. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +); + +/** + The UnregisterKeystrokeNotify() function removes the + notification which was previously registered. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param NotificationHandle The handle of the notification + function being unregistered. + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_INVALID_PARAMETER The NotificationHandle is + invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + + +/// +/// The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is used on the ConsoleIn +/// device. It is an extension to the Simple Text Input protocol +/// which allows a variety of extended shift state information to be +/// returned. +/// +struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{ + EFI_INPUT_RESET_EX Reset; + EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + /// + /// Event to use with WaitForEvent() to wait for a key to be available. + /// + EFI_EVENT WaitForKeyEx; + EFI_SET_STATE SetState; + EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; +}; + + +extern EFI_GUID gEfiSimpleTextInputExProtocolGuid; + +#endif + diff --git a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h index 2c63aa6ff..c56f3757b 100644 --- a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h +++ b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiBaseType.h @@ -1,7 +1,7 @@ /** @file Defines data types and constants introduced in UEFI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> +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 @@ -150,11 +150,13 @@ typedef union { #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_COMPROMISED_DATA RETURN_COMPROMISED_DATA #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 EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA ///@} /// diff --git a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h index 26af39f5d..19acf55d4 100644 --- a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h +++ b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiGpt.h @@ -71,7 +71,8 @@ typedef struct { /// /// The size, in bytes, of each the GUID Partition /// Entry structures in the GUID Partition Entry - /// array. Must be a multiple of 8. + /// array. This field shall be set to a value of 128 x 2^n where n is + /// an integer greater than or equal to zero (e.g., 128, 256, 512, etc.). /// UINT32 SizeOfPartitionEntry; /// diff --git a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h index 6b6d1e066..fb20d763a 100644 --- a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h +++ b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h @@ -3,7 +3,7 @@ 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> +Copyright (c) 2006 - 2012, 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 @@ -660,6 +660,13 @@ typedef struct { UINT8 Day; } EFI_HII_DATE; +typedef struct { + EFI_QUESTION_ID QuestionId; + EFI_FORM_ID FormId; + EFI_GUID FormSetGuid; + EFI_STRING_ID DevicePath; +} EFI_HII_REF; + typedef union { UINT8 u8; UINT16 u16; @@ -669,7 +676,8 @@ typedef union { 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_HII_REF ref; ///< EFI_IFR_TYPE_REF + // UINT8 buffer[]; ///< EFI_IFR_TYPE_BUFFER } EFI_IFR_TYPE_VALUE; // @@ -694,7 +702,7 @@ typedef union { #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_EQ_ID_VAL_LIST_OP 0x14 #define EFI_IFR_AND_OP 0x15 #define EFI_IFR_OR_OP 0x16 #define EFI_IFR_NOT_OP 0x17 @@ -771,6 +779,8 @@ typedef union { #define EFI_IFR_CATENATE_OP 0x5E #define EFI_IFR_GUID_OP 0x5F #define EFI_IFR_SECURITY_OP 0x60 +#define EFI_IFR_MODAL_TAG_OP 0x61 +#define EFI_IFR_REFRESH_ID_OP 0x62 // // Definitions of IFR Standard Headers @@ -843,6 +853,8 @@ typedef struct _EFI_IFR_VARSTORE_EFI { EFI_VARSTORE_ID VarStoreId; EFI_GUID Guid; UINT32 Attributes; + UINT16 Size; + UINT8 Name[1]; } EFI_IFR_VARSTORE_EFI; typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { @@ -875,6 +887,10 @@ typedef struct _EFI_IFR_IMAGE { EFI_IMAGE_ID Id; } EFI_IFR_IMAGE; +typedef struct _EFI_IFR_MODAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODAL; + typedef struct _EFI_IFR_LOCKED { EFI_IFR_OP_HEADER Header; } EFI_IFR_LOCKED; @@ -948,6 +964,11 @@ typedef struct _EFI_IFR_REF4 { EFI_STRING_ID DevicePath; } EFI_IFR_REF4; +typedef struct _EFI_IFR_REF5 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_REF5; + typedef struct _EFI_IFR_RESET_BUTTON { EFI_IFR_OP_HEADER Header; EFI_IFR_STATEMENT_HEADER Statement; @@ -1134,6 +1155,7 @@ typedef struct _EFI_IFR_ONE_OF_OPTION { #define EFI_IFR_TYPE_UNDEFINED 0x09 #define EFI_IFR_TYPE_ACTION 0x0A #define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C #define EFI_IFR_OPTION_DEFAULT 0x10 #define EFI_IFR_OPTION_DEFAULT_MFG 0x20 @@ -1144,6 +1166,11 @@ typedef struct _EFI_IFR_GUID { //Optional Data Follows } EFI_IFR_GUID; +typedef struct _EFI_IFR_REFRESH_ID { + EFI_IFR_OP_HEADER Header; + EFI_GUID RefreshEventGroupId; +} EFI_IFR_REFRESH_ID; + typedef struct _EFI_IFR_DUP { EFI_IFR_OP_HEADER Header; } EFI_IFR_DUP; diff --git a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h index 6ecbcf118..678f3ebd6 100644 --- a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h +++ b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiMultiPhase.h @@ -1,7 +1,7 @@ /** @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> +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 @@ -122,21 +122,26 @@ typedef struct { /// /// 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 - +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 /// /// This attribute is identified by the mnemonic 'HR' /// elsewhere in this specification. /// -#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +/// +/// Attributes of Authenticated Variable +/// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 + /// /// AuthInfo is a WIN_CERTIFICATE using the wCertificateType /// WIN_CERTIFICATE_UEFI_GUID and the CertType -/// EFI_CERT_TYPE_RSA2048_SHA256. If the attribute specifies +/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. 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 the data.and descriptor size. The caller @@ -167,5 +172,24 @@ typedef struct { WIN_CERTIFICATE_UEFI_GUID AuthInfo; } EFI_VARIABLE_AUTHENTICATION; -#endif +/// +/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is +/// set, then the Data buffer shall begin with an instance of a complete (and serialized) +/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new +/// variable value and DataSize shall reflect the combined size of the descriptor and the new +/// variable value. The authentication descriptor is not part of the variable data and is not +/// returned by subsequent calls to GetVariable(). +/// +typedef struct { + /// + /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and + /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT. + /// + EFI_TIME TimeStamp; + /// + /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; + } EFI_VARIABLE_AUTHENTICATION_2; +#endif diff --git a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h index 1f125d4f3..4887157cc 100644 --- a/roms/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h +++ b/roms/ipxe/src/include/ipxe/efi/Uefi/UefiSpec.h @@ -5,7 +5,7 @@ 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> +Copyright (c) 2006 - 2012, 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 @@ -25,6 +25,7 @@ FILE_LICENCE ( BSD3 ); #include <ipxe/efi/Protocol/DevicePath.h> #include <ipxe/efi/Protocol/SimpleTextIn.h> +#include <ipxe/efi/Protocol/SimpleTextInEx.h> #include <ipxe/efi/Protocol/SimpleTextOut.h> /// @@ -128,6 +129,7 @@ typedef struct { @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or AllocateMaxAddress or AllocateAddress. 2) MemoryType is in the range + 3) Memory is NULL. EfiMaxMemoryType..0x7FFFFFFF. @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. @retval EFI_NOT_FOUND The requested pages could not be found. @@ -206,7 +208,7 @@ EFI_STATUS @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. + @retval EFI_INVALID_PARAMETER PoolType was invalid or Buffer is NULL. **/ typedef @@ -277,7 +279,7 @@ EFI_STATUS 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_INVALID_PARAMETER ControllerHandle is NULL. @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances present in the system. 2) No drivers were connected to ControllerHandle. @@ -307,7 +309,7 @@ EFI_STATUS 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. + @retval EFI_INVALID_PARAMETER 1) ControllerHandle is NULL. 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. @@ -1168,7 +1170,7 @@ EFI_STATUS @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 Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. **/ @@ -1194,7 +1196,7 @@ EFI_STATUS @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 Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. **/ @@ -1234,7 +1236,7 @@ EFI_STATUS @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 Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_INVALID_PARAMETER Interface is NULL. @@ -1305,8 +1307,8 @@ EFI_STATUS 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. + @retval EFI_INVALID_PARAMETER 1) Handle is NULL. + 2) AgentHandle is NULL. 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. @@ -1493,7 +1495,7 @@ EFI_STATUS @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_INVALID_PARAMETER Guid is NULL. @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. **/ @@ -1725,16 +1727,17 @@ EFI_STATUS // EFI Runtime Services Table // #define EFI_SYSTEM_TABLE_SIGNATURE SIGNATURE_64 ('I','B','I',' ','S','Y','S','T') +#define EFI_2_31_SYSTEM_TABLE_REVISION ((2 << 16) | (31)) #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_SYSTEM_TABLE_REVISION EFI_2_31_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 +#define EFI_RUNTIME_SERVICES_REVISION EFI_2_31_SYSTEM_TABLE_REVISION /// /// EFI Runtime Services Table. @@ -1786,7 +1789,7 @@ typedef struct { #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 +#define EFI_BOOT_SERVICES_REVISION EFI_2_31_SYSTEM_TABLE_REVISION /// /// EFI Boot Services Table. diff --git a/roms/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h b/roms/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h index 0b1a3e11e..e10e3b549 100644 --- a/roms/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h +++ b/roms/ipxe/src/include/ipxe/efi/X64/ProcessorBind.h @@ -1,7 +1,7 @@ /** @file Processor or Compiler specific defines and types x64 (Intel 64, AMD64). - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2006 - 2012, 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 @@ -149,7 +149,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #else /// /// 8-byte unsigned value @@ -196,7 +196,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #endif /// diff --git a/roms/ipxe/src/include/ipxe/efi/efi.h b/roms/ipxe/src/include/ipxe/efi/efi.h index 8a216b537..b5ce7df9e 100644 --- a/roms/ipxe/src/include/ipxe/efi/efi.h +++ b/roms/ipxe/src/include/ipxe/efi/efi.h @@ -142,5 +142,7 @@ 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/roms/ipxe/src/include/ipxe/efi/efi_hii.h b/roms/ipxe/src/include/ipxe/efi/efi_hii.h index 1a98750f2..8e94bbe7e 100644 --- a/roms/ipxe/src/include/ipxe/efi/efi_hii.h +++ b/roms/ipxe/src/include/ipxe/efi/efi_hii.h @@ -8,133 +8,89 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #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, \ - } +/** GUID indicating formset compliance for IBM Unified Configuration Manager */ +#define EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID \ + { 0x5c8e9746, 0xa5f7, 0x4593, \ + { 0xaf, 0x1f, 0x66, 0xa8, 0x2a, 0xa1, 0x9c, 0xb1 } } -/** - * 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, \ - } +/** An EFI IFR builder */ +struct efi_ifr_builder { + /** IFR opcodes */ + EFI_IFR_OP_HEADER *ops; + /** Length of IFR opcodes */ + size_t ops_len; + /** Strings */ + EFI_HII_STRING_BLOCK *strings; + /** Length of strings */ + size_t strings_len; + /** Current string identifier */ + unsigned int string_id; + /** Current variable store identifier */ + unsigned int varstore_id; + /** Current form identifier */ + unsigned int form_id; + /** An allocation has failed */ + int failed; +}; /** - * Define an EFI IFR form + * Initialise IFR builder * - * @v formid Form ID - * @v title Title string - * @ret ifr Form + * @v ifr IFR builder * - * This definition opens a new scope, which must be closed by an - * EFI_IFR_END(). + * The caller must eventually call efi_ifr_free() to free the dynamic + * storage associated with the IFR builder. */ -#define EFI_IFR_FORM( formid, title ) { \ - .Header = { \ - .OpCode = EFI_IFR_FORM_OP, \ - .Length = sizeof ( EFI_IFR_FORM ), \ - .Scope = 1, \ - }, \ - .FormId = formid, \ - .FormTitle = title, \ - } +static inline void efi_ifr_init ( struct efi_ifr_builder *ifr ) { + memset ( ifr, 0, sizeof ( *ifr ) ); +} -/** - * 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 ), \ - }, \ - } +extern unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, + const char *fmt, ... ); +extern void efi_ifr_end_op ( struct efi_ifr_builder *ifr ); +extern void efi_ifr_false_op ( struct efi_ifr_builder *ifr ); +extern unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr, + unsigned int title_id ); +extern void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid, + unsigned int title_id, unsigned int help_id, + ... ); +void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id, + unsigned int varstore_info, unsigned int varstore_type ); +extern void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, + unsigned int class ); +extern void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr, + unsigned int subclass ); +extern void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, + unsigned int varstore_info, + unsigned int vflags, unsigned long min_value, + unsigned long max_value, unsigned int step, + unsigned int flags ); +extern void efi_ifr_string_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, unsigned int help_id, + unsigned int question_id, + unsigned int varstore_id, + unsigned int varstore_info, unsigned int vflags, + unsigned int min_size, unsigned int max_size, + unsigned int flags ); +extern void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ); +extern void efi_ifr_text_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, unsigned int help_id, + unsigned int text_id ); +extern void efi_ifr_true_op ( struct efi_ifr_builder *ifr ); +extern unsigned int +efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid ); +extern void efi_ifr_free ( struct efi_ifr_builder *ifr ); +extern EFI_HII_PACKAGE_LIST_HEADER * +efi_ifr_package ( struct efi_ifr_builder *ifr, const EFI_GUID *guid, + const char *language, unsigned int language_id ); #endif /* _IPXE_EFI_HII_H */ diff --git a/roms/ipxe/src/include/ipxe/efi/efi_pci.h b/roms/ipxe/src/include/ipxe/efi/efi_pci.h index 24890eb40..6429f2109 100644 --- a/roms/ipxe/src/include/ipxe/efi/efi_pci.h +++ b/roms/ipxe/src/include/ipxe/efi/efi_pci.h @@ -12,6 +12,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/efi/Protocol/PciIo.h> #include <ipxe/efi/Protocol/DevicePath.h> +/* PciRootBridgeIo.h uses LShiftU64(), which isn't defined anywhere else */ +static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) { + return ( value << shift ); +} + struct efi_driver; struct device; diff --git a/roms/ipxe/src/include/ipxe/efi/efi_snp.h b/roms/ipxe/src/include/ipxe/efi/efi_snp.h new file mode 100644 index 000000000..c86760908 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/efi/efi_snp.h @@ -0,0 +1,75 @@ +#ifndef _IPXE_EFI_SNP_H +#define _IPXE_EFI_SNP_H + +/** @file + * + * iPXE EFI SNP interface + * + */ + +#include <ipxe/list.h> +#include <ipxe/netdevice.h> +#include <ipxe/efi/efi.h> +#include <ipxe/efi/Protocol/SimpleNetwork.h> +#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h> +#include <ipxe/efi/Protocol/ComponentName2.h> +#include <ipxe/efi/Protocol/DevicePath.h> +#include <ipxe/efi/Protocol/HiiConfigAccess.h> +#include <ipxe/efi/Protocol/HiiDatabase.h> + +/** 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; + /** Component name protocol */ + EFI_COMPONENT_NAME2_PROTOCOL name2; + /** 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 ) ]; + /** Driver name */ + wchar_t driver_name[16]; + /** Controller name */ + wchar_t controller_name[32]; + /** The device path + * + * This field is variable in size and must appear at the end + * of the structure. + */ + EFI_DEVICE_PATH_PROTOCOL path; +}; + +extern int efi_snp_hii_install ( struct efi_snp_device *snpdev ); +extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ); + +#endif /* _IPXE_EFI_SNP_H */ diff --git a/roms/ipxe/src/include/ipxe/efi/efi_uaccess.h b/roms/ipxe/src/include/ipxe/efi/efi_uaccess.h index dc226a3e5..79c18972e 100644 --- a/roms/ipxe/src/include/ipxe/efi/efi_uaccess.h +++ b/roms/ipxe/src/include/ipxe/efi/efi_uaccess.h @@ -56,6 +56,12 @@ UACCESS_INLINE ( efi, userptr_add ) ( userptr_t userptr, off_t offset ) { return trivial_userptr_add ( userptr, offset ); } +static inline __always_inline off_t +UACCESS_INLINE ( efi, userptr_sub ) ( userptr_t userptr, + userptr_t subtrahend ) { + return trivial_userptr_sub ( userptr, subtrahend ); +} + static inline __always_inline void UACCESS_INLINE ( efi, memcpy_user ) ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, diff --git a/roms/ipxe/src/include/ipxe/efi/ipxe_download.h b/roms/ipxe/src/include/ipxe/efi/ipxe_download.h new file mode 100644 index 000000000..22e3cef08 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/efi/ipxe_download.h @@ -0,0 +1,154 @@ +#ifndef _IPXE_DOWNLOAD_H +#define _IPXE_DOWNLOAD_H + +/* + * 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 ); + +/** @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 /* _IPXE_DOWNLOAD_H */ diff --git a/roms/ipxe/src/include/ipxe/elf.h b/roms/ipxe/src/include/ipxe/elf.h index e5fed2f89..ec675c047 100644 --- a/roms/ipxe/src/include/ipxe/elf.h +++ b/roms/ipxe/src/include/ipxe/elf.h @@ -12,6 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <elf.h> -extern int elf_load ( struct image *image, physaddr_t *entry ); +extern int elf_load ( struct image *image, physaddr_t *entry, physaddr_t *max ); #endif /* _IPXE_ELF_H */ diff --git a/roms/ipxe/src/include/ipxe/entropy.h b/roms/ipxe/src/include/ipxe/entropy.h new file mode 100644 index 000000000..adf325e79 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/errfile.h b/roms/ipxe/src/include/ipxe/errfile.h index 3073383ba..514e1f8ae 100644 --- a/roms/ipxe/src/include/ipxe/errfile.h +++ b/roms/ipxe/src/include/ipxe/errfile.h @@ -60,6 +60,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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_pending ( ERRFILE_CORE | 0x00190000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) @@ -137,6 +140,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 ) @@ -158,7 +169,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_nullnet ( ERRFILE_NET | 0x00090000 ) #define ERRFILE_tcp ( ERRFILE_NET | 0x000a0000 ) #define ERRFILE_ftp ( ERRFILE_NET | 0x000b0000 ) -#define ERRFILE_http ( ERRFILE_NET | 0x000c0000 ) +#define ERRFILE_httpcore ( ERRFILE_NET | 0x000c0000 ) #define ERRFILE_iscsi ( ERRFILE_NET | 0x000d0000 ) #define ERRFILE_tcpip ( ERRFILE_NET | 0x000e0000 ) #define ERRFILE_udp ( ERRFILE_NET | 0x000f0000 ) @@ -239,6 +250,21 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 ) +#define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) +#define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 ) +#define ERRFILE_readline ( ERRFILE_OTHER | 0x00320000 ) /** @} */ diff --git a/roms/ipxe/src/include/ipxe/ethernet.h b/roms/ipxe/src/include/ipxe/ethernet.h index 7e49655a3..1794ff67e 100644 --- a/roms/ipxe/src/include/ipxe/ethernet.h +++ b/roms/ipxe/src/include/ipxe/ethernet.h @@ -10,6 +10,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> +#include <ipxe/netdevice.h> +#include <ipxe/iobuf.h> /** * Check if Ethernet address is all zeroes @@ -77,6 +79,13 @@ static inline int is_valid_ether_addr ( const void *addr ) { ( ! is_zero_ether_addr ( addr ) ) ); } +extern uint8_t eth_broadcast[]; +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, diff --git a/roms/ipxe/src/include/ipxe/fc.h b/roms/ipxe/src/include/ipxe/fc.h index ab6b5bae7..6689f394e 100644 --- a/roms/ipxe/src/include/ipxe/fc.h +++ b/roms/ipxe/src/include/ipxe/fc.h @@ -357,7 +357,15 @@ struct fc_peer { /** List of upper-layer protocols */ struct list_head ulps; - /** Active usage count */ + /** 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; }; @@ -424,8 +432,15 @@ struct fc_ulp { /** Service parameter length */ size_t param_len; - /** Active usage count */ - unsigned int usage; + /** 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 */ @@ -434,6 +449,21 @@ enum fc_ulp_flags { 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 * @@ -456,14 +486,51 @@ 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_increment ( struct fc_ulp *ulp ); -extern void fc_ulp_decrement ( struct fc_ulp *ulp ); +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 ); diff --git a/roms/ipxe/src/include/ipxe/features.h b/roms/ipxe/src/include/ipxe/features.h index 660015cd2..0c92f5be9 100644 --- a/roms/ipxe/src/include/ipxe/features.h +++ b/roms/ipxe/src/include/ipxe/features.h @@ -52,6 +52,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 */ +#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */ /** @} */ diff --git a/roms/ipxe/src/include/ipxe/fip.h b/roms/ipxe/src/include/ipxe/fip.h index b81e8604e..872923375 100644 --- a/roms/ipxe/src/include/ipxe/fip.h +++ b/roms/ipxe/src/include/ipxe/fip.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include <stdint.h> diff --git a/roms/ipxe/src/include/ipxe/hash_df.h b/roms/ipxe/src/include/ipxe/hash_df.h new file mode 100644 index 000000000..607a4a610 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/hmac_drbg.h b/roms/ipxe/src/include/ipxe/hmac_drbg.h new file mode 100644 index 000000000..8dfd2924f --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/http.h b/roms/ipxe/src/include/ipxe/http.h index d8f4ca5ac..cf8c0c7fa 100644 --- a/roms/ipxe/src/include/ipxe/http.h +++ b/roms/ipxe/src/include/ipxe/http.h @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); 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/roms/ipxe/src/include/ipxe/ib_packet.h b/roms/ipxe/src/include/ipxe/ib_packet.h index 4bd335764..a959967cb 100644 --- a/roms/ipxe/src/include/ipxe/ib_packet.h +++ b/roms/ipxe/src/include/ipxe/ib_packet.h @@ -152,9 +152,10 @@ 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 ); + const struct ib_address_vector *dest ); 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 ); + struct ib_address_vector *dest, + struct ib_address_vector *source ); #endif /* _IPXE_IB_PACKET_H */ diff --git a/roms/ipxe/src/include/ipxe/image.h b/roms/ipxe/src/include/ipxe/image.h index dbcd6d642..6022dce66 100644 --- a/roms/ipxe/src/include/ipxe/image.h +++ b/roms/ipxe/src/include/ipxe/image.h @@ -29,7 +29,7 @@ struct image { /** URI of image */ struct uri *uri; /** Name */ - char name[16]; + char *name; /** Flags */ unsigned int flags; @@ -64,6 +64,12 @@ struct image { /** Image is selected for execution */ #define IMAGE_SELECTED 0x0002 +/** Image is trusted */ +#define IMAGE_TRUSTED 0x0004 + +/** Image will be automatically unregistered after execution */ +#define IMAGE_AUTO_UNREGISTER 0x0008 + /** An executable image type */ struct image_type { /** Name of this image type */ @@ -119,6 +125,10 @@ extern struct image *current_image; #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 * @@ -137,8 +147,8 @@ static inline struct image * first_image ( void ) { return list_first_entry ( &images, struct image, list ); } -extern struct image * alloc_image ( void ); -extern void image_set_uri ( struct image *image, struct uri *uri ); +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 ); @@ -148,6 +158,7 @@ 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 @@ -170,15 +181,30 @@ static inline void image_put ( struct image *image ) { } /** - * Set image name + * 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 - * @v name New image name - * @ret rc Return status code */ -static inline int image_set_name ( struct image *image, const char *name ) { - strncpy ( image->name, name, ( sizeof ( image->name ) - 1 ) ); - return 0; +static inline void image_untrust ( struct image *image ) { + image->flags &= ~IMAGE_TRUSTED; } #endif /* _IPXE_IMAGE_H */ diff --git a/roms/ipxe/src/include/ipxe/infiniband.h b/roms/ipxe/src/include/ipxe/infiniband.h index f97a5d4fe..f546ea61b 100644 --- a/roms/ipxe/src/include/ipxe/infiniband.h +++ b/roms/ipxe/src/include/ipxe/infiniband.h @@ -142,6 +142,16 @@ enum ib_queue_pair_type { IB_QPT_ETH, }; +/** Infiniband queue pair operations */ +struct ib_queue_pair_operations { + /** Allocate receive I/O buffer + * + * @v len Maximum receive length + * @ret iobuf I/O buffer (or NULL if out of memory) + */ + struct io_buffer * ( * alloc_iob ) ( size_t len ); +}; + /** An Infiniband Queue Pair */ struct ib_queue_pair { /** Containing Infiniband device */ @@ -169,6 +179,8 @@ struct ib_queue_pair { struct list_head mgids; /** Address vector */ struct ib_address_vector av; + /** Queue pair operations */ + struct ib_queue_pair_operations *op; /** Driver private data */ void *drv_priv; /** Queue owner private data */ @@ -193,13 +205,15 @@ struct ib_completion_queue_operations { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v dest Destination address vector, or NULL + * @v source Source 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 ib_address_vector *dest, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); }; @@ -277,7 +291,7 @@ struct ib_device_operations { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code * @@ -288,7 +302,7 @@ struct ib_device_operations { */ int ( * post_send ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ); /** Post receive work queue entry * @@ -478,8 +492,8 @@ extern void ib_poll_cq ( struct ib_device *ibdev, 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 ); + unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq, + struct ib_queue_pair_operations *op ); 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 ); @@ -490,7 +504,7 @@ extern struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev, 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 ib_address_vector *dest, struct io_buffer *iobuf ); extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf ); @@ -499,7 +513,8 @@ extern void ib_complete_send ( struct ib_device *ibdev, 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 ib_address_vector *dest, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); extern void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ); diff --git a/roms/ipxe/src/include/ipxe/iobuf.h b/roms/ipxe/src/include/ipxe/iobuf.h index 82c8b8896..b2b0cb440 100644 --- a/roms/ipxe/src/include/ipxe/iobuf.h +++ b/roms/ipxe/src/include/ipxe/iobuf.h @@ -13,17 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 * @@ -221,9 +210,12 @@ static inline void iob_populate ( struct io_buffer *iobuf, (iobuf) = NULL; \ __iobuf; } ) +extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align, + size_t offset ); 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 ); +extern struct io_buffer * iob_concatenate ( struct list_head *list ); #endif /* _IPXE_IOBUF_H */ diff --git a/roms/ipxe/src/include/ipxe/ip.h b/roms/ipxe/src/include/ipxe/ip.h index 3f3dc1f77..ca508e274 100644 --- a/roms/ipxe/src/include/ipxe/ip.h +++ b/roms/ipxe/src/include/ipxe/ip.h @@ -31,9 +31,6 @@ struct io_buffer; #define IP_TOS 0 #define IP_TTL 64 -#define IP_FRAG_IOB_SIZE 1500 -#define IP_FRAG_TIMEOUT 50 - /** An IPv4 packet header */ struct iphdr { uint8_t verhdrlen; @@ -73,24 +70,22 @@ struct ipv4_miniroute { struct in_addr gateway; }; -/* Fragment reassembly buffer */ -struct frag_buffer { - /* Identification number */ - uint16_t ident; - /* Source network address */ - struct in_addr src; - /* Destination network address */ - struct in_addr dest; - /* Reassembled I/O buffer */ - struct io_buffer *frag_iob; - /* Reassembly timer */ - struct retry_timer frag_timer; +/* 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; +extern int ipv4_has_any_addr ( struct net_device *netdev ); + #endif /* _IPXE_IP_H */ diff --git a/roms/ipxe/src/include/ipxe/ipoib.h b/roms/ipxe/src/include/ipxe/ipoib.h index e8f12dc5d..68ff8df49 100644 --- a/roms/ipxe/src/include/ipxe/ipoib.h +++ b/roms/ipxe/src/include/ipxe/ipoib.h @@ -8,6 +8,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <ipxe/if_arp.h> #include <ipxe/infiniband.h> /** IPoIB MAC address length */ @@ -33,25 +34,32 @@ 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; + uint16_t reserved; } __attribute__ (( packed )); +/** GUID mask used for constructing eIPoIB Local Ethernet MAC address (LEMAC) */ +#define IPOIB_GUID_MASK 0xe7 + +/** eIPoIB Remote Ethernet MAC address + * + * An eIPoIB REMAC address is an Ethernet-like (6 byte) link-layer + * pseudo-address used to look up a full IPoIB link-layer address. + */ +struct ipoib_remac { + /** Remote QPN + * + * Must be ORed with EIPOIB_QPN_LA so that eIPoIB REMAC + * addresses are considered as locally-assigned Ethernet MAC + * addreses. + */ + uint32_t qpn; + /** Remote LID */ + uint16_t lid; +} __attribute__ (( packed )); + +/** eIPoIB REMAC locally-assigned address indicator */ +#define EIPOIB_QPN_LA 0x02000000UL + extern const char * ipoib_ntoa ( const void *ll_addr ); extern struct net_device * alloc_ipoibdev ( size_t priv_size ); diff --git a/roms/ipxe/src/include/ipxe/isapnp.h b/roms/ipxe/src/include/ipxe/isapnp.h index 47a47025b..b0b0e98d6 100644 --- a/roms/ipxe/src/include/ipxe/isapnp.h +++ b/roms/ipxe/src/include/ipxe/isapnp.h @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) diff --git a/roms/ipxe/src/include/ipxe/iscsi.h b/roms/ipxe/src/include/ipxe/iscsi.h index 5d3d73b0c..be71360a0 100644 --- a/roms/ipxe/src/include/ipxe/iscsi.h +++ b/roms/ipxe/src/include/ipxe/iscsi.h @@ -36,7 +36,7 @@ union iscsi_segment_lengths { */ uint8_t data_len[3]; } bytes; - /** Ths data length (measured in bytes), in network byte + /** The data length (measured in bytes), in network byte * order, with ahs_len as the first byte. */ uint32_t ahs_and_data_len; @@ -515,8 +515,6 @@ enum iscsi_tx_state { ISCSI_TX_AHS, /** Sending the data segment */ ISCSI_TX_DATA, - /** Sending the data segment padding */ - ISCSI_TX_DATA_PADDING, }; /** State of an iSCSI RX engine */ diff --git a/roms/ipxe/src/include/ipxe/lineconsole.h b/roms/ipxe/src/include/ipxe/lineconsole.h new file mode 100644 index 000000000..925c0accc --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/linux/linux_entropy.h b/roms/ipxe/src/include/ipxe/linux/linux_entropy.h new file mode 100644 index 000000000..bd89bd52f --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/linux/linux_time.h b/roms/ipxe/src/include/ipxe/linux/linux_time.h new file mode 100644 index 000000000..93a257730 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/linux/linux_uaccess.h b/roms/ipxe/src/include/ipxe/linux/linux_uaccess.h index 1b4961177..e4dfdd357 100644 --- a/roms/ipxe/src/include/ipxe/linux/linux_uaccess.h +++ b/roms/ipxe/src/include/ipxe/linux/linux_uaccess.h @@ -71,6 +71,12 @@ UACCESS_INLINE(linux, userptr_add)(userptr_t userptr, off_t offset) return trivial_userptr_add(userptr, offset); } +static inline __always_inline off_t +UACCESS_INLINE(linux, userptr_sub)(userptr_t userptr, userptr_t subtrahend) +{ + return trivial_userptr_sub ( userptr, subtrahend ); +} + 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) { diff --git a/roms/ipxe/src/include/ipxe/list.h b/roms/ipxe/src/include/ipxe/list.h index ab4c119dd..0d0973077 100644 --- a/roms/ipxe/src/include/ipxe/list.h +++ b/roms/ipxe/src/include/ipxe/list.h @@ -42,9 +42,9 @@ struct list_head { * * @v list List head */ -#define INIT_LIST_HEAD( list ) do { \ - (list)->next = (list); \ - (list)->prev = (list); \ +#define INIT_LIST_HEAD( list ) do { \ + (list)->next = (list); \ + (list)->prev = (list); \ } while ( 0 ) /** @@ -52,43 +52,35 @@ struct list_head { * * @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) ); \ +#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) ); \ +#define list_add( new, head ) do { \ + list_check ( (head) ); \ + extern_list_add ( (new), (head) ); \ } while ( 0 ) +static inline void inline_list_add ( struct list_head *new, + struct list_head *head ) { + struct list_head *prev = head; + struct list_head *next = head->next; + next->prev = (new); + (new)->next = next; + (new)->prev = prev; + prev->next = (new); +} +extern void extern_list_add ( struct list_head *new, + struct list_head *head ); /** * Add a new entry to the tail of a list @@ -96,26 +88,21 @@ static inline void list_add ( struct list_head *new, struct list_head *head ) { * @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) ); \ +#define list_add_tail( new, head ) do { \ + list_check ( (head) ); \ + extern_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; +static inline void inline_list_add_tail ( struct list_head *new, + struct list_head *head ) { + struct list_head *prev = head->prev; + struct list_head *next = head; + next->prev = (new); + (new)->next = next; + (new)->prev = prev; + prev->next = (new); } +extern void extern_list_add_tail ( struct list_head *new, + struct list_head *head ); /** * Delete an entry from a list @@ -125,25 +112,199 @@ static inline void __list_del ( struct list_head *prev, * 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) ); \ +#define list_del( list ) do { \ + list_check ( (list) ); \ + inline_list_del ( (list) ); \ } while ( 0 ) +static inline void inline_list_del ( struct list_head *list ) { + struct list_head *next = (list)->next; + struct list_head *prev = (list)->prev; + next->prev = prev; + prev->next = next; +} +extern void extern_list_del ( struct list_head *list ); /** * Test whether a list is empty * * @v list List head */ -static inline int list_empty ( const struct list_head *list ) { +#define list_empty( list ) ( { \ + list_check ( (list) ); \ + inline_list_empty ( (list) ); } ) +static inline int inline_list_empty ( const struct list_head *list ) { return ( list->next == list ); } -#define list_empty( list ) ( { \ - list_check ( (list) ); \ - list_empty ( (list) ); } ) +extern int extern_list_empty ( const struct list_head *list ); + +/** + * Test whether a list has just one entry + * + * @v list List to test + */ +#define list_is_singular( list ) ( { \ + list_check ( (list) ); \ + inline_list_is_singular ( (list) ); } ) +static inline int inline_list_is_singular ( const struct list_head *list ) { + return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) ); +} +extern int extern_list_is_singular ( const struct list_head *list ); + +/** + * Test whether an entry is the last entry in list + * + * @v list List entry to test + * @v head List head + */ +#define list_is_last( list, head ) ( { \ + list_check ( (list) ); \ + list_check ( (head) ); \ + inline_list_is_last ( (list), (head) ); } ) +static inline int inline_list_is_last ( const struct list_head *list, + const struct list_head *head ) { + return ( list->next == head ); +} +extern int extern_list_is_last ( const struct list_head *list, + const struct list_head *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. + */ +#define list_cut_position( new, list, entry ) do { \ + list_check ( (new) ); \ + assert ( list_empty ( (new) ) ); \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_cut_position ( (new), (list), (entry) ); \ + } while ( 0 ) +static inline void inline_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; + } +} +extern void extern_list_cut_position ( struct list_head *new, + struct list_head *list, + struct list_head *entry ); + +/** + * 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. + */ +#define list_splice( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_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; + } +} +extern void extern_list_splice ( const struct list_head *list, + struct list_head *entry ); + +/** + * 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. + */ +#define list_splice_tail( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_tail ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_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; + } +} +extern void extern_list_splice_tail ( const struct list_head *list, + struct list_head *entry ); + +/** + * 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. + */ +#define list_splice_init( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_init ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_list_splice_init ( struct list_head *list, + struct list_head *entry ) { + list_splice ( list, entry ); + INIT_LIST_HEAD ( list ); +} +extern void extern_list_splice_init ( struct list_head *list, + struct list_head *entry ); + +/** + * 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. + */ +#define list_splice_tail_init( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_tail_init ( (list), (entry) ); \ + } while ( 0 ) + +static inline void inline_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ) { + list_splice_tail ( list, entry ); + INIT_LIST_HEAD ( list ); +} +extern void extern_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ); /** * Get the container of a list entry @@ -153,8 +314,8 @@ static inline int list_empty ( const struct list_head *list ) { * @v member Name of list field within containing type * @ret container Containing object */ -#define list_entry( list, type, member ) ( { \ - list_check ( (list) ); \ +#define list_entry( list, type, member ) ( { \ + list_check ( (list) ); \ container_of ( list, type, member ); } ) /** @@ -165,11 +326,36 @@ static inline int list_empty ( const struct list_head *list ) { * @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 : \ +#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 * @@ -212,4 +398,75 @@ static inline int list_empty ( const struct list_head *list ) { 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 + */ +#define list_contains( entry, head ) ( { \ + list_check ( (head) ); \ + list_check ( (entry) ); \ + extern_list_contains ( (entry), (head) ); } ) +static inline int inline_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; +} +extern int extern_list_contains ( struct list_head *entry, + struct list_head *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/roms/ipxe/src/include/ipxe/malloc.h b/roms/ipxe/src/include/ipxe/malloc.h index c435a7ddb..bbd6cb898 100644 --- a/roms/ipxe/src/include/ipxe/malloc.h +++ b/roms/ipxe/src/include/ipxe/malloc.h @@ -23,7 +23,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); extern size_t freemem; -extern void * __malloc alloc_memblock ( size_t size, size_t align ); +extern void * __malloc alloc_memblock ( size_t size, size_t align, + size_t offset ); extern void free_memblock ( void *ptr, size_t size ); extern void mpopulate ( void *start, size_t len ); extern void mdumpfree ( void ); @@ -33,19 +34,37 @@ extern void mdumpfree ( void ); * * @v size Requested size * @v align Physical alignment + * @v offset Offset from 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 ); +static inline void * __malloc malloc_dma_offset ( size_t size, + size_t phys_align, + size_t offset ) { + void * ptr = alloc_memblock ( size, phys_align, offset ); if ( ptr && size ) VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 ); return ptr; } +/** + * 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 ) { + return malloc_dma_offset ( size, phys_align, 0 ); +} + /** * Free memory allocated with malloc_dma() * @@ -76,6 +95,17 @@ struct cache_discarder { #define CACHE_DISCARDERS __table ( struct cache_discarder, "cache_discarders" ) /** Declare a cache discarder */ -#define __cache_discarder __table_entry ( CACHE_DISCARDERS, 01 ) +#define __cache_discarder( cost ) __table_entry ( CACHE_DISCARDERS, cost ) + +/** @defgroup cache_cost Cache discarder costs + * + * @{ + */ + +#define CACHE_CHEAP 01 /**< Items with a low replacement cost */ +#define CACHE_NORMAL 02 /**< Items with a normal replacement cost */ +#define CACHE_EXPENSIVE 03 /**< Items with a high replacement cost */ + +/** @} */ #endif /* _IPXE_MALLOC_H */ diff --git a/roms/ipxe/src/include/ipxe/md5.h b/roms/ipxe/src/include/ipxe/md5.h index c3dfeb7e0..860bc4769 100644 --- a/roms/ipxe/src/include/ipxe/md5.h +++ b/roms/ipxe/src/include/ipxe/md5.h @@ -1,23 +1,72 @@ #ifndef _IPXE_MD5_H #define _IPXE_MD5_H -FILE_LICENCE ( GPL2_OR_LATER ); +/** @file + * + * MD5 algorithm + * + */ -struct digest_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]; +}; -#define MD5_DIGEST_SIZE 16 -#define MD5_BLOCK_WORDS 16 -#define MD5_HASH_WORDS 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 )); -struct md5_ctx { - u32 hash[MD5_HASH_WORDS]; - u32 block[MD5_BLOCK_WORDS]; - u64 byte_count; +/** 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 ) ]; }; -#define MD5_CTX_SIZE sizeof ( struct md5_ctx ) +/** 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; diff --git a/roms/ipxe/src/include/ipxe/memblock.h b/roms/ipxe/src/include/ipxe/memblock.h new file mode 100644 index 000000000..13af3e433 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/memblock.h @@ -0,0 +1,17 @@ +#ifndef _IPXE_MEMBLOCK_H +#define _IPXE_MEMBLOCK_H + +/** @file + * + * Largest memory block + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/uaccess.h> + +extern size_t largest_memblock ( userptr_t *start ); + +#endif /* _IPXE_MEMBLOCK_H */ diff --git a/roms/ipxe/src/include/ipxe/menu.h b/roms/ipxe/src/include/ipxe/menu.h new file mode 100644 index 000000000..993b027ea --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/mii.h b/roms/ipxe/src/include/ipxe/mii.h new file mode 100644 index 000000000..cf462418a --- /dev/null +++ b/roms/ipxe/src/include/ipxe/mii.h @@ -0,0 +1,87 @@ +#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_restart ( struct mii_interface *mii ); +extern int mii_reset ( struct mii_interface *mii ); + +#endif /* _IPXE_MII_H */ diff --git a/roms/ipxe/src/include/ipxe/net80211.h b/roms/ipxe/src/include/ipxe/net80211.h index 3c30f06c4..771872c82 100644 --- a/roms/ipxe/src/include/ipxe/net80211.h +++ b/roms/ipxe/src/include/ipxe/net80211.h @@ -272,7 +272,7 @@ enum net80211_crypto_alg { #define NET80211_MAX_RATES 16 /** The maximum number of channels we allow to be configured simultaneously */ -#define NET80211_MAX_CHANNELS 32 +#define NET80211_MAX_CHANNELS 40 /** Seconds we'll wait to get all fragments of a packet */ #define NET80211_FRAG_TIMEOUT 2 diff --git a/roms/ipxe/src/include/ipxe/netdevice.h b/roms/ipxe/src/include/ipxe/netdevice.h index e49191f4a..e5dbd996b 100644 --- a/roms/ipxe/src/include/ipxe/netdevice.h +++ b/roms/ipxe/src/include/ipxe/netdevice.h @@ -66,20 +66,23 @@ struct net_protocol { /** * 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 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 ); + 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 + * @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). @@ -97,6 +100,12 @@ struct net_protocol { 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 * @@ -125,11 +134,12 @@ struct ll_protocol { * @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 ); + uint16_t *net_proto, unsigned int *flags ); /** * Initialise link-layer address * @@ -178,8 +188,17 @@ struct ll_protocol { uint8_t ll_addr_len; /** Link-layer header length */ uint8_t ll_header_len; + /** Flags */ + unsigned int flags; }; +/** Local link-layer address functions only as a name + * + * This flag indicates that the local link-layer address cannot + * directly be used as a destination address by a remote node. + */ +#define LL_NAME_ONLY 0x0001 + /** Network device operations */ struct net_device_operations { /** Open network device @@ -586,6 +605,8 @@ netdev_rx_frozen ( struct net_device *netdev ) { 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 ); @@ -609,7 +630,7 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, 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 ); + const void *ll_source, unsigned int flags ); extern void net_poll ( void ); /** diff --git a/roms/ipxe/src/include/ipxe/null_entropy.h b/roms/ipxe/src/include/ipxe/null_entropy.h new file mode 100644 index 000000000..646d1a17e --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/null_sanboot.h b/roms/ipxe/src/include/ipxe/null_sanboot.h index 341a9a1d2..2b3a2c74d 100644 --- a/roms/ipxe/src/include/ipxe/null_sanboot.h +++ b/roms/ipxe/src/include/ipxe/null_sanboot.h @@ -15,4 +15,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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/roms/ipxe/src/include/ipxe/null_time.h b/roms/ipxe/src/include/ipxe/null_time.h new file mode 100644 index 000000000..2b72cdf50 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/nvo.h b/roms/ipxe/src/include/ipxe/nvo.h index 995afd749..487f8b3f2 100644 --- a/roms/ipxe/src/include/ipxe/nvo.h +++ b/roms/ipxe/src/include/ipxe/nvo.h @@ -42,6 +42,10 @@ struct nvo_block { struct dhcp_options dhcpopts; }; +/** Name of non-volatile options settings block */ +#define NVO_SETTINGS_NAME "nvo" + +extern int nvo_applies ( struct settings *settings, struct setting *setting ); 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 ), diff --git a/roms/ipxe/src/include/ipxe/ocsp.h b/roms/ipxe/src/include/ipxe/ocsp.h new file mode 100644 index 000000000..fe825fd06 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/ocsp.h @@ -0,0 +1,102 @@ +#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 + +/** 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; + /** URI string */ + char *uri_string; + /** 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/roms/ipxe/src/include/ipxe/parseopt.h b/roms/ipxe/src/include/ipxe/parseopt.h index eed40b769..b492a51e5 100644 --- a/roms/ipxe/src/include/ipxe/parseopt.h +++ b/roms/ipxe/src/include/ipxe/parseopt.h @@ -13,7 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stddef.h> struct net_device; -struct image; +struct menu; /** A command-line option descriptor */ struct option_descriptor { @@ -117,9 +117,12 @@ struct command_descriptor { 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_image ( const char *text, struct image **image ); +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 ); diff --git a/roms/ipxe/src/include/ipxe/pci.h b/roms/ipxe/src/include/ipxe/pci.h index 960454d69..a6ed484f1 100644 --- a/roms/ipxe/src/include/ipxe/pci.h +++ b/roms/ipxe/src/include/ipxe/pci.h @@ -172,7 +172,7 @@ FILE_LICENCE ( GPL2_ONLY ); #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_AUX_POWER 0x01C0 /* Auxiliary 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 */ @@ -343,6 +343,9 @@ struct pci_driver { /** 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 ) diff --git a/roms/ipxe/src/include/ipxe/pending.h b/roms/ipxe/src/include/ipxe/pending.h new file mode 100644 index 000000000..51afb4370 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/pending.h @@ -0,0 +1,34 @@ +#ifndef _IPXE_PENDING_H +#define _IPXE_PENDING_H + +/** @file + * + * Pending operations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/list.h> + +/** A pending operation */ +struct pending_operation { + /** Pending count */ + unsigned int count; +}; + +/** + * Check if an operation is pending + * + * @v pending Pending operation + * @v is_pending Operation is pending + */ +static inline int is_pending ( struct pending_operation *pending ) { + return ( pending->count != 0 ); +} + +extern void pending_get ( struct pending_operation *pending ); +extern void pending_put ( struct pending_operation *pending ); +extern int pending_wait ( unsigned long timeout ); + +#endif /* _IPXE_PENDING_H */ diff --git a/roms/ipxe/src/include/ipxe/process.h b/roms/ipxe/src/include/ipxe/process.h index 45c2af639..9b7579817 100644 --- a/roms/ipxe/src/include/ipxe/process.h +++ b/roms/ipxe/src/include/ipxe/process.h @@ -17,6 +17,20 @@ FILE_LICENCE ( GPL2_OR_LATER ); 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 * @@ -24,15 +38,81 @@ struct process { * Returning from this method is isomorphic to yielding the * CPU to another process. */ - void ( * step ) ( struct process *process ); - /** Reference counter - * - * If this interface is not part of a reference-counted - * object, this field may be NULL. - */ - struct refcnt *refcnt; + 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 ); @@ -41,14 +121,15 @@ extern void step ( void ); * Initialise process without adding to process list * * @v process Process - * @v step Process' step() method + * @v desc Process descriptor + * @v refcnt Containing object reference count, or NULL */ static inline __attribute__ (( always_inline )) void process_init_stopped ( struct process *process, - void ( * step ) ( struct process *process ), + struct process_descriptor *desc, struct refcnt *refcnt ) { INIT_LIST_HEAD ( &process->list ); - process->step = step; + process->desc = desc; process->refcnt = refcnt; } @@ -56,13 +137,14 @@ process_init_stopped ( struct process *process, * Initialise process and add to process list * * @v process Process - * @v step Process' step() method + * @v desc Process descriptor + * @v refcnt Containing object reference count, or NULL */ static inline __attribute__ (( always_inline )) void process_init ( struct process *process, - void ( * step ) ( struct process *process ), + struct process_descriptor *desc, struct refcnt *refcnt ) { - process_init_stopped ( process, step, refcnt ); + process_init_stopped ( process, desc, refcnt ); process_add ( process ); } @@ -88,4 +170,36 @@ process_running ( struct process *process ) { */ #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/roms/ipxe/src/include/ipxe/random_nz.h b/roms/ipxe/src/include/ipxe/random_nz.h new file mode 100644 index 000000000..6bb80d2ab --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/rbg.h b/roms/ipxe/src/include/ipxe/rbg.h new file mode 100644 index 000000000..9689142f8 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/retry.h b/roms/ipxe/src/include/ipxe/retry.h index 87f69a5d7..c514822b2 100644 --- a/roms/ipxe/src/include/ipxe/retry.h +++ b/roms/ipxe/src/include/ipxe/retry.h @@ -85,6 +85,7 @@ 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 ); +extern void retry_poll ( void ); /** * Start timer with no delay diff --git a/roms/ipxe/src/include/ipxe/rootcert.h b/roms/ipxe/src/include/ipxe/rootcert.h new file mode 100644 index 000000000..6525df87a --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/rotate.h b/roms/ipxe/src/include/ipxe/rotate.h index 745d84e6c..ba271ca74 100644 --- a/roms/ipxe/src/include/ipxe/rotate.h +++ b/roms/ipxe/src/include/ipxe/rotate.h @@ -10,19 +10,23 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> -static inline uint32_t rol32 ( uint32_t data, unsigned int rotation ) { +static inline __attribute__ (( always_inline )) uint32_t +rol32 ( uint32_t data, unsigned int rotation ) { return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) ); } -static inline uint32_t ror32 ( uint32_t data, unsigned int rotation ) { +static inline __attribute__ (( always_inline )) uint32_t +ror32 ( uint32_t data, unsigned int rotation ) { return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) ); } -static inline uint64_t rol64 ( uint64_t data, unsigned int rotation ) { +static inline __attribute__ (( always_inline )) uint64_t +rol64 ( uint64_t data, unsigned int rotation ) { return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) ); } -static inline uint64_t ror64 ( uint64_t data, unsigned int rotation ) { +static inline __attribute__ (( always_inline )) uint64_t +ror64 ( uint64_t data, unsigned int rotation ) { return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) ); } diff --git a/roms/ipxe/src/include/ipxe/rsa.h b/roms/ipxe/src/include/ipxe/rsa.h index a080f9f08..1a5ad8bab 100644 --- a/roms/ipxe/src/include/ipxe/rsa.h +++ b/roms/ipxe/src/include/ipxe/rsa.h @@ -1,12 +1,81 @@ #ifndef _IPXE_RSA_H #define _IPXE_RSA_H +/** @file + * + * RSA public-key cryptography + */ + FILE_LICENCE ( GPL2_OR_LATER ); -struct pubkey_algorithm; +#include <ipxe/crypto.h> +#include <ipxe/bigint.h> +#include <ipxe/asn1.h> +#include <ipxe/tables.h> -extern struct pubkey_algorithm rsa_algorithm; +/** 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 ) -#include "crypto/axtls/crypto.h" +/** 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/roms/ipxe/src/include/ipxe/sanboot.h b/roms/ipxe/src/include/ipxe/sanboot.h index 913282eb5..14c8a5da4 100644 --- a/roms/ipxe/src/include/ipxe/sanboot.h +++ b/roms/ipxe/src/include/ipxe/sanboot.h @@ -58,12 +58,19 @@ struct uri; /* 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 Requested drive number - * @ret drive Assigned drive number, or negative error + * @v drive Drive number + * @ret rc Return status code */ int san_hook ( struct uri *uri, unsigned int drive ); diff --git a/roms/ipxe/src/include/ipxe/sec80211.h b/roms/ipxe/src/include/ipxe/sec80211.h index 59ca3eb85..3ca3d84f2 100644 --- a/roms/ipxe/src/include/ipxe/sec80211.h +++ b/roms/ipxe/src/include/ipxe/sec80211.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_SEC80211_H diff --git a/roms/ipxe/src/include/ipxe/serial.h b/roms/ipxe/src/include/ipxe/serial.h index c16e56ae6..b47b1d125 100644 --- a/roms/ipxe/src/include/ipxe/serial.h +++ b/roms/ipxe/src/include/ipxe/serial.h @@ -12,5 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); extern void serial_putc ( int ch ); extern int serial_getc ( void ); extern int serial_ischar ( void ); +extern int serial_initialized; #endif /* _IPXE_SERIAL_H */ diff --git a/roms/ipxe/src/include/ipxe/settings.h b/roms/ipxe/src/include/ipxe/settings.h index 0f1ec5bac..3f8876020 100644 --- a/roms/ipxe/src/include/ipxe/settings.h +++ b/roms/ipxe/src/include/ipxe/settings.h @@ -83,7 +83,8 @@ struct setting { #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_MISC 13 /**< Miscellaneous settings */ +#define SETTING_CRYPTO 13 /**< Cryptography settings */ +#define SETTING_MISC 14 /**< Miscellaneous settings */ /** @} */ @@ -161,25 +162,24 @@ struct setting_type { * This is the name exposed to the user (e.g. "string"). */ const char *name; - /** Parse and set value of setting + /** Parse formatted setting value * - * @v settings Settings block - * @v setting Setting to store - * @v value Formatted setting data - * @ret rc Return status code + * @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 ( * storef ) ( struct settings *settings, struct setting *setting, - const char *value ); - /** Fetch and format value of setting + int ( * parse ) ( const char *value, void *buf, size_t len ); + /** Format setting value * - * @v settings Settings block - * @v setting Setting to fetch + * @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 ( * fetchf ) ( struct settings *settings, struct setting *setting, - char *buf, size_t len ); + int ( * format ) ( const void *raw, size_t raw_len, char *buf, + size_t len ); }; /** Configuration setting type table */ @@ -241,6 +241,8 @@ 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 ); @@ -267,22 +269,33 @@ extern int fetch_uuid_setting ( struct settings *settings, extern void clear_settings ( struct settings *settings ); extern int setting_cmp ( struct setting *a, struct setting *b ); +extern struct settings * find_child_settings ( struct settings *parent, + const char *name ); 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 store_named_setting ( const char *name, + struct setting_type *default_type, + const void *data, size_t len ); +extern int storef_named_setting ( const char *name, + struct setting_type *default_type, + 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 int fetchf_named_setting_copy ( const char *name, char **data ); 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; @@ -291,6 +304,7 @@ 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 ); @@ -298,6 +312,7 @@ 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 domain_setting __setting ( SETTING_IPv4_EXTRA ); 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 ); @@ -352,22 +367,6 @@ static inline int delete_setting ( struct settings *settings, return store_setting ( settings, setting, NULL, 0 ); } -/** - * 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 - */ -static inline int fetchf_setting ( struct settings *settings, - struct setting *setting, - char *buf, size_t len ) { - return setting->type->fetchf ( settings, setting, buf, len ); -} - /** * Delete named setting * @@ -375,7 +374,7 @@ static inline int fetchf_setting ( struct settings *settings, * @ret rc Return status code */ static inline int delete_named_setting ( const char *name ) { - return storef_named_setting ( name, NULL ); + return store_named_setting ( name, NULL, NULL, 0 ); } /** diff --git a/roms/ipxe/src/include/ipxe/sha1.h b/roms/ipxe/src/include/ipxe/sha1.h index 9b6f55147..a97035ec7 100644 --- a/roms/ipxe/src/include/ipxe/sha1.h +++ b/roms/ipxe/src/include/ipxe/sha1.h @@ -1,24 +1,80 @@ #ifndef _IPXE_SHA1_H #define _IPXE_SHA1_H +/** @file + * + * SHA-1 algorithm + * + */ + FILE_LICENCE ( GPL2_OR_LATER ); -#include "crypto/axtls/crypto.h" +#include <stdint.h> +#include <ipxe/crypto.h> -struct digest_algorithm; +/** An SHA-1 digest */ +struct sha1_digest { + /** Hash output */ + uint32_t h[5]; +}; -#define SHA1_CTX_SIZE sizeof ( SHA1_CTX ) -#define SHA1_DIGEST_SIZE SHA1_SIZE +/** 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; +}; -extern struct digest_algorithm sha1_algorithm; +/** 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 ) ]; +}; -/* SHA1-wrapping functions defined in sha1extra.c: */ +/** 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 )); -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 ); +/** 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; -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 ); +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/roms/ipxe/src/include/ipxe/sha256.h b/roms/ipxe/src/include/ipxe/sha256.h new file mode 100644 index 000000000..9aa9f3e57 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/syslog.h b/roms/ipxe/src/include/ipxe/syslog.h index 25edc6b0c..131692654 100644 --- a/roms/ipxe/src/include/ipxe/syslog.h +++ b/roms/ipxe/src/include/ipxe/syslog.h @@ -9,6 +9,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <syslog.h> + /** Syslog server port */ #define SYSLOG_PORT 514 @@ -18,19 +20,22 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #define SYSLOG_BUFSIZE 128 -/** Syslog facility +/** Syslog default facility * * This is a policy decision */ -#define SYSLOG_FACILITY 0 /* kernel */ +#define SYSLOG_DEFAULT_FACILITY 0 /* kernel */ -/** Syslog severity +/** Syslog default severity * * This is a policy decision */ -#define SYSLOG_SEVERITY 6 /* informational */ +#define SYSLOG_DEFAULT_SEVERITY LOG_INFO /** Syslog priority */ #define SYSLOG_PRIORITY( facility, severity ) ( 8 * (facility) + (severity) ) +extern int syslog_send ( struct interface *xfer, unsigned int severity, + const char *message, const char *terminator ); + #endif /* _IPXE_SYSLOG_H */ diff --git a/roms/ipxe/src/include/ipxe/tcp.h b/roms/ipxe/src/include/ipxe/tcp.h index 197712b11..6b6691175 100644 --- a/roms/ipxe/src/include/ipxe/tcp.h +++ b/roms/ipxe/src/include/ipxe/tcp.h @@ -54,6 +54,31 @@ struct tcp_mss_option { /** Code for the TCP MSS option */ #define TCP_OPTION_MSS 2 +/** TCP window scale option */ +struct tcp_window_scale_option { + uint8_t kind; + uint8_t length; + uint8_t scale; +} __attribute__ (( packed )); + +/** Padded TCP window scale option (used for sending) */ +struct tcp_window_scale_padded_option { + uint8_t nop; + struct tcp_window_scale_option wsopt; +} __attribute (( packed )); + +/** Code for the TCP window scale option */ +#define TCP_OPTION_WS 3 + +/** Advertised TCP window scale + * + * Using a scale factor of 2**9 provides for a maximum window of 32MB, + * which is sufficient to allow Gigabit-speed transfers with a 200ms + * RTT. The minimum advertised window is 512 bytes, which is still + * less than a single packet. + */ +#define TCP_RX_WINDOW_SCALE 9 + /** TCP timestamp option */ struct tcp_timestamp_option { uint8_t kind; @@ -75,7 +100,9 @@ struct tcp_timestamp_padded_option { struct tcp_options { /** MSS option, if present */ const struct tcp_mss_option *mssopt; - /** Timestampe option, if present */ + /** Window scale option, if present */ + const struct tcp_window_scale_option *wsopt; + /** Timestamp option, if present */ const struct tcp_timestamp_option *tsopt; }; @@ -260,29 +287,31 @@ struct tcp_options { /** * 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. + * The maximum bandwidth on any link is limited by + * + * max_bandwidth * round_trip_time = tcp_window + * + * Some rough expectations for achievable bandwidths over various + * links are: + * + * a) Gigabit LAN: expected bandwidth 125MB/s, typical RTT 0.5ms, + * minimum required window 64kB * - * 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 + * b) Home Internet connection: expected bandwidth 10MB/s, typical + * RTT 25ms, minimum required window 256kB * - * max_bandwidth = ( tcp_window / round_trip_time ) + * c) WAN: expected bandwidth 2MB/s, typical RTT 100ms, minimum + * required window 200kB. * - * 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. + * The maximum possible value for the TCP window size is 1GB (using + * the maximum window scale of 2**14). However, it is advisable to + * keep the window size as small as possible (without limiting + * bandwidth), since in the event of a lost packet the window size + * represents the maximum amount that will need to be retransmitted. * - * 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. + * We therefore choose a maximum window size of 256kB. */ -//#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 ) -#define TCP_MAX_WINDOW_SIZE 8192 +#define TCP_MAX_WINDOW_SIZE ( 256 * 1024 ) /** * Path MTU @@ -308,6 +337,17 @@ struct tcp_options { */ #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_window_scale_padded_option ) + \ + sizeof ( struct tcp_timestamp_padded_option ) ) + /** * Compare TCP sequence numbers * diff --git a/roms/ipxe/src/include/ipxe/tcpip.h b/roms/ipxe/src/include/ipxe/tcpip.h index cdf554eae..34d7f88f4 100644 --- a/roms/ipxe/src/include/ipxe/tcpip.h +++ b/roms/ipxe/src/include/ipxe/tcpip.h @@ -13,6 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/socket.h> #include <ipxe/in.h> #include <ipxe/tables.h> +#include <bits/tcpip.h> struct io_buffer; struct net_device; @@ -121,8 +122,15 @@ extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip, 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 generic_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ); extern uint16_t tcpip_chksum ( const void *data, size_t len ); +/* Use generic_tcpip_continue_chksum() if no architecture-specific + * version is available + */ +#ifndef tcpip_continue_chksum +#define tcpip_continue_chksum generic_tcpip_continue_chksum +#endif + #endif /* _IPXE_TCPIP_H */ diff --git a/roms/ipxe/src/include/ipxe/test.h b/roms/ipxe/src/include/ipxe/test.h new file mode 100644 index 000000000..8c361d284 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/threewire.h b/roms/ipxe/src/include/ipxe/threewire.h index 135ef56a3..b5513ecdd 100644 --- a/roms/ipxe/src/include/ipxe/threewire.h +++ b/roms/ipxe/src/include/ipxe/threewire.h @@ -61,6 +61,19 @@ init_at93cx6 ( struct spi_device *device, unsigned int organisation ) { 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 * diff --git a/roms/ipxe/src/include/ipxe/time.h b/roms/ipxe/src/include/ipxe/time.h new file mode 100644 index 000000000..673fe098a --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/tls.h b/roms/ipxe/src/include/ipxe/tls.h index 94cd322c8..f8a754096 100644 --- a/roms/ipxe/src/include/ipxe/tls.h +++ b/roms/ipxe/src/include/ipxe/tls.h @@ -16,7 +16,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/crypto.h> #include <ipxe/md5.h> #include <ipxe/sha1.h> +#include <ipxe/sha256.h> #include <ipxe/x509.h> +#include <ipxe/pending.h> +#include <ipxe/iobuf.h> /** A TLS header */ struct tls_header { @@ -40,6 +43,9 @@ struct tls_header { /** 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 @@ -73,6 +79,27 @@ struct tls_header { #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 server name extension */ +#define TLS_SERVER_NAME 0 +#define TLS_SERVER_NAME_HOST_NAME 0 + +/* TLS maximum fragment length extension */ +#define TLS_MAX_FRAGMENT_LENGTH 1 +#define TLS_MAX_FRAGMENT_LENGTH_512 1 +#define TLS_MAX_FRAGMENT_LENGTH_1024 2 +#define TLS_MAX_FRAGMENT_LENGTH_2048 3 +#define TLS_MAX_FRAGMENT_LENGTH_4096 4 /** TLS RX state machine state */ enum tls_rx_state { @@ -80,18 +107,18 @@ enum tls_rx_state { TLS_RX_DATA, }; -/** TLS TX state machine state */ -enum tls_tx_state { - TLS_TX_NONE = 0, - TLS_TX_CLIENT_HELLO, - TLS_TX_CLIENT_KEY_EXCHANGE, - TLS_TX_CHANGE_CIPHER, - TLS_TX_FINISHED, - TLS_TX_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 specification */ -struct tls_cipherspec { +/** A TLS cipher suite */ +struct tls_cipher_suite { /** Public-key encryption algorithm */ struct pubkey_algorithm *pubkey; /** Bulk encryption cipher algorithm */ @@ -99,7 +126,15 @@ struct tls_cipherspec { /** MAC digest algorithm */ struct digest_algorithm *digest; /** Key length */ - size_t key_len; + 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 */ @@ -112,6 +147,24 @@ struct tls_cipherspec { 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 */ @@ -128,16 +181,42 @@ struct tls_client_random { 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 */ @@ -154,18 +233,31 @@ struct tls_session { uint8_t server_random[32]; /** Client random bytes */ struct tls_client_random client_random; - /** MD5 context for handshake verification */ - uint8_t handshake_md5_ctx[MD5_CTX_SIZE]; - /** SHA1 context for handshake verification */ - uint8_t handshake_sha1_ctx[SHA1_CTX_SIZE]; + /** 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; - /** Hack: server RSA public key */ - struct x509_rsa_public_key rsa; + /** Server certificate chain */ + struct x509_chain *chain; + /** Certificate validator */ + struct interface validator; + + /** Client security negotiation pending operation */ + struct pending_operation client_negotiation; + /** Server security negotiation pending operation */ + struct pending_operation server_negotiation; /** TX sequence number */ uint64_t tx_seq; - /** TX state */ - enum tls_tx_state tx_state; + /** TX pending transmissions */ + unsigned int tx_pending; /** TX process */ struct process process; @@ -173,15 +265,36 @@ struct tls_session { 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; + /** Current received record header (static I/O buffer) */ + struct io_buffer rx_header_iobuf; + /** List of received data buffers */ + struct list_head rx_data; }; -extern int add_tls ( struct interface *xfer, +/** RX I/O buffer size + * + * The maximum fragment length extension is optional, and many common + * implementations (including OpenSSL) do not support it. We must + * therefore be prepared to receive records of up to 16kB in length. + * The chance of an allocation of this size failing is non-negligible, + * so we must split received data into smaller allocations. + */ +#define TLS_RX_BUFSIZE 4096 + +/** Minimum RX I/O buffer size + * + * To simplify manipulations, we ensure that no RX I/O buffer is + * smaller than this size. This allows us to assume that the MAC and + * padding are entirely contained within the final I/O buffer. + */ +#define TLS_RX_MIN_BUFSIZE 512 + +/** RX I/O buffer alignment */ +#define TLS_RX_ALIGN 16 + +extern int add_tls ( struct interface *xfer, const char *name, struct interface **next ); #endif /* _IPXE_TLS_H */ diff --git a/roms/ipxe/src/include/ipxe/uaccess.h b/roms/ipxe/src/include/ipxe/uaccess.h index b574c3183..95e943675 100644 --- a/roms/ipxe/src/include/ipxe/uaccess.h +++ b/roms/ipxe/src/include/ipxe/uaccess.h @@ -82,6 +82,18 @@ trivial_userptr_add ( userptr_t userptr, off_t offset ) { return ( userptr + offset ); } +/** + * Subtract user pointers + * + * @v userptr User pointer + * @v subtrahend User pointer to be subtracted + * @ret offset Offset + */ +static inline __always_inline off_t +trivial_userptr_sub ( userptr_t userptr, userptr_t subtrahend ) { + return ( userptr - subtrahend ); +} + /** * Copy data between user buffers * @@ -239,6 +251,15 @@ void * user_to_virt ( userptr_t userptr, off_t offset ); */ userptr_t userptr_add ( userptr_t userptr, off_t offset ); +/** + * Subtract user pointers + * + * @v userptr User pointer + * @v subtrahend User pointer to be subtracted + * @ret offset Offset + */ +off_t userptr_sub ( userptr_t userptr, userptr_t subtrahend ); + /** * Convert virtual address to a physical address * diff --git a/roms/ipxe/src/include/ipxe/uuid.h b/roms/ipxe/src/include/ipxe/uuid.h index 2f3c22482..5de56b94e 100644 --- a/roms/ipxe/src/include/ipxe/uuid.h +++ b/roms/ipxe/src/include/ipxe/uuid.h @@ -28,6 +28,6 @@ union uuid { uint8_t raw[16]; }; -extern char * uuid_ntoa ( union uuid *uuid ); +extern char * uuid_ntoa ( const union uuid *uuid ); #endif /* _IPXE_UUID_H */ diff --git a/roms/ipxe/src/include/ipxe/validator.h b/roms/ipxe/src/include/ipxe/validator.h new file mode 100644 index 000000000..23bdab423 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/ipxe/version.h b/roms/ipxe/src/include/ipxe/version.h new file mode 100644 index 000000000..aa894d7e8 --- /dev/null +++ b/roms/ipxe/src/include/ipxe/version.h @@ -0,0 +1,16 @@ +#ifndef _IPXE_VERSION_H +#define _IPXE_VERSION_H + +/** @file + * + * Version number + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +extern const int product_major_version; +extern const int product_minor_version; +extern const char *product_version; + +#endif /* _IPXE_VERSION_H */ diff --git a/roms/ipxe/src/include/ipxe/wpa.h b/roms/ipxe/src/include/ipxe/wpa.h index 293422828..44934b3b9 100644 --- a/roms/ipxe/src/include/ipxe/wpa.h +++ b/roms/ipxe/src/include/ipxe/wpa.h @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_WPA_H diff --git a/roms/ipxe/src/include/ipxe/x509.h b/roms/ipxe/src/include/ipxe/x509.h index 37c5a4ee5..a47942a75 100644 --- a/roms/ipxe/src/include/ipxe/x509.h +++ b/roms/ipxe/src/include/ipxe/x509.h @@ -10,32 +10,372 @@ 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> -struct asn1_cursor; +/** 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; +}; + +/** Margin of error allowed in X.509 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 X509_ERROR_MARGIN_TIME ( ( 12 * 60 + 30 ) * 60 ) + +/** 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; +}; -/** An X.509 RSA public key */ -struct x509_rsa_public_key { - /** Modulus */ - uint8_t *modulus; - /** Modulus length */ - size_t modulus_len; - /** Exponent */ - uint8_t *exponent; - /** Exponent length */ - size_t exponent_len; +/** 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; }; /** - * Free X.509 RSA public key + * Get reference to X.509 certificate * - * @v rsa_pubkey RSA public key + * @v cert X.509 certificate + * @ret cert X.509 certificate */ -static inline void -x509_free_rsa_public_key ( struct x509_rsa_public_key *rsa_pubkey ) { - free ( rsa_pubkey->modulus ); +static inline __attribute__ (( always_inline )) struct x509_certificate * +x509_get ( struct x509_certificate *cert ) { + ref_get ( &cert->refcnt ); + return cert; } -extern int x509_rsa_public_key ( const struct asn1_cursor *certificate, - struct x509_rsa_public_key *rsa_pubkey ); +/** + * 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/roms/ipxe/src/include/ipxe/xferbuf.h b/roms/ipxe/src/include/ipxe/xferbuf.h new file mode 100644 index 000000000..2ca871e59 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/linux_api.h b/roms/ipxe/src/include/linux_api.h index 066cdd305..94dc991f0 100644 --- a/roms/ipxe/src/include/linux_api.h +++ b/roms/ipxe/src/include/linux_api.h @@ -37,7 +37,6 @@ FILE_LICENCE(GPL2_OR_LATER); #include <linux/types.h> #include <linux/posix_types.h> typedef __kernel_pid_t pid_t; -typedef __kernel_time_t time_t; typedef __kernel_suseconds_t suseconds_t; typedef __kernel_loff_t loff_t; #include <linux/time.h> diff --git a/roms/ipxe/src/include/mii.h b/roms/ipxe/src/include/mii.h index 2baff2f18..e2afef854 100644 --- a/roms/ipxe/src/include/mii.h +++ b/roms/ipxe/src/include/mii.h @@ -1,144 +1,141 @@ -/* - * linux/mii.h: definitions for MII-compatible transceivers - * Originally drivers/net/sunhme.h. +#ifndef _MII_H_ +#define _MII_H_ + +/** @file * - * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) + * Media Independent Interface constants + * + * Extracted from Linux's include/linux/mii.h * - * Copied Form Linux 2.4.25 an unneeded items removed by: - * Timothy Legge (timlegge at etherboot dot org) + * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) * - * 03/26/2004 */ FILE_LICENCE ( GPL2_ONLY ); -#ifndef _MII_H_ -#define _MII_H_ - /* 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 */ +#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 */ +#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 */ +#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) +#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) +#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 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 */ +#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... */ +#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 */ +#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 /* Link partner local receiver status */ -#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */ -#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */ -#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */ +#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> @@ -157,63 +154,4 @@ struct mii_if_info { void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); }; - -extern int mii_link_ok (struct mii_if_info *mii); -extern void mii_check_link (struct mii_if_info *mii); -extern unsigned int mii_check_media (struct mii_if_info *mii, - unsigned int ok_to_print, - unsigned int init_media); - - -/** - * mii_nway_result - * @negotiated: value of MII ANAR and'd with ANLPAR - * - * Given a set of MII abilities, check each bit and returns the - * currently supported media, in the priority order defined by - * IEEE 802.3u. We use LPA_xxx constants but note this is not the - * value of LPA solely, as described above. - * - * The one exception to IEEE 802.3u is that 100baseT4 is placed - * between 100T-full and 100T-half. If your phy does not support - * 100T4 this is fine. If your phy places 100T4 elsewhere in the - * priority order, you will need to roll your own function. - */ -static inline unsigned int mii_nway_result (unsigned int negotiated) -{ - unsigned int ret; - - if (negotiated & LPA_100FULL) - ret = LPA_100FULL; - else if (negotiated & LPA_100BASE4) - ret = LPA_100BASE4; - else if (negotiated & LPA_100HALF) - ret = LPA_100HALF; - else if (negotiated & LPA_10FULL) - ret = LPA_10FULL; - else - ret = LPA_10HALF; - - return ret; -} - -/** - * mii_duplex - * @duplex_lock: Non-zero if duplex is locked at full - * @negotiated: value of MII ANAR and'd with ANLPAR - * - * A small helper function for a common case. Returns one - * if the media is operating or locked at full duplex, and - * returns zero otherwise. - */ -static inline unsigned int mii_duplex (unsigned int duplex_lock, - unsigned int negotiated) -{ - if (duplex_lock) - return 1; - if (mii_nway_result(negotiated) & LPA_DUPLEX) - return 1; - return 0; -} - #endif diff --git a/roms/ipxe/src/include/readline/readline.h b/roms/ipxe/src/include/readline/readline.h index 42dfd8c4c..0449a3f98 100644 --- a/roms/ipxe/src/include/readline/readline.h +++ b/roms/ipxe/src/include/readline/readline.h @@ -50,8 +50,8 @@ struct readline_history { }; extern void history_free ( struct readline_history *history ); -extern char * __malloc readline_history ( const char *prompt, - struct readline_history *history ); +extern int readline_history ( const char *prompt, const char *prefill, + struct readline_history *history, char **line ); extern char * __malloc readline ( const char *prompt ); #endif /* _READLINE_H */ diff --git a/roms/ipxe/src/include/stdarg.h b/roms/ipxe/src/include/stdarg.h index 78b261ae3..f317238a9 100644 --- a/roms/ipxe/src/include/stdarg.h +++ b/roms/ipxe/src/include/stdarg.h @@ -9,4 +9,30 @@ typedef __builtin_va_list va_list; #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/roms/ipxe/src/include/stddef.h b/roms/ipxe/src/include/stddef.h index c91a103f8..83a0f0ed6 100644 --- a/roms/ipxe/src/include/stddef.h +++ b/roms/ipxe/src/include/stddef.h @@ -26,5 +26,6 @@ FILE_LICENCE ( GPL2_ONLY ); #define __WCHAR_TYPE__ long int #endif typedef __WCHAR_TYPE__ wchar_t; +typedef __WINT_TYPE__ wint_t; #endif /* STDDEF_H */ diff --git a/roms/ipxe/src/include/stdio.h b/roms/ipxe/src/include/stdio.h index 84181f0a1..91840af5b 100644 --- a/roms/ipxe/src/include/stdio.h +++ b/roms/ipxe/src/include/stdio.h @@ -6,6 +6,10 @@ 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, ... ); diff --git a/roms/ipxe/src/include/stdlib.h b/roms/ipxe/src/include/stdlib.h index 19a7c8e09..3d30858ff 100644 --- a/roms/ipxe/src/include/stdlib.h +++ b/roms/ipxe/src/include/stdlib.h @@ -5,7 +5,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> #include <assert.h> -#include <ctype.h> /***************************************************************************** * @@ -18,9 +17,6 @@ static inline int strtoul_base ( const char **pp, int base ) { const char *p = *pp; - while ( isspace ( *p ) ) - p++; - if ( base == 0 ) { base = 10; if ( *p == '0' ) { diff --git a/roms/ipxe/src/include/string.h b/roms/ipxe/src/include/string.h index 2fd6acf16..3482e1b22 100644 --- a/roms/ipxe/src/include/string.h +++ b/roms/ipxe/src/include/string.h @@ -37,6 +37,7 @@ 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 * memcpy ( void *dest, const void *src, size_t len ) __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; diff --git a/roms/ipxe/src/include/sys/time.h b/roms/ipxe/src/include/sys/time.h index 21fb7e99d..6c9b7421b 100644 --- a/roms/ipxe/src/include/sys/time.h +++ b/roms/ipxe/src/include/sys/time.h @@ -1,20 +1,18 @@ #ifndef _SYS_TIME_H #define _SYS_TIME_H -#include <time.h> +/** @file + * + * Date and time + */ -typedef unsigned long suseconds_t; +#include <stdint.h> -struct timeval { - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ -}; - -struct timezone { - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -extern int gettimeofday ( struct timeval *tv, struct timezone *tz ); +/** 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/roms/ipxe/src/include/syslog.h b/roms/ipxe/src/include/syslog.h new file mode 100644 index 000000000..93f32f867 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/time.h b/roms/ipxe/src/include/time.h index 6ea927c32..bc73af4cd 100644 --- a/roms/ipxe/src/include/time.h +++ b/roms/ipxe/src/include/time.h @@ -1,21 +1,50 @@ #ifndef _TIME_H #define _TIME_H -typedef unsigned long time_t; +/** @file + * + * Date and time + */ +#include <sys/time.h> +#include <ipxe/time.h> + +/** Broken-down time */ struct tm { - int tm_sec; /* seconds */ - int tm_min; /* minutes */ - int tm_hour; /* hours */ - int tm_mday; /* day of the month */ - int tm_mon; /* month */ - int tm_year; /* year */ - int tm_wday; /* day of the week */ - int tm_yday; /* day in the year */ - int tm_isdst; /* daylight saving time */ + /** 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; }; -extern time_t time ( time_t *t ); +/** + * 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 ); diff --git a/roms/ipxe/src/include/usr/autoboot.h b/roms/ipxe/src/include/usr/autoboot.h index a608b3dce..25b9f073d 100644 --- a/roms/ipxe/src/include/usr/autoboot.h +++ b/roms/ipxe/src/include/usr/autoboot.h @@ -14,7 +14,19 @@ struct net_device; struct uri; struct settings; -extern int uriboot ( struct uri *filename, struct uri *root_path ); +/** 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 ); diff --git a/roms/ipxe/src/include/usr/imgmgmt.h b/roms/ipxe/src/include/usr/imgmgmt.h index 1c0a212e3..8db5c9780 100644 --- a/roms/ipxe/src/include/usr/imgmgmt.h +++ b/roms/ipxe/src/include/usr/imgmgmt.h @@ -11,46 +11,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/image.h> -extern int register_and_put_image ( struct image *image ); -extern int register_and_probe_image ( struct image *image ); -extern int register_and_select_image ( struct image *image ); -extern int register_and_boot_image ( struct image *image ); -extern int register_and_replace_image ( struct image *image ); -extern int imgdownload ( struct uri *uri, const char *name, const char *cmdline, - int ( * action ) ( struct image *image ) ); -extern int imgdownload_string ( const char *uri_string, const char *name, - const char *cmdline, - int ( * action ) ( struct image *image ) ); +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 ); -extern void imgfree ( struct image *image ); - -/** - * Select an image for execution - * - * @v image Image - * @ret rc Return status code - */ -static inline int imgselect ( struct image *image ) { - return image_select ( image ); -} - -/** - * Find the previously-selected image - * - * @ret image Image, or NULL - */ -static inline struct image * imgautoselect ( void ) { - return image_find_selected(); -} - -/** - * Execute an image - * - * @v image Image - * @ret rc Return status code - */ -static inline int imgexec ( struct image *image ) { - return image_exec ( image ); -} #endif /* _USR_IMGMGMT_H */ diff --git a/roms/ipxe/src/include/usr/imgtrust.h b/roms/ipxe/src/include/usr/imgtrust.h new file mode 100644 index 000000000..f47105af0 --- /dev/null +++ b/roms/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/roms/ipxe/src/include/usr/nslookup.h b/roms/ipxe/src/include/usr/nslookup.h new file mode 100644 index 000000000..d34649e9f --- /dev/null +++ b/roms/ipxe/src/include/usr/nslookup.h @@ -0,0 +1,14 @@ +#ifndef _USR_NSLOOKUP_H +#define _USR_NSLOOKUP_H + +/** @file + * + * Standalone name resolution + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +extern int nslookup ( const char *name, const char *setting_name ); + +#endif /* _USR_NSLOOKUP_H */ diff --git a/roms/ipxe/src/include/wchar.h b/roms/ipxe/src/include/wchar.h new file mode 100644 index 000000000..ba349aae8 --- /dev/null +++ b/roms/ipxe/src/include/wchar.h @@ -0,0 +1,29 @@ +#ifndef WCHAR_H +#define WCHAR_H + +FILE_LICENCE ( GPL2_ONLY ); + +#include <stddef.h> + +typedef void mbstate_t; + +/** + * Convert wide character to multibyte sequence + * + * @v buf Buffer + * @v wc Wide character + * @v ps Shift state + * @ret len Number of characters written + * + * This is a stub implementation, sufficient to handle basic ASCII + * characters. + */ +static inline __attribute__ (( always_inline )) +size_t wcrtomb ( char *buf, wchar_t wc, mbstate_t *ps __unused ) { + *buf = wc; + return 1; +} + +extern size_t wcslen ( const wchar_t *string ); + +#endif /* WCHAR_H */ diff --git a/roms/ipxe/src/interface/bofm/bofm.c b/roms/ipxe/src/interface/bofm/bofm.c index dfa76d325..b0e92b27c 100644 --- a/roms/ipxe/src/interface/bofm/bofm.c +++ b/roms/ipxe/src/interface/bofm/bofm.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -181,14 +182,14 @@ static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { /* Retrieve current MAC address */ if ( ( rc = bofm->op->harvest ( bofm, en->mport, mac ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " port %d could not harvest: %s\n", + 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 " port %d harvested MAC %s\n", + 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 ); @@ -197,7 +198,7 @@ static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { /* 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 " port %d MAC %s", + 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; @@ -207,7 +208,7 @@ static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { if ( ( en->options & BOFM_EN_EN_A ) && ( en->options & BOFM_EN_USAGE_ENTRY ) && ( ! ( en->options & BOFM_EN_USAGE_HARVEST ) ) ) { - DBG ( "BOFM: " PCI_FMT " port %d applied MAC %s\n", + 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 ) ); @@ -215,7 +216,7 @@ static int bofm_en ( struct bofm_device *bofm, struct bofm_en *en ) { /* Store MAC address */ if ( ( rc = bofm->op->update ( bofm, en->mport, mac ) ) != 0 ) { - DBG ( "BOFM: " PCI_FMT " port %d could not update: %s\n", + DBG ( "BOFM: " PCI_FMT " mport %d could not update: %s\n", PCI_ARGS ( bofm->pci ), en->mport, strerror ( rc ) ); return rc; } @@ -303,14 +304,19 @@ int bofm ( userptr_t bofmtab, struct pci_device *pci ) { 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 ); + 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 " ignored\n", + DBG ( "BOFM: " PCI_FMT " mport %d ignored\n", PCI_BUS ( en.busdevfn ), PCI_SLOT ( en.busdevfn ), - PCI_FUNC ( en.busdevfn ) ); + PCI_FUNC ( en.busdevfn ), en.mport ); continue; } if ( ( rc = bofm_en ( bofm, &en ) ) == 0 ) { diff --git a/roms/ipxe/src/interface/efi/efi_bofm.c b/roms/ipxe/src/interface/efi/efi_bofm.c index 1d647db43..c313d2e97 100644 --- a/roms/ipxe/src/interface/efi/efi_bofm.c +++ b/roms/ipxe/src/interface/efi/efi_bofm.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -97,6 +98,9 @@ typedef struct { 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, @@ -112,20 +116,27 @@ typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) ( 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; }; -typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 { +struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 { UINT32 Signature; UINT32 Reserved1; UINT64 Reserved2; - IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus; + IBM_BOFM_DRIVER_CONFIGURATION_STATUS2 SetStatus; IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport; IBM_BOFM_TABLE BofmTable; -} IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2; +}; /*************************************************************************** * @@ -165,7 +176,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_STATUS efirc; int rc; - DBGCP ( efidrv, "BOFM DRIVER_SUPPORTED %p (%p)\n", device, child ); + DBGCP ( efidrv, "EFIBOFM DRIVER_SUPPORTED %p (%p)\n", device, child ); /* Create corresponding PCI device, if any */ efipci = efipci_create ( efidrv, device ); @@ -176,7 +187,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, /* Look for a BOFM driver */ if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) { - DBGC2 ( efidrv, "BOFM " PCI_FMT " has no driver\n", + DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); efirc = EFI_UNSUPPORTED; goto err_no_driver; @@ -185,8 +196,8 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { - DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n", - PCI_ARGS ( &efipci->pci ) ); + DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " + "protocol\n", PCI_ARGS ( &efipci->pci ) ); efirc = EFI_UNSUPPORTED; goto err_not_bofm; } @@ -196,13 +207,13 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, 0x04 /* Can change MAC */, 0x00 /* No iSCSI */, 0x02 /* Version */ ))!=0){ - DBGC ( efidrv, "BOFM " PCI_FMT " could not register support: " - "%s\n", PCI_ARGS ( &efipci->pci ), + DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register " + "support: %s\n", PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); goto err_cannot_register; } - DBGC ( efidrv, "BOFM " PCI_FMT " is supported by driver \"%s\"\n", + DBGC ( efidrv, "EFIBOFM " PCI_FMT " is supported by driver \"%s\"\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name ); /* Destroy temporary PCI device */ @@ -241,11 +252,12 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, void *interface; } bofm2; struct efi_pci_device *efipci; - userptr_t bofmtab; + IBM_BOFM_TABLE *bofmtab; + IBM_BOFM_TABLE *bofmtab2; EFI_STATUS efirc; int bofmrc; - DBGCP ( efidrv, "BOFM DRIVER_START %p (%p)\n", device, child ); + DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child ); /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); @@ -261,46 +273,70 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { - DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n", - PCI_ARGS ( &efipci->pci ) ); + 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 ) { - DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM2 protocol\n", - PCI_ARGS ( &efipci->pci ) ); - /* Not a fatal error; may be a BOFM1-only system */ - bofm2.bofm2 = NULL; - } - - /* Select appropriate BOFM table (v1 or v2) to use */ - if ( bofm2.bofm2 ) { - DBGC ( efidrv, "BOFM " PCI_FMT " using version 2 BOFM table\n", - PCI_ARGS ( &efipci->pci ) ); + &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 ); - assert ( bofm2.bofm2->SetStatus == bofm1.bofm1->SetStatus ); - bofmtab = virt_to_user ( &bofm2.bofm2->BofmTable ); } else { - DBGC ( efidrv, "BOFM " PCI_FMT " using version 1 BOFM table\n", - PCI_ARGS ( &efipci->pci ) ); - bofmtab = virt_to_user ( &bofm1.bofm1->BofmTable ); + 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 */ - bofmrc = bofm ( bofmtab, &efipci->pci ); - DBGC ( efidrv, "BOFM " PCI_FMT " status %08x\n", + 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 ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, FALSE, - bofmrc ) ) != 0 ) { - DBGC ( efidrv, "BOFM " PCI_FMT " could not set BOFM status: " - "%s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); - goto err_set_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 */ @@ -332,7 +368,7 @@ static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); - DBGCP ( efidrv, "BOFM DRIVER_STOP %p (%ld %p)\n", + DBGCP ( efidrv, "EFIBOFM DRIVER_STOP %p (%ld %p)\n", device, ( ( unsigned long ) num_children ), children ); return 0; @@ -353,12 +389,12 @@ static void efi_bofm_driver_init ( void ) { /* Install driver */ if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { - DBGC ( efidrv, "BOFM could not install driver: %s\n", + DBGC ( efidrv, "EFIBOFM could not install driver: %s\n", efi_strerror ( efirc ) ); return; } - DBGC ( efidrv, "BOFM driver installed\n" ); + DBGC ( efidrv, "EFIBOFM driver installed\n" ); } /** EFI BOFM startup function */ diff --git a/roms/ipxe/src/interface/efi/efi_console.c b/roms/ipxe/src/interface/efi/efi_console.c index 1303a4278..a30ca301b 100644 --- a/roms/ipxe/src/interface/efi/efi_console.c +++ b/roms/ipxe/src/interface/efi/efi_console.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -23,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/efi/efi.h> #include <ipxe/ansiesc.h> #include <ipxe/console.h> +#include <config/console.h> #define ATTR_BOLD 0x08 @@ -48,6 +50,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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; @@ -273,4 +281,5 @@ struct console_driver efi_console __console_driver = { .putchar = efi_putchar, .getchar = efi_getchar, .iskey = efi_iskey, + .usage = CONSOLE_EFI, }; diff --git a/roms/ipxe/src/interface/efi/efi_download.c b/roms/ipxe/src/interface/efi/efi_download.c new file mode 100644 index 000000000..250946e28 --- /dev/null +++ b/roms/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/roms/ipxe/src/interface/efi/efi_driver.c b/roms/ipxe/src/interface/efi/efi_driver.c index 4aa976f90..deb3cf2cd 100644 --- a/roms/ipxe/src/interface/efi/efi_driver.c +++ b/roms/ipxe/src/interface/efi/efi_driver.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -89,12 +90,29 @@ efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf, */ 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 ) { + EFI_HANDLE device, EFI_HANDLE child, + CHAR8 *language, CHAR16 **controller_name ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + union { + EFI_COMPONENT_NAME2_PROTOCOL *name2; + void *interface; + } name2; + EFI_STATUS efirc; + + /* Delegate to the EFI_COMPONENT_NAME2_PROTOCOL instance + * installed on child handle, if present. + */ + if ( ( child != NULL ) && + ( ( efirc = bs->OpenProtocol ( + child, &efi_component_name2_protocol_guid, + &name2.interface, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) == 0 ) ) { + return name2.name2->GetControllerName ( name2.name2, device, + child, language, + controller_name ); + } - /* Just let EFI use the default Device Path Name */ + /* Otherwise, let EFI use the default Device Path Name */ return EFI_UNSUPPORTED; } diff --git a/roms/ipxe/src/interface/efi/efi_hii.c b/roms/ipxe/src/interface/efi/efi_hii.c new file mode 100644 index 000000000..834060b54 --- /dev/null +++ b/roms/ipxe/src/interface/efi/efi_hii.c @@ -0,0 +1,577 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <ipxe/efi/efi.h> +#include <ipxe/efi/efi_strings.h> +#include <ipxe/efi/efi_hii.h> + +/** Tiano GUID */ +static const EFI_GUID tiano_guid = EFI_IFR_TIANO_GUID; + +/** + * Add string to IFR builder + * + * @v ifr IFR builder + * @v fmt Format string + * @v ... Arguments + * @ret string_id String identifier, or zero on failure + */ +unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, const char *fmt, + ... ) { + EFI_HII_STRING_BLOCK *new_strings; + EFI_HII_SIBT_STRING_UCS2_BLOCK *ucs2; + size_t new_strings_len; + va_list args; + size_t len; + unsigned int string_id; + + /* Do nothing if a previous allocation has failed */ + if ( ifr->failed ) + return 0; + + /* Calculate string length */ + va_start ( args, fmt ); + len = ( efi_vsnprintf ( NULL, 0, fmt, args ) + 1 /* wNUL */ ); + va_end ( args ); + + /* Reallocate strings */ + new_strings_len = ( ifr->strings_len + + offsetof ( typeof ( *ucs2 ), StringText ) + + ( len * sizeof ( ucs2->StringText[0] ) ) ); + new_strings = realloc ( ifr->strings, new_strings_len ); + if ( ! new_strings ) { + ifr->failed = 1; + return 0; + } + ucs2 = ( ( ( void * ) new_strings ) + ifr->strings_len ); + ifr->strings = new_strings; + ifr->strings_len = new_strings_len; + + /* Fill in string */ + ucs2->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; + va_start ( args, fmt ); + efi_vsnprintf ( ucs2->StringText, len, fmt, args ); + va_end ( args ); + + /* Allocate string ID */ + string_id = ++(ifr->string_id); + + DBGC ( ifr, "IFR %p string %#04x is \"%ls\"\n", + ifr, string_id, ucs2->StringText ); + return string_id; +} + +/** + * Add IFR opcode to IFR builder + * + * @v ifr IFR builder + * @v opcode Opcode + * @v len Opcode length + * @ret op Opcode, or NULL + */ +static void * efi_ifr_op ( struct efi_ifr_builder *ifr, unsigned int opcode, + size_t len ) { + EFI_IFR_OP_HEADER *new_ops; + EFI_IFR_OP_HEADER *op; + size_t new_ops_len; + + /* Do nothing if a previous allocation has failed */ + if ( ifr->failed ) + return NULL; + + /* Reallocate opcodes */ + new_ops_len = ( ifr->ops_len + len ); + new_ops = realloc ( ifr->ops, new_ops_len ); + if ( ! new_ops ) { + ifr->failed = 1; + return NULL; + } + op = ( ( ( void * ) new_ops ) + ifr->ops_len ); + ifr->ops = new_ops; + ifr->ops_len = new_ops_len; + + /* Fill in opcode header */ + op->OpCode = opcode; + op->Length = len; + + return op; +} + +/** + * Add end opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_end_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_END *end; + + /* Add opcode */ + end = efi_ifr_op ( ifr, EFI_IFR_END_OP, sizeof ( *end ) ); + + DBGC ( ifr, "IFR %p end\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, end, sizeof ( *end ) ); +} + +/** + * Add false opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_false_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FALSE *false; + + /* Add opcode */ + false = efi_ifr_op ( ifr, EFI_IFR_FALSE_OP, sizeof ( *false ) ); + + DBGC ( ifr, "IFR %p false\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, false, sizeof ( *false ) ); +} + +/** + * Add form opcode to IFR builder + * + * @v ifr IFR builder + * @v title_id Title string identifier + * @ret form_id Form identifier + */ +unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr, + unsigned int title_id ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FORM *form; + + /* Add opcode */ + form = efi_ifr_op ( ifr, EFI_IFR_FORM_OP, sizeof ( *form ) ); + if ( ! form ) + return 0; + form->Header.Scope = 1; + form->FormId = ++(ifr->form_id); + form->FormTitle = title_id; + + DBGC ( ifr, "IFR %p name/value store %#04x title %#04x\n", + ifr, form->FormId, title_id ); + DBGC2_HDA ( ifr, dispaddr, form, sizeof ( *form ) ); + return form->FormId; +} + +/** + * Add formset opcode to IFR builder + * + * @v ifr IFR builder + * @v guid GUID + * @v title_id Title string identifier + * @v help_id Help string identifier + * @v ... Class GUIDs (terminated by NULL) + */ +void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, const EFI_GUID *guid, + unsigned int title_id, unsigned int help_id, ... ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FORM_SET *formset; + EFI_GUID *class_guid; + unsigned int num_class_guids = 0; + size_t len; + va_list args; + + /* Count number of class GUIDs */ + va_start ( args, help_id ); + while ( va_arg ( args, const EFI_GUID * ) != NULL ) + num_class_guids++; + va_end ( args ); + + /* Add opcode */ + len = ( sizeof ( *formset ) + + ( num_class_guids * sizeof ( *class_guid ) ) ); + formset = efi_ifr_op ( ifr, EFI_IFR_FORM_SET_OP, len ); + if ( ! formset ) + return; + formset->Header.Scope = 1; + memcpy ( &formset->Guid, guid, sizeof ( formset->Guid ) ); + formset->FormSetTitle = title_id; + formset->Help = help_id; + formset->Flags = num_class_guids; + + /* Add class GUIDs */ + class_guid = ( ( ( void * ) formset ) + sizeof ( *formset ) ); + va_start ( args, help_id ); + while ( num_class_guids-- ) { + memcpy ( class_guid++, va_arg ( args, const EFI_GUID * ), + sizeof ( *class_guid ) ); + } + va_end ( args ); + + DBGC ( ifr, "IFR %p formset title %#04x help %#04x\n", + ifr, title_id, help_id ); + DBGC2_HDA ( ifr, dispaddr, formset, len ); +} + +/** + * Add get opcode to IFR builder + * + * @v ifr IFR builder + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v varstore_type Variable type + */ +void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id, + unsigned int varstore_info, unsigned int varstore_type ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GET *get; + + /* Add opcode */ + get = efi_ifr_op ( ifr, EFI_IFR_GET_OP, sizeof ( *get ) ); + get->VarStoreId = varstore_id; + get->VarStoreInfo.VarName = varstore_info; + get->VarStoreType = varstore_type; + + DBGC ( ifr, "IFR %p get varstore %#04x:%#04x type %#02x\n", + ifr, varstore_id, varstore_info, varstore_type ); + DBGC2_HDA ( ifr, dispaddr, get, sizeof ( *get ) ); +} + +/** + * Add GUID class opcode to IFR builder + * + * @v ifr IFR builder + * @v class Class + */ +void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, unsigned int class ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GUID_CLASS *guid_class; + + /* Add opcode */ + guid_class = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, + sizeof ( *guid_class ) ); + if ( ! guid_class ) + return; + memcpy ( &guid_class->Guid, &tiano_guid, sizeof ( guid_class->Guid ) ); + guid_class->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS; + guid_class->Class = class; + + DBGC ( ifr, "IFR %p GUID class %#02x\n", ifr, class ); + DBGC2_HDA ( ifr, dispaddr, guid_class, sizeof ( *guid_class ) ); +} + +/** + * Add GUID subclass opcode to IFR builder + * + * @v ifr IFR builder + * @v subclass Subclass + */ +void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr, + unsigned int subclass ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GUID_SUBCLASS *guid_subclass; + + /* Add opcode */ + guid_subclass = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, + sizeof ( *guid_subclass ) ); + if ( ! guid_subclass ) + return; + memcpy ( &guid_subclass->Guid, &tiano_guid, + sizeof ( guid_subclass->Guid ) ); + guid_subclass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS; + guid_subclass->SubClass = subclass; + + DBGC ( ifr, "IFR %p GUID subclass %#02x\n", ifr, subclass ); + DBGC2_HDA ( ifr, dispaddr, guid_subclass, sizeof ( *guid_subclass ) ); +} + +/** + * Add numeric opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v question_id Question identifier + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v vflags Variable flags + * @v min_value Minimum value + * @v max_value Maximum value + * @v step Step + * @v flags Flags + */ +void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, unsigned int varstore_info, + unsigned int vflags, unsigned long min_value, + unsigned long max_value, unsigned int step, + unsigned int flags ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_NUMERIC *numeric; + unsigned int size; + + /* Add opcode */ + numeric = efi_ifr_op ( ifr, EFI_IFR_NUMERIC_OP, sizeof ( *numeric ) ); + if ( ! numeric ) + return; + numeric->Question.Header.Prompt = prompt_id; + numeric->Question.Header.Help = help_id; + numeric->Question.QuestionId = question_id; + numeric->Question.VarStoreId = varstore_id; + numeric->Question.VarStoreInfo.VarName = varstore_info; + numeric->Question.Flags = vflags; + size = ( flags & EFI_IFR_NUMERIC_SIZE ); + switch ( size ) { + case EFI_IFR_NUMERIC_SIZE_1 : + numeric->data.u8.MinValue = min_value; + numeric->data.u8.MaxValue = max_value; + numeric->data.u8.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_2 : + numeric->data.u16.MinValue = min_value; + numeric->data.u16.MaxValue = max_value; + numeric->data.u16.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_4 : + numeric->data.u32.MinValue = min_value; + numeric->data.u32.MaxValue = max_value; + numeric->data.u32.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_8 : + numeric->data.u64.MinValue = min_value; + numeric->data.u64.MaxValue = max_value; + numeric->data.u64.Step = step; + break; + } + + DBGC ( ifr, "IFR %p numeric prompt %#04x help %#04x question %#04x " + "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, + varstore_id, varstore_info ); + DBGC2_HDA ( ifr, dispaddr, numeric, sizeof ( *numeric ) ); +} + +/** + * Add string opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v question_id Question identifier + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v vflags Variable flags + * @v min_size Minimum size + * @v max_size Maximum size + * @v flags Flags + */ +void efi_ifr_string_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, unsigned int varstore_info, + unsigned int vflags, unsigned int min_size, + unsigned int max_size, unsigned int flags ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_STRING *string; + + /* Add opcode */ + string = efi_ifr_op ( ifr, EFI_IFR_STRING_OP, sizeof ( *string ) ); + if ( ! string ) + return; + string->Question.Header.Prompt = prompt_id; + string->Question.Header.Help = help_id; + string->Question.QuestionId = question_id; + string->Question.VarStoreId = varstore_id; + string->Question.VarStoreInfo.VarName = varstore_info; + string->Question.Flags = vflags; + string->MinSize = min_size; + string->MaxSize = max_size; + string->Flags = flags; + + DBGC ( ifr, "IFR %p string prompt %#04x help %#04x question %#04x " + "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, + varstore_id, varstore_info ); + DBGC2_HDA ( ifr, dispaddr, string, sizeof ( *string ) ); +} + +/** + * Add suppress-if opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_SUPPRESS_IF *suppress_if; + + /* Add opcode */ + suppress_if = efi_ifr_op ( ifr, EFI_IFR_SUPPRESS_IF_OP, + sizeof ( *suppress_if ) ); + suppress_if->Header.Scope = 1; + + DBGC ( ifr, "IFR %p suppress-if\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, suppress_if, sizeof ( *suppress_if ) ); +} + +/** + * Add text opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v text_id Text string identifier + */ +void efi_ifr_text_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int text_id ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_TEXT *text; + + /* Add opcode */ + text = efi_ifr_op ( ifr, EFI_IFR_TEXT_OP, sizeof ( *text ) ); + if ( ! text ) + return; + text->Statement.Prompt = prompt_id; + text->Statement.Help = help_id; + text->TextTwo = text_id; + + DBGC ( ifr, "IFR %p text prompt %#04x help %#04x text %#04x\n", + ifr, prompt_id, help_id, text_id ); + DBGC2_HDA ( ifr, dispaddr, text, sizeof ( *text ) ); +} + +/** + * Add true opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_true_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_TRUE *true; + + /* Add opcode */ + true = efi_ifr_op ( ifr, EFI_IFR_TRUE_OP, sizeof ( *true ) ); + + DBGC ( ifr, "IFR %p true\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, true, sizeof ( *true ) ); +} + +/** + * Add name/value store opcode to IFR builder + * + * @v ifr IFR builder + * @v guid GUID + * @ret varstore_id Variable store identifier, or 0 on failure + */ +unsigned int efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_VARSTORE_NAME_VALUE *varstore; + + /* Add opcode */ + varstore = efi_ifr_op ( ifr, EFI_IFR_VARSTORE_NAME_VALUE_OP, + sizeof ( *varstore ) ); + if ( ! varstore ) + return 0; + varstore->VarStoreId = ++(ifr->varstore_id); + memcpy ( &varstore->Guid, guid, sizeof ( varstore->Guid ) ); + + DBGC ( ifr, "IFR %p name/value store %#04x\n", + ifr, varstore->VarStoreId ); + DBGC2_HDA ( ifr, dispaddr, varstore, sizeof ( *varstore ) ); + return varstore->VarStoreId; +} + +/** + * Free memory used by IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_free ( struct efi_ifr_builder *ifr ) { + + free ( ifr->ops ); + free ( ifr->strings ); + memset ( ifr, 0, sizeof ( *ifr ) ); +} + +/** + * Construct package list from IFR builder + * + * @v ifr IFR builder + * @v guid Package GUID + * @v language Language + * @v language_id Language string ID + * @ret package Package list, or NULL + * + * The package list is allocated using malloc(), and must eventually + * be freed by the caller. (The caller must also call efi_ifr_free() + * to free the temporary storage used during construction.) + */ +EFI_HII_PACKAGE_LIST_HEADER * efi_ifr_package ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid, + const char *language, + unsigned int language_id ) { + struct { + EFI_HII_PACKAGE_LIST_HEADER header; + struct { + EFI_HII_PACKAGE_HEADER header; + uint8_t data[ifr->ops_len]; + } __attribute__ (( packed )) ops; + struct { + union { + EFI_HII_STRING_PACKAGE_HDR header; + uint8_t pad[offsetof(EFI_HII_STRING_PACKAGE_HDR, + Language) + + strlen ( language ) + 1 /* NUL */ ]; + } __attribute__ (( packed )) header; + uint8_t data[ifr->strings_len]; + EFI_HII_STRING_BLOCK end; + } __attribute__ (( packed )) strings; + EFI_HII_PACKAGE_HEADER end; + } __attribute__ (( packed )) *package; + + /* Fail if any previous allocation failed */ + if ( ifr->failed ) + return NULL; + + /* Allocate package list */ + package = zalloc ( sizeof ( *package ) ); + if ( ! package ) + return NULL; + + /* Populate package list */ + package->header.PackageLength = sizeof ( *package ); + memcpy ( &package->header.PackageListGuid, guid, + sizeof ( package->header.PackageListGuid ) ); + package->ops.header.Length = sizeof ( package->ops ); + package->ops.header.Type = EFI_HII_PACKAGE_FORMS; + memcpy ( package->ops.data, ifr->ops, sizeof ( package->ops.data ) ); + package->strings.header.header.Header.Length = + sizeof ( package->strings ); + package->strings.header.header.Header.Type = + EFI_HII_PACKAGE_STRINGS; + package->strings.header.header.HdrSize = + sizeof ( package->strings.header ); + package->strings.header.header.StringInfoOffset = + sizeof ( package->strings.header ); + package->strings.header.header.LanguageName = language_id; + strcpy ( package->strings.header.header.Language, language ); + memcpy ( package->strings.data, ifr->strings, + sizeof ( package->strings.data ) ); + package->strings.end.BlockType = EFI_HII_SIBT_END; + package->end.Type = EFI_HII_PACKAGE_END; + package->end.Length = sizeof ( package->end ); + + return &package->header; +} + diff --git a/roms/ipxe/src/interface/efi/efi_init.c b/roms/ipxe/src/interface/efi/efi_init.c index 6c7b4955f..aaf894718 100644 --- a/roms/ipxe/src/interface/efi/efi_init.c +++ b/roms/ipxe/src/interface/efi/efi_init.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_io.c b/roms/ipxe/src/interface/efi/efi_io.c index 9a9aad31c..a620d6e43 100644 --- a/roms/ipxe/src/interface/efi/efi_io.c +++ b/roms/ipxe/src/interface/efi/efi_io.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_pci.c b/roms/ipxe/src/interface/efi/efi_pci.c index fa71e7d84..0288cf326 100644 --- a/roms/ipxe/src/interface/efi/efi_pci.c +++ b/roms/ipxe/src/interface/efi/efi_pci.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -216,17 +217,19 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, */ 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; - } + /* Try to enable I/O cycles, memory cycles, and bus mastering. + * Some platforms will 'helpfully' report errors if these bits + * can't be enabled (for example, if the card doesn't actually + * support I/O cycles). Work around any such platforms by + * enabling bits individually and simply ignoring any errors. + */ + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); return 0; } diff --git a/roms/ipxe/src/interface/efi/efi_smbios.c b/roms/ipxe/src/interface/efi/efi_smbios.c index 4b58d8466..506b04e77 100644 --- a/roms/ipxe/src/interface/efi/efi_smbios.c +++ b/roms/ipxe/src/interface/efi/efi_smbios.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_snp.c b/roms/ipxe/src/interface/efi/efi_snp.c index f40bfff94..200275966 100644 --- a/roms/ipxe/src/interface/efi/efi_snp.c +++ b/roms/ipxe/src/interface/efi/efi_snp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -31,66 +32,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 <ipxe/efi/efi_snp.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; @@ -113,6 +57,10 @@ static EFI_GUID efi_nii31_protocol_guid = { { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } }; +/** EFI component name protocol */ +static EFI_GUID efi_component_name2_protocol_guid + = EFI_COMPONENT_NAME2_PROTOCOL_GUID; + /** List of SNP devices */ static LIST_HEAD ( efi_snp_devices ); @@ -535,7 +483,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, 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; + size_t payload_len; int rc; EFI_STATUS efirc; @@ -588,20 +536,22 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, } /* Allocate buffer */ - ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len ); - iobuf = alloc_iob ( ll_headroom + len ); + payload_len = ( len - ll_protocol->ll_header_len ); + iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ? + payload_len : IOB_ZLEN ) ); 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 ); + iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN - + ll_protocol->ll_header_len ) ); memcpy ( iob_put ( iobuf, len ), data, len ); /* Create link-layer header, if specified */ if ( ll_header_len ) { - iob_pull ( iobuf, ll_header_len ); + iob_pull ( iobuf, ll_protocol->ll_header_len ); if ( ( rc = ll_protocol->push ( snpdev->netdev, iobuf, ll_dest, ll_src, htons ( *net_proto ) )) != 0 ){ @@ -658,6 +608,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, const void *iob_ll_dest; const void *iob_ll_src; uint16_t iob_net_proto; + unsigned int iob_flags; int rc; EFI_STATUS efirc; @@ -682,7 +633,8 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, /* Attempt to decode link-layer header */ if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest, - &iob_ll_src, &iob_net_proto ) ) != 0 ){ + &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 ); @@ -756,330 +708,52 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = { /****************************************************************************** * - * Human Interface Infrastructure + * Component name protocol * ****************************************************************************** */ -/** 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 GUID used for our EFI SNP formset */ -#define EFI_SNP_FORMSET_GUID \ - { 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, - 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 + * Look up driver name * - * @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; - - /* 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 + * @v name2 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_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_STRING config, EFI_STRING *progress ) { +efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, + CHAR8 *language __unused, CHAR16 **driver_name ) { struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); + container_of ( name2, struct efi_snp_device, name2 ); - DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev ); - - *progress = config; - return EFI_INVALID_PARAMETER; + *driver_name = snpdev->driver_name; + return 0; } /** - * Handle form actions + * Look up controller name * - * @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 + * @v name2 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_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 ) { +efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, + EFI_HANDLE device __unused, + EFI_HANDLE child __unused, + CHAR8 *language __unused, + CHAR16 **controller_name ) { struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); + container_of ( name2, struct efi_snp_device, name2 ); - DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev ); - return EFI_UNSUPPORTED; + *controller_name = snpdev->controller_name; + return 0; } -/** 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 @@ -1173,8 +847,19 @@ static int efi_snp_probe ( struct net_device *netdev ) { 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 component name structure */ + efi_snprintf ( snpdev->driver_name, + ( sizeof ( snpdev->driver_name ) / + sizeof ( snpdev->driver_name[0] ) ), + PRODUCT_SHORT_NAME " %s", netdev->dev->driver_name ); + efi_snprintf ( snpdev->controller_name, + ( sizeof ( snpdev->controller_name ) / + sizeof ( snpdev->controller_name[0] ) ), + PRODUCT_SHORT_NAME " %s (%s)", + netdev->name, netdev_addr ( netdev ) ); + snpdev->name2.GetDriverName = efi_snp_get_driver_name; + snpdev->name2.GetControllerName = efi_snp_get_controller_name; + snpdev->name2.SupportedLanguages = "en"; /* Populate the device name */ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / @@ -1204,7 +889,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &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, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not install protocols: " "%s\n", snpdev, efi_strerror ( efirc ) ); @@ -1221,23 +906,11 @@ static int efi_snp_probe ( struct net_device *netdev ) { 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; + /* Install HII */ + if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n", + snpdev, strerror ( rc ) ); + goto err_hii_install; } /* Add to list of SNP devices */ @@ -1247,10 +920,8 @@ static int efi_snp_probe ( struct net_device *netdev ) { snpdev, netdev->name, snpdev->handle ); return 0; - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - err_register_hii: - free ( snpdev->package_list ); - err_create_hii: + efi_snp_hii_uninstall ( snpdev ); + err_hii_install: efipci_child_del ( efipci, snpdev->handle ); err_efipci_child_add: bs->UninstallMultipleProtocolInterfaces ( @@ -1259,7 +930,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &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, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ); err_install_protocol_interface: bs->CloseEvent ( snpdev->snp.WaitForPacket ); @@ -1277,8 +948,21 @@ static int efi_snp_probe ( struct net_device *netdev ) { * * @v netdev Network device */ -static void efi_snp_notify ( struct net_device *netdev __unused ) { - /* Nothing to do */ +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" ) ); } /** @@ -1298,8 +982,7 @@ static void efi_snp_remove ( struct net_device *netdev ) { } /* Uninstall the SNP */ - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - free ( snpdev->package_list ); + efi_snp_hii_uninstall ( snpdev ); efipci_child_del ( snpdev->efipci, snpdev->handle ); list_del ( &snpdev->list ); bs->UninstallMultipleProtocolInterfaces ( @@ -1308,7 +991,7 @@ static void efi_snp_remove ( struct net_device *netdev ) { &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, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ); bs->CloseEvent ( snpdev->snp.WaitForPacket ); netdev_put ( snpdev->netdev ); diff --git a/roms/ipxe/src/interface/efi/efi_snp_hii.c b/roms/ipxe/src/interface/efi/efi_snp_hii.c new file mode 100644 index 000000000..3a1193a38 --- /dev/null +++ b/roms/ipxe/src/interface/efi/efi_snp_hii.c @@ -0,0 +1,707 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * EFI SNP HII protocol + * + * The HII protocols are some of the less-well designed parts of the + * entire EFI specification. This is a significant accomplishment. + * + * The face-slappingly ludicrous query string syntax seems to be + * motivated by the desire to allow a caller to query multiple drivers + * simultaneously via the single-instance HII_CONFIG_ROUTING_PROTOCOL, + * which is supposed to pass relevant subsets of the query string to + * the relevant drivers. + * + * Nobody uses the HII_CONFIG_ROUTING_PROTOCOL. Not even the EFI + * setup browser uses the HII_CONFIG_ROUTING_PROTOCOL. To the best of + * my knowledge, there has only ever been one implementation of the + * HII_CONFIG_ROUTING_PROTOCOL (as part of EDK2), and it just doesn't + * work. It's so badly broken that I can't even figure out what the + * code is _trying_ to do. + * + * Fundamentally, the problem seems to be that Javascript programmers + * should not be allowed to design APIs for C code. + */ + +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <stdio.h> +#include <wchar.h> +#include <errno.h> +#include <ipxe/settings.h> +#include <ipxe/nvo.h> +#include <ipxe/device.h> +#include <ipxe/netdevice.h> +#include <ipxe/version.h> +#include <ipxe/efi/efi.h> +#include <ipxe/efi/efi_hii.h> +#include <ipxe/efi/efi_snp.h> +#include <ipxe/efi/efi_strings.h> +#include <config/general.h> + +/** EFI configuration access protocol GUID */ +static EFI_GUID efi_hii_config_access_protocol_guid + = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; + +/** EFI platform setup formset GUID */ +static EFI_GUID efi_hii_platform_setup_formset_guid + = EFI_HII_PLATFORM_SETUP_FORMSET_GUID; + +/** EFI IBM UCM compliant formset GUID */ +static EFI_GUID efi_hii_ibm_ucm_compliant_formset_guid + = EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID; + +/** EFI HII database protocol */ +static EFI_HII_DATABASE_PROTOCOL *efihii; +EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); + +/** + * Identify settings to be exposed via HII + * + * @v snpdev SNP device + * @ret settings Settings, or NULL + */ +static struct settings * efi_snp_hii_settings ( struct efi_snp_device *snpdev ){ + + return find_child_settings ( netdev_settings ( snpdev->netdev ), + NVO_SETTINGS_NAME ); +} + +/** + * Check whether or not setting is applicable + * + * @v snpdev SNP device + * @v setting Setting + * @ret applies Setting applies + */ +static int efi_snp_hii_setting_applies ( struct efi_snp_device *snpdev, + struct setting *setting ) { + + return nvo_applies ( efi_snp_hii_settings ( snpdev ), setting ); +} + +/** + * Generate a random GUID + * + * @v guid GUID to fill in + */ +static void efi_snp_hii_random_guid ( EFI_GUID *guid ) { + uint8_t *byte = ( ( uint8_t * ) guid ); + unsigned int i; + + for ( i = 0 ; i < sizeof ( *guid ) ; i++ ) + *(byte++) = random(); +} + +/** + * Generate EFI SNP questions + * + * @v snpdev SNP device + * @v ifr IFR builder + * @v varstore_id Variable store identifier + */ +static void efi_snp_hii_questions ( struct efi_snp_device *snpdev, + struct efi_ifr_builder *ifr, + unsigned int varstore_id ) { + struct setting *setting; + unsigned int name_id; + unsigned int prompt_id; + unsigned int help_id; + unsigned int question_id; + + /* Add all applicable settings */ + for_each_table_entry ( setting, SETTINGS ) { + if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) + continue; + name_id = efi_ifr_string ( ifr, "%s", setting->name ); + prompt_id = efi_ifr_string ( ifr, "%s", setting->description ); + help_id = efi_ifr_string ( ifr, "http://ipxe.org/cfg/%s", + setting->name ); + question_id = setting->tag; + efi_ifr_string_op ( ifr, prompt_id, help_id, + question_id, varstore_id, name_id, + 0, 0x00, 0xff, 0 ); + } +} + +/** + * Build HII package list for SNP device + * + * @v snpdev SNP device + * @ret package Package list, or NULL on error + */ +static EFI_HII_PACKAGE_LIST_HEADER * +efi_snp_hii_package_list ( struct efi_snp_device *snpdev ) { + struct net_device *netdev = snpdev->netdev; + struct device *dev = netdev->dev; + struct efi_ifr_builder ifr; + EFI_HII_PACKAGE_LIST_HEADER *package; + const char *product_name; + EFI_GUID package_guid; + EFI_GUID formset_guid; + EFI_GUID varstore_guid; + unsigned int title_id; + unsigned int varstore_id; + + /* Initialise IFR builder */ + efi_ifr_init ( &ifr ); + + /* Determine product name */ + product_name = ( PRODUCT_NAME[0] ? PRODUCT_NAME : PRODUCT_SHORT_NAME ); + + /* Generate GUIDs */ + efi_snp_hii_random_guid ( &package_guid ); + efi_snp_hii_random_guid ( &formset_guid ); + efi_snp_hii_random_guid ( &varstore_guid ); + + /* Generate title string (used more than once) */ + title_id = efi_ifr_string ( &ifr, "%s (%s)", product_name, + netdev_addr ( netdev ) ); + + /* Generate opcodes */ + efi_ifr_form_set_op ( &ifr, &formset_guid, title_id, + efi_ifr_string ( &ifr, + "Configure " PRODUCT_SHORT_NAME), + &efi_hii_platform_setup_formset_guid, + &efi_hii_ibm_ucm_compliant_formset_guid, NULL ); + efi_ifr_guid_class_op ( &ifr, EFI_NETWORK_DEVICE_CLASS ); + efi_ifr_guid_subclass_op ( &ifr, 0x03 ); + varstore_id = efi_ifr_varstore_name_value_op ( &ifr, &varstore_guid ); + efi_ifr_form_op ( &ifr, title_id ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Name" ), + efi_ifr_string ( &ifr, "Firmware product name" ), + efi_ifr_string ( &ifr, "%s", product_name ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Version" ), + efi_ifr_string ( &ifr, "Firmware version" ), + efi_ifr_string ( &ifr, "%s", product_version ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Driver" ), + efi_ifr_string ( &ifr, "Firmware driver" ), + efi_ifr_string ( &ifr, "%s", dev->driver_name ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Device" ), + efi_ifr_string ( &ifr, "Hardware device" ), + efi_ifr_string ( &ifr, "%s", dev->name ) ); + efi_snp_hii_questions ( snpdev, &ifr, varstore_id ); + efi_ifr_end_op ( &ifr ); + efi_ifr_end_op ( &ifr ); + + /* Build package */ + package = efi_ifr_package ( &ifr, &package_guid, "en-us", + efi_ifr_string ( &ifr, "English" ) ); + if ( ! package ) { + DBGC ( snpdev, "SNPDEV %p could not build IFR package\n", + snpdev ); + efi_ifr_free ( &ifr ); + return NULL; + } + + /* Free temporary storage */ + efi_ifr_free ( &ifr ); + return package; +} + +/** + * Append response to result string + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string + * @ret rc Return status code + * + * The result string is allocated dynamically using + * BootServices::AllocatePool(), and the caller is responsible for + * eventually calling BootServices::FreePool(). + */ +static int efi_snp_hii_append ( struct efi_snp_device *snpdev __unused, + const char *key, const char *value, + wchar_t **results ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + size_t len; + void *new; + + /* Allocate new string */ + len = ( ( *results ? ( wcslen ( *results ) + 1 /* "&" */ ) : 0 ) + + strlen ( key ) + 1 /* "=" */ + strlen ( value ) + 1 /* NUL */ ); + bs->AllocatePool ( EfiBootServicesData, ( len * sizeof ( wchar_t ) ), + &new ); + if ( ! new ) + return -ENOMEM; + + /* Populate string */ + efi_snprintf ( new, len, "%ls%s%s=%s", ( *results ? *results : L"" ), + ( *results ? L"&" : L"" ), key, value ); + bs->FreePool ( *results ); + *results = new; + + return 0; +} + +/** + * Fetch HII setting + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string + * @v have_setting Flag indicating detection of a setting + * @ret rc Return status code + */ +static int efi_snp_hii_fetch ( struct efi_snp_device *snpdev, + const char *key, const char *value, + wchar_t **results, int *have_setting ) { + struct settings *settings = efi_snp_hii_settings ( snpdev ); + struct setting *setting; + int len; + char *buf; + char *encoded; + int i; + int rc; + + /* Handle ConfigHdr components */ + if ( ( strcasecmp ( key, "GUID" ) == 0 ) || + ( strcasecmp ( key, "NAME" ) == 0 ) || + ( strcasecmp ( key, "PATH" ) == 0 ) ) { + return efi_snp_hii_append ( snpdev, key, value, results ); + } + if ( have_setting ) + *have_setting = 1; + + /* Do nothing more unless we have a settings block */ + if ( ! settings ) { + rc = -ENOTSUP; + goto err_no_settings; + } + + /* Identify setting */ + setting = find_setting ( key ); + if ( ! setting ) { + DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", + snpdev, key ); + rc = -ENODEV; + goto err_find_setting; + } + + /* Encode value */ + if ( setting_exists ( settings, setting ) ) { + + /* Calculate formatted length */ + len = fetchf_setting ( settings, setting, NULL, 0 ); + if ( len < 0 ) { + rc = len; + DBGC ( snpdev, "SNPDEV %p could not fetch %s: %s\n", + snpdev, setting->name, strerror ( rc ) ); + goto err_fetchf_len; + } + + /* Allocate buffer for formatted value and HII-encoded value */ + buf = zalloc ( len + 1 /* NUL */ + ( len * 4 ) + 1 /* NUL */ ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + encoded = ( buf + len + 1 /* NUL */ ); + + /* Format value */ + fetchf_setting ( settings, setting, buf, ( len + 1 /* NUL */ )); + for ( i = 0 ; i < len ; i++ ) { + sprintf ( ( encoded + ( 4 * i ) ), "%04x", + *( ( uint8_t * ) buf + i ) ); + } + + } else { + + /* Non-existent or inapplicable setting */ + buf = NULL; + encoded = ""; + } + + /* Append results */ + if ( ( rc = efi_snp_hii_append ( snpdev, key, encoded, + results ) ) != 0 ) { + goto err_append; + } + + /* Success */ + rc = 0; + + err_append: + free ( buf ); + err_alloc: + err_fetchf_len: + err_find_setting: + err_no_settings: + return rc; +} + +/** + * Fetch HII setting + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string (unused) + * @v have_setting Flag indicating detection of a setting (unused) + * @ret rc Return status code + */ +static int efi_snp_hii_store ( struct efi_snp_device *snpdev, + const char *key, const char *value, + wchar_t **results __unused, + int *have_setting __unused ) { + struct settings *settings = efi_snp_hii_settings ( snpdev ); + struct setting *setting; + char *buf; + char tmp[5]; + char *endp; + int len; + int i; + int rc; + + /* Handle ConfigHdr components */ + if ( ( strcasecmp ( key, "GUID" ) == 0 ) || + ( strcasecmp ( key, "NAME" ) == 0 ) || + ( strcasecmp ( key, "PATH" ) == 0 ) ) { + /* Nothing to do */ + return 0; + } + + /* Do nothing more unless we have a settings block */ + if ( ! settings ) { + rc = -ENOTSUP; + goto err_no_settings; + } + + /* Identify setting */ + setting = find_setting ( key ); + if ( ! setting ) { + DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", + snpdev, key ); + rc = -ENODEV; + goto err_find_setting; + } + + /* Allocate buffer */ + len = ( strlen ( value ) / 4 ); + buf = zalloc ( len + 1 /* NUL */ ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Decode value */ + tmp[4] = '\0'; + for ( i = 0 ; i < len ; i++ ) { + memcpy ( tmp, ( value + ( i * 4 ) ), 4 ); + buf[i] = strtoul ( tmp, &endp, 16 ); + if ( endp != &tmp[4] ) { + DBGC ( snpdev, "SNPDEV %p invalid character %s\n", + snpdev, tmp ); + rc = -EINVAL; + goto err_inval; + } + } + + /* Store value */ + if ( ( rc = storef_setting ( settings, setting, buf ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not store \"%s\" into %s: %s\n", + snpdev, buf, setting->name, strerror ( rc ) ); + goto err_storef; + } + + /* Success */ + rc = 0; + + err_storef: + err_inval: + free ( buf ); + err_alloc: + err_find_setting: + err_no_settings: + return rc; +} + +/** + * Process portion of HII configuration string + * + * @v snpdev SNP device + * @v string HII configuration string + * @v progress Progress through HII configuration string + * @v results Results string + * @v have_setting Flag indicating detection of a setting (unused) + * @v process Function used to process key=value pairs + * @ret rc Return status code + */ +static int efi_snp_hii_process ( struct efi_snp_device *snpdev, + wchar_t *string, wchar_t **progress, + wchar_t **results, int *have_setting, + int ( * process ) ( struct efi_snp_device *, + const char *key, + const char *value, + wchar_t **results, + int *have_setting ) ) { + wchar_t *wkey = string; + wchar_t *wend = string; + wchar_t *wvalue = NULL; + size_t key_len; + size_t value_len; + void *temp; + char *key; + char *value; + int rc; + + /* Locate key, value (if any), and end */ + while ( *wend ) { + if ( *wend == L'&' ) + break; + if ( *(wend++) == L'=' ) + wvalue = wend; + } + + /* Allocate memory for key and value */ + key_len = ( ( wvalue ? ( wvalue - 1 ) : wend ) - wkey ); + value_len = ( wvalue ? ( wend - wvalue ) : 0 ); + temp = zalloc ( key_len + 1 /* NUL */ + value_len + 1 /* NUL */ ); + if ( ! temp ) + return -ENOMEM; + key = temp; + value = ( temp + key_len + 1 /* NUL */ ); + + /* Copy key and value */ + while ( key_len-- ) + key[key_len] = wkey[key_len]; + while ( value_len-- ) + value[value_len] = wvalue[value_len]; + + /* Process key and value */ + if ( ( rc = process ( snpdev, key, value, results, + have_setting ) ) != 0 ) { + goto err; + } + + /* Update progress marker */ + *progress = wend; + + err: + /* Free temporary storage */ + free ( temp ); + + return rc; +} + +/** + * 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 ) { + struct efi_snp_device *snpdev = + container_of ( hii, struct efi_snp_device, hii ); + int have_setting = 0; + wchar_t *pos; + int rc; + + DBGC ( snpdev, "SNPDEV %p ExtractConfig request \"%ls\"\n", + snpdev, request ); + + /* Initialise results */ + *results = NULL; + + /* Process all request fragments */ + for ( pos = *progress = request ; *progress && **progress ; + pos = *progress + 1 ) { + if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, + results, &have_setting, + efi_snp_hii_fetch ) ) != 0 ) { + return RC_TO_EFIRC ( rc ); + } + } + + /* If we have no explicit request, return all settings */ + if ( ! have_setting ) { + struct setting *setting; + + for_each_table_entry ( setting, SETTINGS ) { + if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) + continue; + if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, + NULL, results, + NULL ) ) != 0 ) { + return RC_TO_EFIRC ( rc ); + } + } + } + + DBGC ( snpdev, "SNPDEV %p ExtractConfig results \"%ls\"\n", + snpdev, *results ); + return 0; +} + +/** + * 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 ); + wchar_t *pos; + int rc; + + DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config ); + + /* Process all request fragments */ + for ( pos = *progress = config ; *progress && **progress ; + pos = *progress + 1 ) { + if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, + NULL, NULL, + efi_snp_hii_store ) ) != 0 ) { + return RC_TO_EFIRC ( rc ); + } + } + + return 0; +} + +/** + * 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, +}; + +/** + * Install HII protocol and packages for SNP device + * + * @v snpdev SNP device + * @ret rc Return status code + */ +int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + int efirc; + int rc; + + /* Initialise HII protocol */ + memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); + + /* Create HII package list */ + snpdev->package_list = efi_snp_hii_package_list ( snpdev ); + if ( ! snpdev->package_list ) { + DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", + snpdev ); + rc = -ENOMEM; + goto err_build_package_list; + } + + /* 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_new_package_list; + } + + /* Install HII protocol */ + if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( + &snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n", + snpdev, efi_strerror ( efirc ) ); + rc = EFIRC_TO_RC ( efirc ); + goto err_install_protocol; + } + + return 0; + + bs->UninstallMultipleProtocolInterfaces ( + snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ); + err_install_protocol: + efihii->RemovePackageList ( efihii, snpdev->hii_handle ); + err_new_package_list: + free ( snpdev->package_list ); + snpdev->package_list = NULL; + err_build_package_list: + return rc; +} + +/** + * Uninstall HII protocol and package for SNP device + * + * @v snpdev SNP device + */ +void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + + bs->UninstallMultipleProtocolInterfaces ( + snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ); + efihii->RemovePackageList ( efihii, snpdev->hii_handle ); + free ( snpdev->package_list ); + snpdev->package_list = NULL; +} diff --git a/roms/ipxe/src/interface/efi/efi_strerror.c b/roms/ipxe/src/interface/efi/efi_strerror.c index 430758f83..46bfbbb5b 100644 --- a/roms/ipxe/src/interface/efi/efi_strerror.c +++ b/roms/ipxe/src/interface/efi/efi_strerror.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_strings.c b/roms/ipxe/src/interface/efi/efi_strings.c index 0fbc45384..751589b46 100644 --- a/roms/ipxe/src/interface/efi/efi_strings.c +++ b/roms/ipxe/src/interface/efi/efi_strings.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_timer.c b/roms/ipxe/src/interface/efi/efi_timer.c index 1f8ad1504..b110cae29 100644 --- a/roms/ipxe/src/interface/efi/efi_timer.c +++ b/roms/ipxe/src/interface/efi/efi_timer.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_uaccess.c b/roms/ipxe/src/interface/efi/efi_uaccess.c index d80ca7a75..8b429b9ee 100644 --- a/roms/ipxe/src/interface/efi/efi_uaccess.c +++ b/roms/ipxe/src/interface/efi/efi_uaccess.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/efi/efi_umalloc.c b/roms/ipxe/src/interface/efi/efi_umalloc.c index d1d689ea2..b49949327 100644 --- a/roms/ipxe/src/interface/efi/efi_umalloc.c +++ b/roms/ipxe/src/interface/efi/efi_umalloc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/linux/linux_console.c b/roms/ipxe/src/interface/linux/linux_console.c index aeb7c6618..5105eaa94 100644 --- a/roms/ipxe/src/interface/linux/linux_console.c +++ b/roms/ipxe/src/interface/linux/linux_console.c @@ -33,6 +33,14 @@ FILE_LICENCE(GPL2_OR_LATER); #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 */ @@ -79,6 +87,7 @@ struct console_driver linux_console __console_driver = { .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) diff --git a/roms/ipxe/src/interface/linux/linux_entropy.c b/roms/ipxe/src/interface/linux/linux_entropy.c new file mode 100644 index 000000000..4671a48da --- /dev/null +++ b/roms/ipxe/src/interface/linux/linux_entropy.c @@ -0,0 +1,97 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/interface/linux/linux_nap.c b/roms/ipxe/src/interface/linux/linux_nap.c index 98642bad0..f1d3cd962 100644 --- a/roms/ipxe/src/interface/linux/linux_nap.c +++ b/roms/ipxe/src/interface/linux/linux_nap.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE(GPL2_OR_LATER); diff --git a/roms/ipxe/src/interface/linux/linux_time.c b/roms/ipxe/src/interface/linux/linux_time.c new file mode 100644 index 000000000..6d722aad0 --- /dev/null +++ b/roms/ipxe/src/interface/linux/linux_time.c @@ -0,0 +1,45 @@ +/* + * 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. + */ + +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/roms/ipxe/src/interface/linux/linux_uaccess.c b/roms/ipxe/src/interface/linux/linux_uaccess.c index d4e52d093..5ab0b6b65 100644 --- a/roms/ipxe/src/interface/linux/linux_uaccess.c +++ b/roms/ipxe/src/interface/linux/linux_uaccess.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE(GPL2_OR_LATER); diff --git a/roms/ipxe/src/interface/smbios/smbios.c b/roms/ipxe/src/interface/smbios/smbios.c index b60e10f76..8ed24dd66 100644 --- a/roms/ipxe/src/interface/smbios/smbios.c +++ b/roms/ipxe/src/interface/smbios/smbios.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/interface/smbios/smbios_settings.c b/roms/ipxe/src/interface/smbios/smbios_settings.c index 92dc41272..893b958e1 100644 --- a/roms/ipxe/src/interface/smbios/smbios_settings.c +++ b/roms/ipxe/src/interface/smbios/smbios_settings.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -119,14 +120,21 @@ static int smbios_fetch ( struct settings *settings __unused, if ( tag_len == 0 ) { /* String */ - return read_smbios_string ( &structure, - buf[tag_offset], - data, len ); + if ( ( rc = read_smbios_string ( &structure, + buf[tag_offset], + data, len ) ) < 0 ) { + return rc; + } + if ( ! setting->type ) + setting->type = &setting_type_string; + return rc; } else { /* Raw data */ if ( len > tag_len ) len = tag_len; memcpy ( data, &buf[tag_offset], len ); + if ( ! setting->type ) + setting->type = &setting_type_hex; return tag_len; } } diff --git a/roms/ipxe/src/net/80211/net80211.c b/roms/ipxe/src/net/80211/net80211.c index f5ab65f04..2181fc4ac 100644 --- a/roms/ipxe/src/net/80211/net80211.c +++ b/roms/ipxe/src/net/80211/net80211.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -135,7 +136,8 @@ static int net80211_ll_push ( struct net_device *netdev, 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 ); + const void **ll_source, uint16_t * net_proto, + unsigned int *flags ); /** @} */ /** @@ -159,7 +161,7 @@ net80211_marshal_request_info ( struct net80211_device *dev, * @defgroup net80211_assoc_ll 802.11 association handling functions * @{ */ -static void net80211_step_associate ( struct process *proc ); +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, @@ -385,9 +387,6 @@ static struct net_device_operations net80211_netdev_ops = { /* ---------- 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 * @@ -529,6 +528,7 @@ static int net80211_ll_push ( struct net_device *netdev, * @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 @@ -537,7 +537,7 @@ static int net80211_ll_push ( struct net_device *netdev, 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 ) + uint16_t * net_proto, unsigned int *flags ) { struct ieee80211_frame *hdr = iobuf->data; struct ieee80211_llc_snap_header *lhdr = @@ -586,6 +586,10 @@ static int net80211_ll_pull ( struct net_device *netdev __unused, *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; } @@ -729,6 +733,11 @@ int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc, u8 dest[6], /* ---------- 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 * @@ -751,7 +760,7 @@ struct net80211_device * net80211_alloc ( size_t priv_size ) return NULL; netdev->ll_protocol = &net80211_ll_protocol; - netdev->ll_broadcast = net80211_ll_broadcast; + netdev->ll_broadcast = eth_broadcast; netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN; netdev_init ( netdev, &net80211_netdev_ops ); @@ -760,7 +769,7 @@ struct net80211_device * net80211_alloc ( size_t priv_size ) dev->priv = ( u8 * ) dev + sizeof ( *dev ); dev->op = &net80211_null_ops; - process_init_stopped ( &dev->proc_assoc, net80211_step_associate, + process_init_stopped ( &dev->proc_assoc, &net80211_process_desc, &netdev->refcnt ); INIT_LIST_HEAD ( &dev->mgmt_queue ); INIT_LIST_HEAD ( &dev->mgmt_info_queue ); @@ -1387,7 +1396,7 @@ int net80211_probe_step ( struct net80211_probe_ctx *ctx ) ctx->probe = iob; rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ, - net80211_ll_broadcast, + eth_broadcast, iob_disown ( siob ) ); if ( rc ) { DBGC ( dev, "802.11 %p send probe failed: " @@ -1630,12 +1639,10 @@ void net80211_free_wlanlist ( struct list_head *list ) /** * Step 802.11 association process * - * @v proc Association process + * @v dev 802.11 device */ -static void net80211_step_associate ( struct process *proc ) +static void net80211_step_associate ( struct net80211_device *dev ) { - struct net80211_device *dev = - container_of ( proc, struct net80211_device, proc_assoc ); int rc = 0; int status = dev->state & NET80211_STATUS_MASK; @@ -1836,7 +1843,7 @@ static void net80211_step_associate ( struct process *proc ) dev->rctl = rc80211_init ( dev ); - process_del ( proc ); + process_del ( &dev->proc_assoc ); DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev, dev->essid, eth_ntoa ( dev->bssid ) ); @@ -1861,7 +1868,7 @@ static void net80211_step_associate ( struct process *proc ) net80211_free_wlan ( dev->associating ); dev->associating = NULL; - process_del ( proc ); + process_del ( &dev->proc_assoc ); DBGC ( dev, "802.11 %p association failed (state=%04x): " "%s\n", dev, dev->state, strerror ( dev->assoc_rc ) ); diff --git a/roms/ipxe/src/net/80211/rc80211.c b/roms/ipxe/src/net/80211/rc80211.c index 56bbc8a06..eea3bc908 100644 --- a/roms/ipxe/src/net/80211/rc80211.c +++ b/roms/ipxe/src/net/80211/rc80211.c @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/80211/sec80211.c b/roms/ipxe/src/net/80211/sec80211.c index 82b1ce941..d159edbdf 100644 --- a/roms/ipxe/src/net/80211/sec80211.c +++ b/roms/ipxe/src/net/80211/sec80211.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/80211/wep.c b/roms/ipxe/src/net/80211/wep.c index 3b1045525..37b27f71a 100644 --- a/roms/ipxe/src/net/80211/wep.c +++ b/roms/ipxe/src/net/80211/wep.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/80211/wpa.c b/roms/ipxe/src/net/80211/wpa.c index 38ddb911b..e2c4945f9 100644 --- a/roms/ipxe/src/net/80211/wpa.c +++ b/roms/ipxe/src/net/80211/wpa.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -29,9 +30,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 * @@ -514,7 +517,8 @@ static int wpa_handle_1_of_4 ( struct wpa_common_ctx *ctx, ctx->state = WPA_WORKING; memcpy ( ctx->Anonce, pkt->nonce, sizeof ( ctx->Anonce ) ); if ( ! ctx->have_Snonce ) { - get_random_bytes ( ctx->Snonce, sizeof ( ctx->Snonce ) ); + rbg_generate ( NULL, 0, 0, ctx->Snonce, + sizeof ( ctx->Snonce ) ); ctx->have_Snonce = 1; } diff --git a/roms/ipxe/src/net/80211/wpa_ccmp.c b/roms/ipxe/src/net/80211/wpa_ccmp.c index 89bb36fd8..f98ebea26 100644 --- a/roms/ipxe/src/net/80211/wpa_ccmp.c +++ b/roms/ipxe/src/net/80211/wpa_ccmp.c @@ -13,11 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/crypto.h> #include <ipxe/hmac.h> diff --git a/roms/ipxe/src/net/80211/wpa_psk.c b/roms/ipxe/src/net/80211/wpa_psk.c index 780738e79..71190b139 100644 --- a/roms/ipxe/src/net/80211/wpa_psk.c +++ b/roms/ipxe/src/net/80211/wpa_psk.c @@ -13,11 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/sha1.h> #include <ipxe/wpa.h> diff --git a/roms/ipxe/src/net/80211/wpa_tkip.c b/roms/ipxe/src/net/80211/wpa_tkip.c index 0a94df07e..fa3e0763b 100644 --- a/roms/ipxe/src/net/80211/wpa_tkip.c +++ b/roms/ipxe/src/net/80211/wpa_tkip.c @@ -13,11 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/crypto.h> #include <ipxe/hmac.h> @@ -543,15 +545,15 @@ struct net80211_crypto tkip_crypto __net80211_crypto = { static void tkip_kie_mic ( const void *kck, const void *msg, size_t len, void *mic ) { - struct md5_ctx md5; + uint8_t ctx[MD5_CTX_SIZE]; u8 kckb[16]; size_t kck_len = 16; memcpy ( kckb, kck, kck_len ); - hmac_init ( &md5_algorithm, &md5, kckb, &kck_len ); - hmac_update ( &md5_algorithm, &md5, msg, len ); - hmac_final ( &md5_algorithm, &md5, kckb, &kck_len, mic ); + hmac_init ( &md5_algorithm, ctx, kckb, &kck_len ); + hmac_update ( &md5_algorithm, ctx, msg, len ); + hmac_final ( &md5_algorithm, ctx, kckb, &kck_len, mic ); } /** diff --git a/roms/ipxe/src/net/aoe.c b/roms/ipxe/src/net/aoe.c index 3b1953a2f..a6d7b3e7b 100644 --- a/roms/ipxe/src/net/aoe.c +++ b/roms/ipxe/src/net/aoe.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -906,13 +907,14 @@ static int aoedev_open ( struct interface *parent, struct net_device *netdev, * @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 ) { + const void *ll_source, + unsigned int flags __unused ) { struct aoehdr *aoehdr = iobuf->data; struct aoe_command *aoecmd; int rc; diff --git a/roms/ipxe/src/net/arp.c b/roms/ipxe/src/net/arp.c index 9b5fd220e..b94eb9064 100644 --- a/roms/ipxe/src/net/arp.c +++ b/roms/ipxe/src/net/arp.c @@ -13,12 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> +#include <stdlib.h> #include <string.h> #include <byteswap.h> #include <errno.h> @@ -26,6 +28,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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/refcnt.h> #include <ipxe/arp.h> /** @file @@ -38,104 +45,291 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/** 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 { + /** Reference count */ + struct refcnt refcnt; + /** List of ARP cache entries */ + struct list_head list; + /** Network device */ + struct net_device *netdev; /** Network-layer protocol */ struct net_protocol *net_protocol; - /** Link-layer protocol */ - struct ll_protocol *ll_protocol; - /** Network-layer address */ - uint8_t net_addr[MAX_NET_ADDR_LEN]; - /** Link-layer address */ - uint8_t ll_addr[MAX_LL_ADDR_LEN]; + /** 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; }; -/** Number of entries in the ARP cache +/** 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 ); + +/** + * Free ARP cache entry * - * This is a global cache, covering all network interfaces, - * network-layer protocols and link-layer protocols. + * @v refcnt Reference count */ -#define NUM_ARP_ENTRIES 4 +static void arp_free ( struct refcnt *refcnt ) { + struct arp_entry *arp = + container_of ( refcnt, struct arp_entry, refcnt ); -/** The ARP cache */ -static struct arp_entry arp_table[NUM_ARP_ENTRIES]; -#define arp_table_end &arp_table[NUM_ARP_ENTRIES] + /* Sanity check */ + assert ( list_empty ( &arp->tx_queue ) ); -static unsigned int next_new_arp_entry = 0; + /* Drop reference to network device */ + netdev_put ( arp->netdev ); -struct net_protocol arp_protocol __net_protocol; + /* Free entry */ + free ( arp ); +} + +/** + * 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 and initialise entry */ + arp = zalloc ( sizeof ( *arp ) ); + if ( ! arp ) + return NULL; + ref_init ( &arp->refcnt, arp_free ); + 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, &arp->refcnt ); + arp->timer.min_timeout = ARP_MIN_TIMEOUT; + arp->timer.max_timeout = ARP_MAX_TIMEOUT; + INIT_LIST_HEAD ( &arp->tx_queue ); + + /* Start timer running to trigger initial transmission */ + start_timer_nodelay ( &arp->timer ); + + /* Transfer ownership to cache */ + list_add ( &arp->list, &arp_entries ); + + 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 ll_protocol Link-layer protocol + * @v netdev Network device * @v net_protocol Network-layer protocol - * @v net_addr Network-layer address + * @v net_dest Destination network-layer address * @ret arp ARP cache entry, or NULL if not found - * */ -static struct arp_entry * -arp_find_entry ( struct ll_protocol *ll_protocol, - struct net_protocol *net_protocol, - const void *net_addr ) { +static struct arp_entry * arp_find ( struct net_device *netdev, + struct net_protocol *net_protocol, + const void *net_dest ) { struct arp_entry *arp; - for ( arp = arp_table ; arp < arp_table_end ; arp++ ) { - if ( ( arp->ll_protocol == ll_protocol ) && + list_for_each_entry ( arp, &arp_entries, list ) { + if ( ( arp->netdev == netdev ) && ( arp->net_protocol == net_protocol ) && - ( memcmp ( arp->net_addr, net_addr, - net_protocol->net_addr_len ) == 0 ) ) + ( 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; } /** - * Look up media-specific link-layer address in the ARP cache + * 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; + + /* Take ownership from cache */ + list_del ( &arp->list ); + + /* Stop timer */ + stop_timer ( &arp->timer ); + + /* Discard any outstanding I/O buffers */ + while ( ( iobuf = list_first_entry ( &arp->tx_queue, struct io_buffer, + list ) ) != NULL ) { + 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 remaining reference */ + ref_put ( &arp->refcnt ); +} + +/** + * 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 dest_net_addr Destination network-layer address - * @v source_net_addr Source network-layer address - * @ret dest_ll_addr Destination link layer address + * @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 * - * This function will use the ARP cache to look up the link-layer - * address for the link-layer protocol associated with the network - * device and the given network-layer protocol and addresses. If - * found, the destination link-layer address will be filled in in @c - * dest_ll_addr. + * @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; + 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. Take out a temporary + * reference on the entry to prevent it from going out of + * scope during the call to net_tx(). + */ + ref_get ( &arp->refcnt ); + while ( ( iobuf = list_first_entry ( &arp->tx_queue, struct io_buffer, + list ) ) != NULL ) { + 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 */ + } + } + ref_put ( &arp->refcnt ); +} + +/** + * Handle ARP timer expiry * - * If no address is found in the ARP cache, an ARP request will be - * transmitted on the specified network device and -ENOENT will be - * returned. + * @v timer Retry timer + * @v fail Failure indicator */ -int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, - const void *dest_net_addr, const void *source_net_addr, - void *dest_ll_addr ) { +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; - const struct arp_entry *arp; + struct net_protocol *net_protocol = arp->net_protocol; struct io_buffer *iobuf; struct arphdr *arphdr; int rc; - /* Look for existing entry in ARP table */ - arp = arp_find_entry ( ll_protocol, net_protocol, dest_net_addr ); - if ( arp ) { - DBG ( "ARP cache hit: %s %s => %s %s\n", - net_protocol->name, net_protocol->ntoa ( arp->net_addr ), - ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); - memcpy ( dest_ll_addr, arp->ll_addr, ll_protocol->ll_addr_len); - return 0; + /* If we have failed, destroy the cache entry */ + if ( fail ) { + arp_destroy ( arp, -ETIMEDOUT ); + return; } - DBG ( "ARP cache miss: %s %s\n", net_protocol->name, - net_protocol->ntoa ( dest_net_addr ) ); + + /* 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 ) - return -ENOMEM; + ( 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 */ @@ -148,18 +342,19 @@ int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, 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 ), - source_net_addr, 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 ), - dest_net_addr, 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 ) - return rc; - - return -ENOENT; + netdev->ll_broadcast, netdev->ll_addr ) ) != 0 ) { + DBGC ( arp, "ARP %p could not transmit request: %s\n", + arp, strerror ( rc ) ); + return; + } } /** @@ -186,87 +381,80 @@ static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) { * @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 - * - * This handles ARP requests and responses as detailed in RFC826. The - * method detailed within the RFC is pretty optimised, handling - * requests and responses with basically a single code path and - * avoiding the need for extraneous ARP requests; read the RFC for - * details. */ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, - const void *ll_source __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 merge = 0; + int rc; /* Identify network-layer and link-layer protocols */ arp_net_protocol = arp_find_protocol ( arphdr->ar_pro ); - if ( ! arp_net_protocol ) + 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 ) ) + ( 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_entry ( ll_protocol, net_protocol, - arp_sender_pa ( arphdr ) ); + arp = arp_find ( netdev, net_protocol, arp_sender_pa ( arphdr ) ); if ( arp ) { - memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ), - arphdr->ar_hln ); - merge = 1; - DBG ( "ARP cache update: %s %s => %s %s\n", - net_protocol->name, net_protocol->ntoa ( arp->net_addr ), - ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); + arp_update ( arp, arp_sender_ha ( arphdr ) ); } - /* See if we own the target protocol address */ - if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0) + /* If it's not a request, there's nothing more to do */ + if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) ) { + rc = 0; goto done; - - /* Create new ARP table entry if necessary */ - if ( ! merge ) { - arp = &arp_table[next_new_arp_entry++ % NUM_ARP_ENTRIES]; - arp->ll_protocol = ll_protocol; - arp->net_protocol = net_protocol; - memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ), - arphdr->ar_hln ); - memcpy ( arp->net_addr, arp_sender_pa ( arphdr ), - arphdr->ar_pln); - DBG ( "ARP cache add: %s %s => %s %s\n", - net_protocol->name, net_protocol->ntoa ( arp->net_addr ), - ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) ); } - /* If it's not a request, there's nothing more to do */ - if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) ) + /* 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 */ - DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name, - net_protocol->ntoa ( arp_target_pa ( arphdr ) ), - ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) ); + 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 */ - net_tx ( iob_disown ( iobuf ), netdev, &arp_protocol, - arp_target_ha ( arphdr ), netdev->ll_addr ); + 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 0; + return rc; } /** @@ -288,3 +476,65 @@ struct net_protocol arp_protocol __net_protocol = { .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 */ + arp = list_last_entry ( &arp_entries, struct arp_entry, list ); + if ( arp ) { + arp_destroy ( arp, -ENOBUFS ); + return 1; + } else { + return 0; + } +} + +/** ARP cache discarder + * + * ARP cache entries are deemed to have a high replacement cost, since + * flushing an active ARP cache entry midway through a TCP transfer + * will cause substantial disruption. + */ +struct cache_discarder arp_discarder __cache_discarder ( CACHE_EXPENSIVE ) = { + .discard = arp_discard, +}; diff --git a/roms/ipxe/src/net/cachedhcp.c b/roms/ipxe/src/net/cachedhcp.c index 36f480a96..fc7dabc90 100644 --- a/roms/ipxe/src/net/cachedhcp.c +++ b/roms/ipxe/src/net/cachedhcp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/dhcpopts.c b/roms/ipxe/src/net/dhcpopts.c index 249fde151..6d29a7b5e 100644 --- a/roms/ipxe/src/net/dhcpopts.c +++ b/roms/ipxe/src/net/dhcpopts.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/dhcppkt.c b/roms/ipxe/src/net/dhcppkt.c index 0a0e458fc..528f90037 100644 --- a/roms/ipxe/src/net/dhcppkt.c +++ b/roms/ipxe/src/net/dhcppkt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/eapol.c b/roms/ipxe/src/net/eapol.c index 9e5f26401..eb0362994 100644 --- a/roms/ipxe/src/net/eapol.c +++ b/roms/ipxe/src/net/eapol.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -38,11 +39,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @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 ) { + const void *ll_dest, const void *ll_source, + unsigned int flags __unused ) { struct eapol_frame *eapol = iob->data; struct eapol_handler *handler; diff --git a/roms/ipxe/src/net/eth_slow.c b/roms/ipxe/src/net/eth_slow.c index 9e68939cf..69c38f30a 100644 --- a/roms/ipxe/src/net/eth_slow.c +++ b/roms/ipxe/src/net/eth_slow.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -234,12 +235,14 @@ static int eth_slow_marker_rx ( struct io_buffer *iobuf, * @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 ) { + const void *ll_source __unused, + unsigned int flags __unused ) { union eth_slow_packet *eth_slow = iobuf->data; /* Sanity checks */ diff --git a/roms/ipxe/src/net/ethernet.c b/roms/ipxe/src/net/ethernet.c index d14cfefcc..4fd2ab6e5 100644 --- a/roms/ipxe/src/net/ethernet.c +++ b/roms/ipxe/src/net/ethernet.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -38,7 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** Ethernet broadcast MAC address */ -static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** * Add Ethernet link-layer header @@ -50,9 +51,9 @@ static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; * @v net_proto Network-layer protocol, in network-byte order * @ret rc Return status code */ -static int eth_push ( struct net_device *netdev __unused, - struct io_buffer *iobuf, const void *ll_dest, - const void *ll_source, uint16_t net_proto ) { +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 */ @@ -71,11 +72,12 @@ static int eth_push ( struct net_device *netdev __unused, * @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 eth_pull ( struct net_device *netdev __unused, - struct io_buffer *iobuf, const void **ll_dest, - const void **ll_source, uint16_t *net_proto ) { +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 */ @@ -92,6 +94,10 @@ static int eth_pull ( struct net_device *netdev __unused, *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; } diff --git a/roms/ipxe/src/net/fakedhcp.c b/roms/ipxe/src/net/fakedhcp.c index b43e9b124..d67501ed3 100644 --- a/roms/ipxe/src/net/fakedhcp.c +++ b/roms/ipxe/src/net/fakedhcp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -114,7 +115,8 @@ int create_fakedhcpdiscover ( struct net_device *netdev, int rc; if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER, - ciaddr, data, max_len ) ) != 0 ) { + dhcp_last_xid, ciaddr, data, + max_len ) ) != 0 ) { DBG ( "Could not create DHCPDISCOVER: %s\n", strerror ( rc ) ); return rc; @@ -139,7 +141,8 @@ int create_fakedhcpack ( struct net_device *netdev, int rc; /* Create base DHCPACK packet */ - if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0, + 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; @@ -190,7 +193,8 @@ int create_fakepxebsack ( struct net_device *netdev, } /* Create base DHCPACK packet */ - if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0, + 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 ) ); diff --git a/roms/ipxe/src/net/fc.c b/roms/ipxe/src/net/fc.c index 1934fab3d..58008995c 100644 --- a/roms/ipxe/src/net/fc.c +++ b/roms/ipxe/src/net/fc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -1580,7 +1581,7 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) { fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) ); /* Sanity check */ - assert ( ulp->usage == 0 ); + assert ( list_empty ( &ulp->users ) ); /* Stop link monitor */ fc_link_stop ( &ulp->link ); @@ -1594,35 +1595,50 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) { } /** - * Increment Fibre Channel upper-layer protocol active usage count + * Attach Fibre Channel upper-layer protocol user * - * @v ulp Fibre Channel ulp + * @v ulp Fibre Channel upper-layer protocol + * @v user Fibre Channel upper-layer protocol user */ -void fc_ulp_increment ( struct fc_ulp *ulp ) { +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 ); - /* Increment our usage count */ - ulp->usage++; + /* Attach user */ + user->ulp = fc_ulp_get ( ulp ); + list_add ( &user->list, &ulp->users ); } /** - * Decrement Fibre Channel upper-layer protocol active usage count + * Detach Fibre Channel upper-layer protocol user * - * @v ulp Fibre Channel ulp + * @v user Fibre Channel upper-layer protocol user */ -void fc_ulp_decrement ( struct fc_ulp *ulp ) { +void fc_ulp_detach ( struct fc_ulp_user *user ) { + struct fc_ulp *ulp = user->ulp; - /* Sanity check */ - assert ( ulp->usage > 0 ); + /* Do nothing if not attached */ + if ( ! ulp ) + return; - /* Decrement our usage count and log out if we reach zero */ - if ( --(ulp->usage) == 0 ) + /* 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 ); } /** @@ -1636,6 +1652,8 @@ void fc_ulp_decrement ( struct fc_ulp *ulp ) { */ 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 ) && @@ -1644,6 +1662,22 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len, 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 ) ) { @@ -1670,18 +1704,11 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len, /* Record login */ fc_link_up ( &ulp->link ); - /* 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_start ( &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; @@ -1694,6 +1721,8 @@ int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len, * @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 ) ); @@ -1711,8 +1740,15 @@ void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) { /* 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 ( ulp->usage == 0 ) + if ( list_empty ( &ulp->users ) ) fc_ulp_close ( ulp, rc ); } @@ -1795,6 +1831,7 @@ static struct fc_ulp * fc_ulp_create ( struct fc_peer *peer, 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 ); diff --git a/roms/ipxe/src/net/fcels.c b/roms/ipxe/src/net/fcels.c index f8bcb865f..1cfe90727 100644 --- a/roms/ipxe/src/net/fcels.c +++ b/roms/ipxe/src/net/fcels.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -244,20 +245,15 @@ static struct interface_descriptor fc_els_job_desc = /** * Fibre Channel ELS process * - * @v process Process + * @v els Fibre Channel ELS transaction */ -static void fc_els_step ( struct process *process ) { - struct fc_els *els = - container_of ( process, struct fc_els, process ); +static void fc_els_step ( struct fc_els *els ) { int xchg_id; int rc; /* Sanity check */ assert ( fc_els_is_request ( els ) ); - /* Stop process */ - process_del ( &els->process ); - /* Create exchange */ if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port, &els->peer_port_id, @@ -278,6 +274,10 @@ static void fc_els_step ( struct process *process ) { } } +/** 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 * @@ -298,7 +298,8 @@ static struct fc_els * fc_els_create ( struct fc_port *port, 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_step, &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, diff --git a/roms/ipxe/src/net/fcns.c b/roms/ipxe/src/net/fcns.c index 7769e255e..3ca4ad557 100644 --- a/roms/ipxe/src/net/fcns.c +++ b/roms/ipxe/src/net/fcns.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -153,19 +154,14 @@ static int fc_ns_query_deliver ( struct fc_ns_query *query, /** * Name server query process * - * @v process Process + * @v query Name server query */ -static void fc_ns_query_step ( struct process *process ) { - struct fc_ns_query *query = - container_of ( process, struct fc_ns_query, process ); +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; - /* Stop process */ - process_del ( &query->process ); - /* Create exchange */ if ( ( xchg_id = fc_xchg_originate ( &query->xchg, query->port, &fc_gs_port_id, @@ -208,6 +204,10 @@ static struct interface_operation fc_ns_query_xchg_op[] = { 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 * @@ -226,7 +226,8 @@ int fc_ns_query ( struct fc_peer *peer, struct fc_port *port, 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_step, &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; diff --git a/roms/ipxe/src/net/fcoe.c b/roms/ipxe/src/net/fcoe.c index db2fc9806..d11304258 100644 --- a/roms/ipxe/src/net/fcoe.c +++ b/roms/ipxe/src/net/fcoe.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -331,10 +332,12 @@ static struct io_buffer * fcoe_alloc_iob ( struct fcoe_port *fcoe __unused, * @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 ) { + const void *ll_dest, const void *ll_source, + unsigned int flags __unused ) { struct fcoe_header *fcoehdr; struct fcoe_footer *fcoeftr; struct fcoe_port *fcoe; @@ -924,12 +927,14 @@ static struct fip_handler fip_handlers[] = { * @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 ) { + const void *ll_source __unused, + unsigned int flags __unused ) { struct fip_header *fiphdr = iobuf->data; struct fip_descriptors descs; struct fip_handler *handler; diff --git a/roms/ipxe/src/net/fcp.c b/roms/ipxe/src/net/fcp.c index 40cd057e6..241b54638 100644 --- a/roms/ipxe/src/net/fcp.c +++ b/roms/ipxe/src/net/fcp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -146,8 +147,8 @@ struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor = { struct fcp_device { /** Reference count */ struct refcnt refcnt; - /** Fibre Channel upper-layer protocol */ - struct fc_ulp *ulp; + /** Fibre Channel upper-layer protocol user */ + struct fc_ulp_user user; /** SCSI command issuing interface */ struct interface scsi; /** List of active commands */ @@ -649,11 +650,9 @@ static int fcpcmd_recv_unknown ( struct fcp_command *fcpcmd, /** * Transmit FCP frame * - * @v process FCP command process + * @v fcpcmd FCP command */ -static void fcpcmd_step ( struct process *process ) { - struct fcp_command *fcpcmd = - container_of ( process, struct fcp_command, process ); +static void fcpcmd_step ( struct fcp_command *fcpcmd ) { int rc; /* Send the current IU */ @@ -723,6 +722,10 @@ static struct interface_operation fcpcmd_xchg_op[] = { 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 * @@ -734,13 +737,13 @@ static struct interface_descriptor fcpcmd_xchg_desc = static int fcpdev_scsi_command ( struct fcp_device *fcpdev, struct interface *parent, struct scsi_cmd *command ) { - struct fcp_prli_service_parameters *param = fcpdev->ulp->param; + struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param; struct fcp_command *fcpcmd; int xchg_id; int rc; /* Check link */ - if ( ( rc = fcpdev->ulp->link.rc ) != 0 ) { + 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; @@ -748,7 +751,7 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev, /* Check target capability */ assert ( param != NULL ); - assert ( fcpdev->ulp->param_len >= sizeof ( *param ) ); + 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 ); @@ -765,15 +768,16 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev, 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_step, &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->ulp->peer->port, - &fcpdev->ulp->peer->port_id, + 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", @@ -822,11 +826,7 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) { } /* Drop reference to ULP */ - if ( fcpdev->ulp ) { - fc_ulp_decrement ( fcpdev->ulp ); - fc_ulp_put ( fcpdev->ulp ); - fcpdev->ulp = NULL; - } + fc_ulp_detach ( &fcpdev->user ); } /** @@ -836,7 +836,8 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) { * @ret len Length of window */ static size_t fcpdev_window ( struct fcp_device *fcpdev ) { - return ( fc_link_ok ( &fcpdev->ulp->link ) ? ~( ( size_t ) 0 ) : 0 ); + return ( fc_link_ok ( &fcpdev->user.ulp->link ) ? + ~( ( size_t ) 0 ) : 0 ); } /** @@ -897,15 +898,15 @@ 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->ulp->link ) ) { + 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->ulp->peer->port != NULL ); - return identify_device ( &fcpdev->ulp->peer->port->transport ); + assert ( fcpdev->user.ulp->peer->port != NULL ); + return identify_device ( &fcpdev->user.ulp->peer->port->transport ); } /** FCP device SCSI interface operations */ @@ -923,6 +924,26 @@ static struct interface_operation fcpdev_scsi_op[] = { 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 * @@ -953,11 +974,13 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn, ref_init ( &fcpdev->refcnt, NULL ); intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt ); INIT_LIST_HEAD ( &fcpdev->fcpcmds ); - fcpdev->ulp = fc_ulp_get ( ulp ); - fc_ulp_increment ( fcpdev->ulp ); + 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 ) ); diff --git a/roms/ipxe/src/net/icmp.c b/roms/ipxe/src/net/icmp.c index 84dad4256..830d82924 100644 --- a/roms/ipxe/src/net/icmp.c +++ b/roms/ipxe/src/net/icmp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/infiniband.c b/roms/ipxe/src/net/infiniband.c index c2cb834df..12d1d83ce 100644 --- a/roms/ipxe/src/net/infiniband.c +++ b/roms/ipxe/src/net/infiniband.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -167,6 +168,7 @@ void ib_poll_cq ( struct ib_device *ibdev, * @v send_cq Send completion queue * @v num_recv_wqes Number of receive work queue entries * @v recv_cq Receive completion queue + * @v op Queue pair operations * @ret qp Queue pair * * The queue pair will be left in the INIT state; you must call @@ -177,7 +179,8 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, - struct ib_completion_queue *recv_cq ) { + struct ib_completion_queue *recv_cq, + struct ib_queue_pair_operations *op ) { struct ib_queue_pair *qp; size_t total_size; int rc; @@ -209,6 +212,7 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) + ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) )); INIT_LIST_HEAD ( &qp->mgids ); + qp->op = op; /* Perform device-specific initialisation and get QPN */ if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) { @@ -259,7 +263,6 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, * * @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 ) { @@ -301,7 +304,7 @@ void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { } for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) { if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) { - ib_complete_recv ( ibdev, qp, NULL, iobuf, + ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, -ECANCELED ); } } @@ -380,14 +383,14 @@ struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination 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 ib_address_vector *dest, struct io_buffer *iobuf ) { - struct ib_address_vector av_copy; + struct ib_address_vector dest_copy; int rc; /* Check queue fill level */ @@ -398,21 +401,21 @@ int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, } /* Use default address vector if none specified */ - if ( ! av ) - av = &qp->av; + if ( ! dest ) + dest = &qp->av; /* Make modifiable copy of address vector */ - memcpy ( &av_copy, av, sizeof ( av_copy ) ); - av = &av_copy; + memcpy ( &dest_copy, dest, sizeof ( dest_copy ) ); + dest = &dest_copy; /* Fill in optional parameters in address vector */ - if ( ! av->qkey ) - av->qkey = qp->qkey; - if ( ! av->rate ) - av->rate = IB_RATE_2_5; + if ( ! dest->qkey ) + dest->qkey = qp->qkey; + if ( ! dest->rate ) + dest->rate = IB_RATE_2_5; /* Post to hardware */ - if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) { + if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) { DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: " "%s\n", ibdev, qp->qpn, strerror ( rc ) ); return rc; @@ -483,16 +486,19 @@ void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v dest Destination address vector, or NULL + * @v source Source 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 ib_address_vector *dest, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { if ( qp->recv.cq->op->complete_recv ) { - qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc ); + qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source, + iobuf, rc ); } else { free_iob ( iobuf ); } @@ -513,7 +519,7 @@ void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { while ( qp->recv.fill < qp->recv.num_wqes ) { /* Allocate I/O buffer */ - iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE ); + iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE ); if ( ! iobuf ) { /* Non-fatal; we will refill on next attempt */ return; @@ -610,6 +616,13 @@ int ib_open ( struct ib_device *ibdev ) { 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 ) { @@ -633,13 +646,6 @@ int ib_open ( struct ib_device *ibdev ) { goto err_create_gsi; } - /* Open device */ - if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) { - DBGC ( ibdev, "IBDEV %p could not open: %s\n", - ibdev, strerror ( rc ) ); - goto err_open; - } - /* Add to head of open devices list */ list_add ( &ibdev->open_list, &open_ib_devices ); @@ -649,14 +655,14 @@ int ib_open ( struct ib_device *ibdev ) { assert ( ibdev->open_count == 1 ); return 0; - ibdev->op->close ( ibdev ); - err_open: 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; @@ -680,6 +686,7 @@ void ib_close ( struct ib_device *ibdev ) { ib_destroy_sma ( ibdev, ibdev->smi ); ib_destroy_mi ( ibdev, ibdev->smi ); ibdev->op->close ( ibdev ); + ibdev->port_state = IB_PORT_STATE_DOWN; } } @@ -861,15 +868,12 @@ void ib_poll_eq ( struct ib_device *ibdev ) { static void ib_step ( struct process *process __unused ) { struct ib_device *ibdev; - for_each_ibdev ( ibdev ) + list_for_each_entry ( ibdev, &open_ib_devices, open_list ) ib_poll_eq ( ibdev ); } /** Infiniband event queue process */ -struct process ib_process __permanent_process = { - .list = LIST_HEAD_INIT ( ib_process.list ), - .step = ib_step, -}; +PERMANENT_PROCESS ( ib_process, ib_step ); /*************************************************************************** * diff --git a/roms/ipxe/src/net/infiniband/ib_cm.c b/roms/ipxe/src/net/infiniband/ib_cm.c index 1a0646beb..797639bc8 100644 --- a/roms/ipxe/src/net/infiniband/ib_cm.c +++ b/roms/ipxe/src/net/infiniband/ib_cm.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/infiniband/ib_cmrc.c b/roms/ipxe/src/net/infiniband/ib_cmrc.c index ed388b2f1..1cc0fcfef 100644 --- a/roms/ipxe/src/net/infiniband/ib_cmrc.c +++ b/roms/ipxe/src/net/infiniband/ib_cmrc.c @@ -92,7 +92,7 @@ struct ib_cmrc_connection { /** * Shut down CMRC connection gracefully * - * @v process Process + * @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 @@ -107,9 +107,7 @@ struct ib_cmrc_connection { * connection, ensuring that the structure is not freed before the * shutdown process has run. */ -static void ib_cmrc_shutdown ( struct process *process ) { - struct ib_cmrc_connection *cmrc = - container_of ( process, struct ib_cmrc_connection, shutdown ); +static void ib_cmrc_shutdown ( struct ib_cmrc_connection *cmrc ) { DBGC ( cmrc, "CMRC %p shutting down\n", cmrc ); @@ -119,9 +117,6 @@ static void ib_cmrc_shutdown ( struct process *process ) { ib_destroy_cq ( cmrc->ibdev, cmrc->cq ); ib_close ( cmrc->ibdev ); - /* Remove process from run queue */ - process_del ( &cmrc->shutdown ); - /* Drop the remaining reference */ ref_put ( &cmrc->refcnt ); } @@ -180,6 +175,9 @@ static void ib_cmrc_changed ( struct ib_device *ibdev __unused, 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 ); @@ -222,13 +220,15 @@ static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v dest Destination address vector, or NULL + * @v source Source 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 ib_address_vector *dest __unused, + struct ib_address_vector *source __unused, struct io_buffer *iobuf, int rc ) { struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp ); @@ -259,6 +259,11 @@ static struct ib_completion_queue_operations ib_cmrc_completion_ops = { .complete_recv = ib_cmrc_complete_recv, }; +/** Infiniband CMRC queue pair operations */ +static struct ib_queue_pair_operations ib_cmrc_queue_pair_ops = { + .alloc_iob = alloc_iob, +}; + /** * Send data via CMRC * @@ -360,6 +365,11 @@ static struct interface_operation ib_cmrc_xfer_operations[] = { 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 * @@ -385,7 +395,7 @@ int ib_cmrc_open ( struct interface *xfer, struct ib_device *ibdev, 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, + process_init_stopped ( &cmrc->shutdown, &ib_cmrc_shutdown_desc, &cmrc->refcnt ); /* Open Infiniband device */ @@ -407,7 +417,8 @@ int ib_cmrc_open ( struct interface *xfer, struct ib_device *ibdev, /* 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 ); + cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq, + &ib_cmrc_queue_pair_ops ); if ( ! cmrc->qp ) { DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc ); rc = -ENOMEM; diff --git a/roms/ipxe/src/net/infiniband/ib_mcast.c b/roms/ipxe/src/net/infiniband/ib_mcast.c index 0f03b54ac..0a5e72a37 100644 --- a/roms/ipxe/src/net/infiniband/ib_mcast.c +++ b/roms/ipxe/src/net/infiniband/ib_mcast.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/infiniband/ib_mi.c b/roms/ipxe/src/net/infiniband/ib_mi.c index d4cf58a66..ef6d539f1 100644 --- a/roms/ipxe/src/net/infiniband/ib_mi.c +++ b/roms/ipxe/src/net/infiniband/ib_mi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -111,13 +112,15 @@ static int ib_mi_handle ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector + * @v source Source 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 ib_address_vector *dest __unused, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp ); union ib_mad *mad; @@ -151,7 +154,7 @@ static void ib_mi_complete_recv ( struct ib_device *ibdev, DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) ); /* Handle MAD */ - if ( ( rc = ib_mi_handle ( ibdev, mi, mad, av ) ) != 0 ) + if ( ( rc = ib_mi_handle ( ibdev, mi, mad, source ) ) != 0 ) goto out; out: @@ -163,6 +166,11 @@ static struct ib_completion_queue_operations ib_mi_completion_ops = { .complete_recv = ib_mi_complete_recv, }; +/** Management interface queue pair operations */ +static struct ib_queue_pair_operations ib_mi_queue_pair_ops = { + .alloc_iob = alloc_iob, +}; + /** * Transmit MAD * @@ -352,7 +360,8 @@ struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev, /* Create queue pair */ mi->qp = ib_create_qp ( ibdev, type, IB_MI_NUM_SEND_WQES, mi->cq, - IB_MI_NUM_RECV_WQES, mi->cq ); + IB_MI_NUM_RECV_WQES, mi->cq, + &ib_mi_queue_pair_ops ); if ( ! mi->qp ) { DBGC ( mi, "MI %p could not allocate queue pair\n", mi ); goto err_create_qp; diff --git a/roms/ipxe/src/net/infiniband/ib_packet.c b/roms/ipxe/src/net/infiniband/ib_packet.c index d58e0ad4b..6c850e39b 100644 --- a/roms/ipxe/src/net/infiniband/ib_packet.c +++ b/roms/ipxe/src/net/infiniband/ib_packet.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -41,11 +42,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v iobuf I/O buffer to contain headers * @v qp Queue pair * @v payload_len Payload length - * @v av Address vector + * @v dest Destination address vector + * @ret rc Return status code */ 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 ) { + const struct ib_address_vector *dest ) { struct ib_local_route_header *lrh; struct ib_global_route_header *grh; struct ib_base_transport_header *bth; @@ -58,7 +60,8 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, 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 ); + ibdev, ibdev->lid, qp->ext_qpn, dest->lid, dest->qpn, + dest->qkey ); /* Calculate packet length */ pad_len = ( (-payload_len) & 0x3 ); @@ -70,7 +73,7 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *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 ? + grh = ( dest->gid_present ? iob_push ( iobuf, sizeof ( *grh ) ) : NULL ); lrh = iob_push ( iobuf, sizeof ( *lrh ) ); lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len ); @@ -79,8 +82,8 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, 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->sl__lnh = ( ( dest->sl << 4 ) | lnh ); + lrh->dlid = htons ( dest->lid ); lrh->length = htons ( lrh_len >> 2 ); lrh->slid = htons ( ibdev->lid ); @@ -92,18 +95,18 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, 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 ) ); + memcpy ( &grh->dgid, &dest->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->dest_qp = htonl ( dest->qpn ); bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL ); /* Construct DETH */ - deth->qkey = htonl ( av->qkey ); + deth->qkey = htonl ( dest->qkey ); deth->src_qp = htonl ( qp->ext_qpn ); DBGCP_HDA ( ibdev, 0, iobuf->data, @@ -119,11 +122,14 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, * @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 + * @v dest Destination address vector to fill in + * @v source Source address vector to fill in + * @ret rc Return status code */ 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_address_vector *dest, + struct ib_address_vector *source ) { struct ib_local_route_header *lrh; struct ib_global_route_header *grh; struct ib_base_transport_header *bth; @@ -131,15 +137,14 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, 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 ) ); + memset ( dest, 0, sizeof ( *dest ) ); + memset ( source, 0, sizeof ( *source ) ); /* Extract LRH */ if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) { @@ -149,10 +154,11 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } lrh = iobuf->data; iob_pull ( iobuf, sizeof ( *lrh ) ); - av->lid = ntohs ( lrh->slid ); - av->sl = ( lrh->sl__lnh >> 4 ); + dest->lid = ntohs ( lrh->dlid ); + dest->sl = ( lrh->sl__lnh >> 4 ); + source->lid = ntohs ( lrh->slid ); + source->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 ) ) ) { @@ -170,8 +176,10 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } grh = iobuf->data; iob_pull ( iobuf, sizeof ( *grh ) ); - av->gid_present = 1; - memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) ); + dest->gid_present = 1; + memcpy ( &dest->gid, &grh->dgid, sizeof ( dest->gid ) ); + source->gid_present = 1; + memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) ); } else { grh = NULL; } @@ -189,7 +197,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, ibdev, bth->opcode ); return -ENOTSUP; } - qpn = ntohl ( bth->dest_qp ); + dest->qpn = ntohl ( bth->dest_qp ); /* Extract DETH */ if ( iob_len ( iobuf ) < sizeof ( *deth ) ) { @@ -199,8 +207,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } deth = iobuf->data; iob_pull ( iobuf, sizeof ( *deth ) ); - av->qpn = ntohl ( deth->src_qp ); - av->qkey = ntohl ( deth->qkey ); + source->qpn = ntohl ( deth->src_qp ); + source->qkey = ntohl ( deth->qkey ); /* Calculate payload length, if applicable */ if ( payload_len ) { @@ -212,7 +220,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, /* Determine destination QP, if applicable */ if ( qp ) { - if ( IB_LID_MULTICAST ( lid ) && grh ) { + if ( IB_LID_MULTICAST ( dest->lid ) && grh ) { if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){ DBGC ( ibdev, "IBDEV %p RX for unknown MGID " IB_GID_FMT "\n", @@ -220,9 +228,9 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, return -ENODEV; } } else { - if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) { + if ( ! ( *qp = ib_find_qp_qpn ( ibdev, dest->qpn ) ) ) { DBGC ( ibdev, "IBDEV %p RX for nonexistent " - "QPN %lx\n", ibdev, qpn ); + "QPN %lx\n", ibdev, dest->qpn ); return -ENODEV; } } @@ -230,9 +238,9 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } 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 ) ); + ibdev, dest->lid, ( IB_LID_MULTICAST ( dest->lid ) ? + ( qp ? (*qp)->ext_qpn : -1UL ) : dest->qpn ), + source->lid, source->qpn, ntohl ( deth->qkey ) ); DBGCP_HDA ( ibdev, 0, ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ), ( orig_iob_len - iob_len ( iobuf ) ) ); diff --git a/roms/ipxe/src/net/infiniband/ib_pathrec.c b/roms/ipxe/src/net/infiniband/ib_pathrec.c index 7b9146547..1b95cbfa8 100644 --- a/roms/ipxe/src/net/infiniband/ib_pathrec.c +++ b/roms/ipxe/src/net/infiniband/ib_pathrec.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/infiniband/ib_sma.c b/roms/ipxe/src/net/infiniband/ib_sma.c index 1f3c6d804..86553732a 100644 --- a/roms/ipxe/src/net/infiniband/ib_sma.c +++ b/roms/ipxe/src/net/infiniband/ib_sma.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/infiniband/ib_smc.c b/roms/ipxe/src/net/infiniband/ib_smc.c index 8196cb7e3..4d947d568 100644 --- a/roms/ipxe/src/net/infiniband/ib_smc.c +++ b/roms/ipxe/src/net/infiniband/ib_smc.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/iobpad.c b/roms/ipxe/src/net/iobpad.c index f83c76d87..9cc8328e9 100644 --- a/roms/ipxe/src/net/iobpad.c +++ b/roms/ipxe/src/net/iobpad.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/ipv4.c b/roms/ipxe/src/net/ipv4.c index b2d51ada4..791d41951 100644 --- a/roms/ipxe/src/net/ipv4.c +++ b/roms/ipxe/src/net/ipv4.c @@ -14,6 +14,7 @@ #include <ipxe/tcpip.h> #include <ipxe/dhcp.h> #include <ipxe/settings.h> +#include <ipxe/timer.h> /** @file * @@ -23,14 +24,17 @@ FILE_LICENCE ( GPL2_OR_LATER ); -/* Unique IP datagram identification number */ -static uint16_t next_ident = 0; +/* 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 ( frag_buffers ); +static LIST_HEAD ( ipv4_fragments ); + +/** Fragment reassembly timeout */ +#define IP_FRAG_TIMEOUT ( TICKS_PER_SEC / 2 ) /** * Add IPv4 minirouting table entry @@ -46,16 +50,16 @@ add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address, struct in_addr netmask, struct in_addr gateway ) { struct ipv4_miniroute *miniroute; - DBG ( "IPv4 add %s", inet_ntoa ( address ) ); - DBG ( "/%s ", inet_ntoa ( netmask ) ); + DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) ); + DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) ); if ( gateway.s_addr ) - DBG ( "gw %s ", inet_ntoa ( gateway ) ); - DBG ( "via %s\n", netdev->name ); + 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 ) { - DBG ( "IPv4 could not add miniroute\n" ); + DBGC ( netdev, "IPv4 could not add miniroute\n" ); return NULL; } @@ -83,12 +87,13 @@ add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address, * @v miniroute Routing table entry */ static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) { + struct net_device *netdev = miniroute->netdev; - DBG ( "IPv4 del %s", inet_ntoa ( miniroute->address ) ); - DBG ( "/%s ", inet_ntoa ( miniroute->netmask ) ); + DBGC ( netdev, "IPv4 del %s", inet_ntoa ( miniroute->address ) ); + DBGC ( netdev, "/%s ", inet_ntoa ( miniroute->netmask ) ); if ( miniroute->gateway.s_addr ) - DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) ); - DBG ( "via %s\n", miniroute->netdev->name ); + DBGC ( netdev, "gw %s ", inet_ntoa ( miniroute->gateway ) ); + DBGC ( netdev, "via %s\n", miniroute->netdev->name ); netdev_put ( miniroute->netdev ); list_del ( &miniroute->list ); @@ -110,10 +115,6 @@ static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) { int local; int has_gw; - /* Never attempt to route the broadcast address */ - if ( dest->s_addr == INADDR_BROADCAST ) - return NULL; - /* Find first usable route in routing table */ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { if ( ! netdev_is_open ( miniroute->netdev ) ) @@ -132,103 +133,128 @@ static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) { } /** - * Fragment reassembly counter timeout + * Expire fragment reassembly buffer * - * @v timer Retry timer - * @v over If asserted, the timer is greater than @c MAX_TIMEOUT + * @v timer Retry timer + * @v fail Failure indicator */ -static void ipv4_frag_expired ( struct retry_timer *timer __unused, - int over ) { - if ( over ) { - DBG ( "Fragment reassembly timeout" ); - /* Free the fragment buffer */ - } +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 ); } /** - * Free fragment buffer + * Find matching fragment reassembly buffer * - * @v fragbug Fragment buffer + * @v iphdr IPv4 header + * @ret frag Fragment reassembly buffer, or NULL */ -static void free_fragbuf ( struct frag_buffer *fragbuf ) { - free ( fragbuf ); +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, fragment of the datagram - * @ret frag_iob Reassembled packet, or NULL + * @v iobuf I/O buffer + * @ret iobuf Reassembled packet, or NULL */ -static struct io_buffer * ipv4_reassemble ( struct io_buffer * iobuf ) { +static struct io_buffer * ipv4_reassemble ( struct io_buffer *iobuf ) { struct iphdr *iphdr = iobuf->data; - struct frag_buffer *fragbuf; - - /** - * Check if the fragment belongs to any fragment series - */ - list_for_each_entry ( fragbuf, &frag_buffers, list ) { - if ( fragbuf->ident == iphdr->ident && - fragbuf->src.s_addr == iphdr->src.s_addr ) { - /** - * Check if the packet is the expected fragment - * - * The offset of the new packet must be equal to the - * length of the data accumulated so far (the length of - * the reassembled I/O buffer - */ - if ( iob_len ( fragbuf->frag_iob ) == - ( iphdr->frags & IP_MASK_OFFSET ) ) { - /** - * Append the contents of the fragment to the - * reassembled I/O buffer - */ - iob_pull ( iobuf, sizeof ( *iphdr ) ); - memcpy ( iob_put ( fragbuf->frag_iob, - iob_len ( iobuf ) ), - iobuf->data, iob_len ( iobuf ) ); - free_iob ( iobuf ); - - /** Check if the fragment series is over */ - if ( ! ( iphdr->frags & IP_MASK_MOREFRAGS ) ) { - iobuf = fragbuf->frag_iob; - free_fragbuf ( fragbuf ); - return iobuf; - } - - } else { - /* Discard the fragment series */ - free_fragbuf ( fragbuf ); - free_iob ( iobuf ); - } - return NULL; - } + 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; } - - /** Check if the fragment is the first in the fragment series */ - if ( iphdr->frags & IP_MASK_MOREFRAGS && - ( ( iphdr->frags & IP_MASK_OFFSET ) == 0 ) ) { - - /** Create a new fragment buffer */ - fragbuf = ( struct frag_buffer* ) malloc ( sizeof( *fragbuf ) ); - fragbuf->ident = iphdr->ident; - fragbuf->src = iphdr->src; - - /* Set up the reassembly I/O buffer */ - fragbuf->frag_iob = alloc_iob ( IP_FRAG_IOB_SIZE ); - iob_pull ( iobuf, sizeof ( *iphdr ) ); - memcpy ( iob_put ( fragbuf->frag_iob, iob_len ( iobuf ) ), + + /* 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; + } + } - /* Set the reassembly timer */ - timer_init ( &fragbuf->frag_timer, ipv4_frag_expired, NULL ); - start_timer_fixed ( &fragbuf->frag_timer, IP_FRAG_TIMEOUT ); + /* (Re)start fragment reassembly timer */ + start_timer_fixed ( &frag->timer, IP_FRAG_TIMEOUT ); - /* Add the fragment buffer to the list of fragment buffers */ - list_add ( &fragbuf->list, &frag_buffers ); - } - + return NULL; + + drop: + free_iob ( iobuf ); return NULL; } @@ -255,33 +281,6 @@ static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) { return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) ); } -/** - * Determine link-layer address - * - * @v dest IPv4 destination address - * @v src IPv4 source address - * @v netdev Network device - * @v ll_dest Link-layer destination address buffer - * @ret rc Return status code - */ -static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src, - struct net_device *netdev, uint8_t *ll_dest ) { - struct ll_protocol *ll_protocol = netdev->ll_protocol; - - if ( dest.s_addr == INADDR_BROADCAST ) { - /* Broadcast address */ - memcpy ( ll_dest, netdev->ll_broadcast, - ll_protocol->ll_addr_len ); - return 0; - } else if ( IN_MULTICAST ( ntohl ( dest.s_addr ) ) ) { - return ll_protocol->mc_hash ( AF_INET, &dest, ll_dest ); - } else { - /* Unicast address: resolve via ARP */ - return arp_resolve ( netdev, &ipv4_protocol, &dest, - &src, ll_dest ); - } -} - /** * Transmit IP packet * @@ -306,7 +305,9 @@ static int ipv4_tx ( struct io_buffer *iobuf, struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest ); struct ipv4_miniroute *miniroute; struct in_addr next_hop; - uint8_t ll_dest[MAX_LL_ADDR_LEN]; + 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 */ @@ -314,7 +315,6 @@ static int ipv4_tx ( struct io_buffer *iobuf, iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) ); iphdr->service = IP_TOS; iphdr->len = htons ( iob_len ( iobuf ) ); - iphdr->ident = htons ( ++next_ident ); iphdr->ttl = IP_TTL; iphdr->protocol = tcpip_protocol->tcpip_proto; iphdr->dest = sin_dest->sin_addr; @@ -327,21 +327,23 @@ static int ipv4_tx ( struct io_buffer *iobuf, ( ! 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 ) { - DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) ); + DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n", + inet_ntoa ( iphdr->dest ) ); rc = -ENETUNREACH; goto err; } - /* Determine link-layer destination address */ - if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev, - ll_dest ) ) != 0 ) { - DBG ( "IPv4 has no link-layer address for %s: %s\n", - inet_ntoa ( next_hop ), strerror ( rc ) ); - 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 ) @@ -349,17 +351,48 @@ static int ipv4_tx ( struct io_buffer *iobuf, iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) ); /* Print IP4 header for debugging */ - DBG ( "IPv4 TX %s->", inet_ntoa ( iphdr->src ) ); - DBG ( "%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 ) ); - - /* Hand off to link layer */ - if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest, - netdev->ll_addr ) ) != 0 ) { - DBG ( "IPv4 could not transmit packet via %s: %s\n", - netdev->name, strerror ( rc ) ); - return rc; + 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; @@ -369,21 +402,60 @@ static int ipv4_tx ( struct io_buffer *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 + */ +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 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 __unused, + struct net_device *netdev, const void *ll_dest __unused, - const void *ll_source __unused ) { + const void *ll_source __unused, + unsigned int flags ) { struct iphdr *iphdr = iobuf->data; size_t hdrlen; size_t len; @@ -397,77 +469,88 @@ static int ipv4_rx ( struct io_buffer *iobuf, /* Sanity check the IPv4 header */ if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) { - DBG ( "IPv4 packet too short at %zd bytes (min %zd bytes)\n", - 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 ) { - DBG ( "IPv4 version %#02x not supported\n", iphdr->verhdrlen ); + DBGC ( iphdr->src, "IPv4 version %#02x not supported\n", + iphdr->verhdrlen ); goto err; } hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 ); if ( hdrlen < sizeof ( *iphdr ) ) { - DBG ( "IPv4 header too short at %zd bytes (min %zd bytes)\n", - 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 ) ) { - DBG ( "IPv4 header too long at %zd bytes " - "(packet is %zd bytes)\n", 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 ) { - DBG ( "IPv4 checksum incorrect (is %04x including checksum " - "field, should be 0000)\n", csum ); + 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 ) { - DBG ( "IPv4 length too short at %zd bytes " - "(header is %zd bytes)\n", 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 ) ) { - DBG ( "IPv4 length too long at %zd bytes " - "(packet is %zd bytes)\n", 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; } - /* Print IPv4 header for debugging */ - DBG ( "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) ); - DBG ( "%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 ) ); - - /* Truncate packet to correct length, calculate pseudo-header - * checksum and then strip off the IPv4 header. - */ + /* Truncate packet to correct length */ iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) ); - pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM ); - iob_pull ( iobuf, hdrlen ); - /* Fragment reassembly */ - if ( ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) ) || - ( ( iphdr->frags & htons ( IP_MASK_OFFSET ) ) != 0 ) ) { - /* Pass the fragment to ipv4_reassemble() which either - * returns a fully reassembled I/O buffer or NULL. + /* 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 and hand off to transport layer */ + /* 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 ) { - DBG ( "IPv4 received packet rejected by stack: %s\n", - strerror ( rc ) ); + DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by " + "stack: %s\n", strerror ( rc ) ); return rc; } @@ -487,15 +570,10 @@ static int ipv4_rx ( struct io_buffer *iobuf, */ static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) { const struct in_addr *address = net_addr; - struct ipv4_miniroute *miniroute; - list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { - if ( ( miniroute->netdev == netdev ) && - ( miniroute->address.s_addr == address->s_addr ) ) { - /* Found matching address */ - return 0; - } - } + if ( ipv4_has_addr ( netdev, *address ) ) + return 0; + return -ENOENT; } diff --git a/roms/ipxe/src/net/ipv6.c b/roms/ipxe/src/net/ipv6.c index 712aa49e5..57bf94d8d 100644 --- a/roms/ipxe/src/net/ipv6.c +++ b/roms/ipxe/src/net/ipv6.c @@ -288,13 +288,15 @@ static int ipv6_process_nxt_hdr ( struct io_buffer *iobuf, uint8_t nxt_hdr, * @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 const void *ll_source, + __unused unsigned int flags ) { struct ip6_header *ip6hdr = iobuf->data; union { diff --git a/roms/ipxe/src/net/mii.c b/roms/ipxe/src/net/mii.c deleted file mode 100644 index dbaecf11c..000000000 --- a/roms/ipxe/src/net/mii.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - - mii.c: MII interface library - - Ported to iPXE by Daniel Verkamp <daniel@drv.nu> - from Linux drivers/net/mii.c - - Maintained by Jeff Garzik <jgarzik@pobox.com> - Copyright 2001,2002 Jeff Garzik - - Various code came from myson803.c and other files by - Donald Becker. Copyright: - - Written 1998-2002 by Donald Becker. - - 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. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - -*/ - -#include <mii.h> - -/** - * mii_link_ok - is link status up/ok - * @mii: the MII interface - * - * Returns 1 if the MII reports link status up/ok, 0 otherwise. - */ -int -mii_link_ok ( struct mii_if_info *mii ) -{ - /* first, a dummy read, needed to latch some MII phys */ - mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR ); - if ( mii->mdio_read ( mii->dev, mii->phy_id, MII_BMSR ) & BMSR_LSTATUS ) - return 1; - return 0; -} - -/** - * mii_check_link - check MII link status - * @mii: MII interface - * - * If the link status changed (previous != current), call - * netif_carrier_on() if current link status is Up or call - * netif_carrier_off() if current link status is Down. - */ -void -mii_check_link ( struct mii_if_info *mii ) -{ - int cur_link = mii_link_ok ( mii ); - int prev_link = netdev_link_ok ( mii->dev ); - - if ( cur_link && !prev_link ) - netdev_link_up ( mii->dev ); - else if (prev_link && !cur_link) - netdev_link_down ( mii->dev ); -} - - -/** - * mii_check_media - check the MII interface for a duplex change - * @mii: the MII interface - * @ok_to_print: OK to print link up/down messages - * @init_media: OK to save duplex mode in @mii - * - * Returns 1 if the duplex mode changed, 0 if not. - * If the media type is forced, always returns 0. - */ -unsigned int -mii_check_media ( struct mii_if_info *mii, - unsigned int ok_to_print, - unsigned int init_media ) -{ - unsigned int old_carrier, new_carrier; - int advertise, lpa, media, duplex; - int lpa2 = 0; - - /* if forced media, go no further */ - if (mii->force_media) - return 0; /* duplex did not change */ - - /* check current and old link status */ - old_carrier = netdev_link_ok ( mii->dev ) ? 1 : 0; - new_carrier = (unsigned int) mii_link_ok ( mii ); - - /* if carrier state did not change, this is a "bounce", - * just exit as everything is already set correctly - */ - if ( ( ! init_media ) && ( old_carrier == new_carrier ) ) - return 0; /* duplex did not change */ - - /* no carrier, nothing much to do */ - if ( ! new_carrier ) { - netdev_link_down ( mii->dev ); - if ( ok_to_print ) - DBG ( "%s: link down\n", mii->dev->name); - return 0; /* duplex did not change */ - } - - /* - * we have carrier, see who's on the other end - */ - netdev_link_up ( mii->dev ); - - /* get MII advertise and LPA values */ - if ( ( ! init_media ) && ( mii->advertising ) ) { - advertise = mii->advertising; - } else { - advertise = mii->mdio_read ( mii->dev, mii->phy_id, MII_ADVERTISE ); - mii->advertising = advertise; - } - lpa = mii->mdio_read ( mii->dev, mii->phy_id, MII_LPA ); - if ( mii->supports_gmii ) - lpa2 = mii->mdio_read ( mii->dev, mii->phy_id, MII_STAT1000 ); - - /* figure out media and duplex from advertise and LPA values */ - media = mii_nway_result ( lpa & advertise ); - duplex = ( media & ADVERTISE_FULL ) ? 1 : 0; - if ( lpa2 & LPA_1000FULL ) - duplex = 1; - - if ( ok_to_print ) - DBG ( "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", - mii->dev->name, - lpa2 & ( LPA_1000FULL | LPA_1000HALF ) ? "1000" : - media & ( ADVERTISE_100FULL | ADVERTISE_100HALF ) ? "100" : "10", - duplex ? "full" : "half", - lpa); - - if ( ( init_media ) || ( mii->full_duplex != duplex ) ) { - mii->full_duplex = duplex; - return 1; /* duplex changed */ - } - - return 0; /* duplex did not change */ -} diff --git a/roms/ipxe/src/net/netdev_settings.c b/roms/ipxe/src/net/netdev_settings.c index 2ef3984d9..9efe6811c 100644 --- a/roms/ipxe/src/net/netdev_settings.c +++ b/roms/ipxe/src/net/netdev_settings.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/netdevice.c b/roms/ipxe/src/net/netdevice.c index 9b0ea199a..ec3456a93 100644 --- a/roms/ipxe/src/net/netdevice.c +++ b/roms/ipxe/src/net/netdevice.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -62,6 +63,23 @@ struct errortab netdev_errors[] __errortab = { __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 * @@ -163,8 +181,8 @@ static void netdev_record_stat ( struct net_device_stats *stats, int rc ) { int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { int rc; - DBGC ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n", - netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) ); + 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 ); @@ -194,34 +212,50 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { } /** - * Complete network transmission + * Discard transmitted packet * * @v netdev Network device - * @v iobuf I/O buffer + * @v iobuf I/O buffer, or NULL * @v rc Packet status code * - * The packet must currently be in the network device's TX queue. + * The packet is discarded and a TX error is recorded. This function + * takes ownership of the I/O buffer. */ -void netdev_tx_complete_err ( struct net_device *netdev, - struct io_buffer *iobuf, int rc ) { +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 ) { - DBGC ( netdev, "NETDEV %s transmission %p complete\n", - netdev->name, iobuf ); + 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 */ - assert ( iobuf->list.next != NULL ); - assert ( iobuf->list.prev != NULL ); + list_check_contains_entry ( iobuf, &netdev->tx_queue, list ); /* Dequeue and free I/O buffer */ list_del ( &iobuf->list ); - free_iob ( iobuf ); + netdev_tx_err ( netdev, iobuf, rc ); } /** @@ -265,8 +299,8 @@ static void netdev_tx_flush ( struct net_device *netdev ) { */ void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) { - DBGC ( netdev, "NETDEV %s received %p (%p+%zx)\n", - netdev->name, iobuf, iobuf->data, iob_len ( 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 ) && @@ -416,8 +450,11 @@ int register_netdev ( struct net_device *netdev ) { ifindex++ ); } - /* Set initial link-layer address */ - netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); + /* 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 ); @@ -449,6 +486,7 @@ int register_netdev ( struct net_device *netdev ) { err_probe: for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) driver->remove ( netdev ); + clear_settings ( netdev_settings ( netdev ) ); unregister_settings ( netdev_settings ( netdev ) ); err_register_settings: return rc; @@ -533,6 +571,7 @@ void unregister_netdev ( struct net_device *netdev ) { driver->remove ( netdev ); /* Unregister per-netdev configuration settings */ + clear_settings ( netdev_settings ( netdev ) ); unregister_settings ( netdev_settings ( netdev ) ); /* Remove from device list */ @@ -635,17 +674,11 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, 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 ) { - free_iob ( iobuf ); + /* Record error for diagnosis */ + netdev_tx_err ( netdev, iobuf, rc ); return rc; } @@ -661,17 +694,19 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, * @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 ) { + 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 ); + ll_source, flags ); } DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n", @@ -693,6 +728,7 @@ void net_poll ( void ) { const void *ll_dest; const void *ll_source; uint16_t net_proto; + unsigned int flags; int rc; /* Poll and process each network device */ @@ -710,23 +746,19 @@ void net_poll ( void ) { 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 ) ) ) { + /* Process all received packets */ + while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) { - DBGC ( netdev, "NETDEV %s processing %p (%p+%zx)\n", - netdev->name, iobuf, iobuf->data, - iob_len ( iobuf ) ); + 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 ) ) != 0 ) { + &net_proto, + &flags ) ) != 0 ) { free_iob ( iobuf ); continue; } @@ -734,7 +766,7 @@ void net_poll ( void ) { /* Hand packet to network layer */ if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev, net_proto, ll_dest, - ll_source ) ) != 0 ) { + ll_source, flags ) ) != 0 ) { /* Record error for diagnosis */ netdev_rx_err ( netdev, NULL, rc ); } @@ -752,7 +784,4 @@ static void net_step ( struct process *process __unused ) { } /** Networking stack process */ -struct process net_process __permanent_process = { - .list = LIST_HEAD_INIT ( net_process.list ), - .step = net_step, -}; +PERMANENT_PROCESS ( net_process, net_step ); diff --git a/roms/ipxe/src/net/nullnet.c b/roms/ipxe/src/net/nullnet.c index 48849dfd6..4ac50f64b 100644 --- a/roms/ipxe/src/net/nullnet.c +++ b/roms/ipxe/src/net/nullnet.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/rarp.c b/roms/ipxe/src/net/rarp.c index da67c459d..371145015 100644 --- a/roms/ipxe/src/net/rarp.c +++ b/roms/ipxe/src/net/rarp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -38,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @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. @@ -45,7 +47,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); static int rarp_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused, const void *ll_dest __unused, - const void *ll_source __unused ) { + const void *ll_source __unused, + unsigned int flags __unused ) { free_iob ( iobuf ); return 0; } diff --git a/roms/ipxe/src/net/retry.c b/roms/ipxe/src/net/retry.c index 082be39bb..8f210bdcc 100644 --- a/roms/ipxe/src/net/retry.c +++ b/roms/ipxe/src/net/retry.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -148,6 +149,7 @@ void stop_timer ( struct retry_timer *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 */ @@ -169,16 +171,16 @@ static void timer_expired ( struct retry_timer *timer ) { /* Call expiry callback */ timer->expired ( timer, fail ); + /* If refcnt is NULL, then timer may already have been freed */ - ref_put ( timer->refcnt ); + ref_put ( refcnt ); } /** - * Single-step the retry timer list + * Poll the retry timer list * - * @v process Retry timer process */ -static void retry_step ( struct process *process __unused ) { +void retry_poll ( void ) { struct retry_timer *timer; unsigned long now = currticks(); unsigned long used; @@ -197,8 +199,14 @@ static void retry_step ( struct process *process __unused ) { } } +/** + * Single-step the retry timer list + * + * @v process Retry timer process + */ +static void retry_step ( struct process *process __unused ) { + retry_poll(); +} + /** Retry timer process */ -struct process retry_process __permanent_process = { - .list = LIST_HEAD_INIT ( retry_process.list ), - .step = retry_step, -}; +PERMANENT_PROCESS ( retry_process, retry_step ); diff --git a/roms/ipxe/src/net/tcp.c b/roms/ipxe/src/net/tcp.c index fbcf279e1..938edd577 100644 --- a/roms/ipxe/src/net/tcp.c +++ b/roms/ipxe/src/net/tcp.c @@ -7,8 +7,10 @@ #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/pending.h> #include <ipxe/xfer.h> #include <ipxe/open.h> #include <ipxe/uri.h> @@ -85,6 +87,18 @@ struct tcp_connection { * Equivalent to TS.Recent in RFC 1323 terminology. */ uint32_t ts_recent; + /** Send window scale + * + * Equivalent to Snd.Wind.Scale in RFC 1323 terminology + */ + uint8_t snd_win_scale; + /** Receive window scale + * + * Equivalent to Rcv.Wind.Scale in RFC 1323 terminology + */ + uint8_t rcv_win_scale; + /** Maximum receive window */ + uint32_t max_rcv_win; /** Transmit queue */ struct list_head tx_queue; @@ -94,6 +108,11 @@ struct tcp_connection { struct retry_timer timer; /** Shutdown (TIME_WAIT) timer */ struct retry_timer wait; + + /** Pending operations for SYN and FIN */ + struct pending_operation pending_flags; + /** Pending operations for transmit queue */ + struct pending_operation pending_data; }; /** TCP flags */ @@ -278,6 +297,7 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer, tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN ); tcp_dump_state ( tcp ); tcp->snd_seq = random(); + tcp->max_rcv_win = TCP_MAX_WINDOW_SIZE; INIT_LIST_HEAD ( &tcp->tx_queue ); INIT_LIST_HEAD ( &tcp->rx_queue ); memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) ); @@ -290,6 +310,9 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer, /* Start timer to initiate SYN */ start_timer_nodelay ( &tcp->timer ); + /* Add a pending operation for the SYN */ + pending_get ( &tcp->pending_flags ); + /* Attach parent interface, transfer reference to connection * list and return */ @@ -339,10 +362,17 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) { list_del ( &iobuf->list ); free_iob ( iobuf ); + pending_put ( &tcp->pending_data ); } + assert ( ! is_pending ( &tcp->pending_data ) ); + + /* Remove pending operations for SYN and FIN, if applicable */ + pending_put ( &tcp->pending_flags ); + pending_put ( &tcp->pending_flags ); /* 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 ); @@ -357,9 +387,14 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { 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 ) ) { + if ( list_empty ( &tcp->tx_queue ) && + ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) { + tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN ); tcp_dump_state ( tcp ); + + /* Add a pending operation for the FIN */ + pending_get ( &tcp->pending_flags ); } } @@ -391,6 +426,25 @@ static size_t tcp_xmit_win ( struct tcp_connection *tcp ) { 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 * @@ -425,6 +479,7 @@ static size_t tcp_process_tx_queue ( struct tcp_connection *tcp, size_t max_len, if ( ! iob_len ( iobuf ) ) { list_del ( &iobuf->list ); free_iob ( iobuf ); + pending_put ( &tcp->pending_data ); } } len += frag_len; @@ -448,6 +503,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { struct io_buffer *iobuf; struct tcp_header *tcphdr; struct tcp_mss_option *mssopt; + struct tcp_window_scale_padded_option *wsopt; struct tcp_timestamp_padded_option *tsopt; void *payload; unsigned int flags; @@ -455,6 +511,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { uint32_t seq_len; uint32_t app_win; uint32_t max_rcv_win; + uint32_t max_representable_win; int rc; /* If retransmission timer is already running, do nothing */ @@ -490,25 +547,26 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { start_timer ( &tcp->timer ); /* Allocate I/O buffer */ - iobuf = alloc_iob ( len + MAX_LL_NET_HEADER_LEN ); + 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, MAX_LL_NET_HEADER_LEN ); + 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; + max_rcv_win = tcp->max_rcv_win; app_win = xfer_window ( &tcp->xfer ); if ( max_rcv_win > app_win ) max_rcv_win = app_win; + max_representable_win = ( 0xffff << tcp->rcv_win_scale ); + if ( max_rcv_win > max_representable_win ) + max_rcv_win = max_representable_win; max_rcv_win &= ~0x03; /* Keep everything dword-aligned */ if ( tcp->rcv_win < max_rcv_win ) tcp->rcv_win = max_rcv_win; @@ -520,6 +578,11 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { mssopt->kind = TCP_OPTION_MSS; mssopt->length = sizeof ( *mssopt ); mssopt->mss = htons ( TCP_MSS ); + wsopt = iob_push ( iobuf, sizeof ( *wsopt ) ); + wsopt->nop = TCP_OPTION_NOP; + wsopt->wsopt.kind = TCP_OPTION_WS; + wsopt->wsopt.length = sizeof ( wsopt->wsopt ); + wsopt->wsopt.scale = TCP_RX_WINDOW_SCALE; } if ( ( flags & TCP_SYN ) || ( tcp->flags & TCP_TS_ENABLED ) ) { tsopt = iob_push ( iobuf, sizeof ( *tsopt ) ); @@ -539,7 +602,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { tcphdr->ack = htonl ( tcp->rcv_ack ); tcphdr->hlen = ( ( payload - iobuf->data ) << 2 ); tcphdr->flags = flags; - tcphdr->win = htons ( tcp->rcv_win ); + tcphdr->win = htons ( tcp->rcv_win >> tcp->rcv_win_scale ); tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) ); /* Dump header */ @@ -634,14 +697,14 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp, int rc; /* Allocate space for dataless TX buffer */ - iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN ); + 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, MAX_LL_NET_HEADER_LEN ); + iob_reserve ( iobuf, TCP_MAX_HEADER_LEN ); /* Construct RST response */ tcphdr = iob_push ( iobuf, sizeof ( *tcphdr ) ); @@ -652,7 +715,7 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp, 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->win = htons ( 0 ); tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) ); /* Dump header */ @@ -727,6 +790,9 @@ static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data, case TCP_OPTION_MSS: options->mssopt = data; break; + case TCP_OPTION_WS: + options->wsopt = data; + break; case TCP_OPTION_TS: options->tsopt = data; break; @@ -783,6 +849,10 @@ static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq, tcp->rcv_ack = seq; if ( options->tsopt ) tcp->flags |= TCP_TS_ENABLED; + if ( options->wsopt ) { + tcp->snd_win_scale = options->wsopt->scale; + tcp->rcv_win_scale = TCP_RX_WINDOW_SCALE; + } } /* Ignore duplicate SYN */ @@ -848,8 +918,10 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, len = ack_len; acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) & ( TCP_SYN | TCP_FIN ) ); - if ( acked_flags ) + if ( acked_flags ) { len--; + pending_put ( &tcp->pending_flags ); + } /* Update SEQ and sent counters, and window size */ tcp->snd_seq = ack; @@ -864,8 +936,12 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, 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 ) ) + if ( list_empty ( &tcp->tx_queue ) && + ( tcp->flags & TCP_XFER_CLOSED ) && + ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) { tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN ); + pending_get ( &tcp->pending_flags ); + } return 0; } @@ -1080,10 +1156,12 @@ static int tcp_rx ( struct io_buffer *iobuf, uint16_t csum; uint32_t seq; uint32_t ack; + uint16_t raw_win; uint32_t win; unsigned int flags; size_t len; uint32_t seq_len; + size_t old_xfer_window; int rc; /* Sanity check packet */ @@ -1119,11 +1197,11 @@ static int tcp_rx ( struct io_buffer *iobuf, tcp = tcp_demux ( ntohs ( tcphdr->dest ) ); seq = ntohl ( tcphdr->seq ); ack = ntohl ( tcphdr->ack ); - win = ntohs ( tcphdr->win ); + raw_win = ntohs ( tcphdr->win ); flags = tcphdr->flags; tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ), ( hlen - sizeof ( *tcphdr ) ), &options ); - if ( options.tsopt ) + if ( tcp && options.tsopt ) tcp->ts_val = ntohl ( options.tsopt->tsval ); iob_pull ( iobuf, hlen ); len = iob_len ( iobuf ); @@ -1145,8 +1223,12 @@ static int tcp_rx ( struct io_buffer *iobuf, goto discard; } + /* Record old data-transfer window */ + old_xfer_window = tcp_xfer_window ( tcp ); + /* Handle ACK, if present */ if ( flags & TCP_ACK ) { + win = ( raw_win << tcp->snd_win_scale ); if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) { tcp_xmit_reset ( tcp, st_src, tcphdr ); goto discard; @@ -1191,6 +1273,10 @@ static int tcp_rx ( struct io_buffer *iobuf, 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: @@ -1214,13 +1300,29 @@ struct tcpip_protocol tcp_protocol __tcpip_protocol = { static unsigned int tcp_discard ( void ) { struct tcp_connection *tcp; struct io_buffer *iobuf; + struct tcp_rx_queued_header *tcpqhdr; + uint32_t max_win; 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 ) { + + /* Limit window to prevent future discards */ + tcpqhdr = iobuf->data; + max_win = ( tcpqhdr->seq - tcp->rcv_ack ); + if ( max_win < tcp->max_rcv_win ) { + DBGC ( tcp, "TCP %p reducing maximum window " + "from %d to %d\n", + tcp, tcp->max_rcv_win, max_win ); + tcp->max_rcv_win = max_win; + } + + /* Remove packet from queue */ list_del ( &iobuf->list ); free_iob ( iobuf ); + + /* Report discard */ discarded++; break; } @@ -1230,10 +1332,30 @@ static unsigned int tcp_discard ( void ) { } /** TCP cache discarder */ -struct cache_discarder tcp_cache_discarder __cache_discarder = { +struct cache_discarder tcp_discarder __cache_discarder ( CACHE_NORMAL ) = { .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 @@ -1256,25 +1378,6 @@ static void tcp_xfer_close ( struct tcp_connection *tcp, int rc ) { tcp_xmit ( tcp ); } -/** - * Check 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 ); -} - /** * Deliver datagram as I/O buffer * @@ -1290,6 +1393,9 @@ static int tcp_xfer_deliver ( struct tcp_connection *tcp, /* Enqueue packet */ list_add_tail ( &iobuf->list, &tcp->tx_queue ); + /* Each enqueued packet is a pending operation */ + pending_get ( &tcp->pending_data ); + /* Transmit data, if possible */ tcp_xmit ( tcp ); diff --git a/roms/ipxe/src/net/tcp/ftp.c b/roms/ipxe/src/net/tcp/ftp.c index 957f05cc8..9f93fb66f 100644 --- a/roms/ipxe/src/net/tcp/ftp.c +++ b/roms/ipxe/src/net/tcp/ftp.c @@ -1,3 +1,22 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + #include <stdint.h> #include <stdlib.h> #include <stdio.h> @@ -34,6 +53,7 @@ enum ftp_state { FTP_USER, FTP_PASS, FTP_TYPE, + FTP_SIZE, FTP_PASV, FTP_RETR, FTP_WAIT, @@ -68,6 +88,8 @@ struct ftp_request { char status_text[5]; /** Passive-mode parameters, as text */ char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */ + /** File size, as text */ + char filesize[20]; }; /** @@ -157,6 +179,7 @@ static struct ftp_control_string ftp_strings[] = { [FTP_USER] = { "USER ", ftp_user }, [FTP_PASS] = { "PASS ", ftp_password }, [FTP_TYPE] = { "TYPE I", NULL }, + [FTP_SIZE] = { "SIZE ", ftp_uri_path }, [FTP_PASV] = { "PASV", NULL }, [FTP_RETR] = { "RETR ", ftp_uri_path }, [FTP_WAIT] = { NULL, NULL }, @@ -234,6 +257,14 @@ static void ftp_reply ( struct ftp_request *ftp ) { if ( status_major == '1' ) return; + /* If the SIZE command is not supported by the server, we go to + * the next step. + */ + if ( ( status_major == '5' ) && ( ftp->state == FTP_SIZE ) ) { + ftp_next_state ( ftp ); + 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. @@ -245,6 +276,26 @@ static void ftp_reply ( struct ftp_request *ftp ) { return; } + /* Parse file size */ + if ( ftp->state == FTP_SIZE ) { + size_t filesize; + char *endptr; + + /* Parse size */ + filesize = strtoul ( ftp->filesize, &endptr, 10 ); + if ( *endptr != '\0' ) { + DBGC ( ftp, "FTP %p invalid SIZE \"%s\"\n", + ftp, ftp->filesize ); + ftp_done ( ftp, -EPROTO ); + return; + } + + /* Use seek() to notify recipient of filesize */ + DBGC ( ftp, "FTP %p file size is %zd bytes\n", ftp, filesize ); + xfer_seek ( &ftp->xfer, filesize ); + xfer_seek ( &ftp->xfer, 0 ); + } + /* Open passive connection when we get "PASV" response */ if ( ftp->state == FTP_PASV ) { char *ptr = ftp->passive_text; @@ -295,35 +346,33 @@ static int ftp_control_deliver ( struct ftp_request *ftp, while ( len-- ) { c = *(data++); - switch ( c ) { - case '\r' : - case '\n' : + if ( ( c == '\r' ) || ( c == '\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 ) + if ( recvbuf != ftp->status_text ) ftp_reply ( ftp ); /* Start filling up the status code buffer */ recvbuf = ftp->status_text; recvsize = sizeof ( ftp->status_text ) - 1; - break; - case '(' : + } else if ( ( ftp->state == FTP_PASV ) && ( c == '(' ) ) { /* Start filling up the passive parameter buffer */ recvbuf = ftp->passive_text; recvsize = sizeof ( ftp->passive_text ) - 1; - break; - case ')' : + } else if ( ( ftp->state == FTP_PASV ) && ( c == ')' ) ) { /* Stop filling the passive parameter buffer */ recvsize = 0; - break; - default : + } else if ( ( ftp->state == FTP_SIZE ) && ( c == ' ' ) ) { + /* Start filling up the file size buffer */ + recvbuf = ftp->filesize; + recvsize = sizeof ( ftp->filesize ) - 1; + } else { /* Fill up buffer if applicable */ if ( recvsize > 0 ) { *(recvbuf++) = c; recvsize--; } - break; } } @@ -378,37 +427,15 @@ static void ftp_data_closed ( struct ftp_request *ftp, int rc ) { } } -/** - * Handle data delivery via FTP data channel - * - * @v ftp FTP request - * @v iobuf I/O buffer - * @v meta Data transfer metadata - * @ret rc Return status code - */ -static int ftp_data_deliver ( struct ftp_request *ftp, - struct io_buffer *iobuf, - struct xfer_metadata *meta __unused ) { - int rc; - - if ( ( rc = xfer_deliver_iob ( &ftp->xfer, iobuf ) ) != 0 ) { - DBGC ( ftp, "FTP %p failed to deliver data: %s\n", - ftp, strerror ( rc ) ); - return rc; - } - - return 0; -} - /** FTP data channel interface operations */ static struct interface_operation ftp_data_operations[] = { - INTF_OP ( xfer_deliver, struct ftp_request *, ftp_data_deliver ), INTF_OP ( intf_close, struct ftp_request *, ftp_data_closed ), }; /** FTP data channel interface descriptor */ static struct interface_descriptor ftp_data_desc = - INTF_DESC ( struct ftp_request, data, ftp_data_operations ); + INTF_DESC_PASSTHRU ( struct ftp_request, data, ftp_data_operations, + xfer ); /***************************************************************************** * @@ -423,7 +450,8 @@ static struct interface_operation ftp_xfer_operations[] = { /** FTP data transfer interface descriptor */ static struct interface_descriptor ftp_xfer_desc = - INTF_DESC ( struct ftp_request, xfer, ftp_xfer_operations ); + INTF_DESC_PASSTHRU ( struct ftp_request, xfer, ftp_xfer_operations, + data ); /***************************************************************************** * diff --git a/roms/ipxe/src/net/tcp/http.c b/roms/ipxe/src/net/tcp/http.c index 20f14e680..90bae9d7a 100644 --- a/roms/ipxe/src/net/tcp/http.c +++ b/roms/ipxe/src/net/tcp/http.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -25,525 +26,13 @@ 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/uri.h> -#include <ipxe/refcnt.h> -#include <ipxe/iobuf.h> -#include <ipxe/xfer.h> +#include <stddef.h> #include <ipxe/open.h> -#include <ipxe/socket.h> -#include <ipxe/tcpip.h> -#include <ipxe/process.h> -#include <ipxe/linebuf.h> -#include <ipxe/features.h> -#include <ipxe/base64.h> #include <ipxe/http.h> +#include <ipxe/features.h> FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 ); -/** HTTP receive state */ -enum http_rx_state { - HTTP_RX_RESPONSE = 0, - HTTP_RX_HEADER, - HTTP_RX_DATA, - HTTP_RX_DEAD, -}; - -/** - * An HTTP request - * - */ -struct http_request { - /** Reference count */ - struct refcnt refcnt; - /** Data transfer interface */ - struct interface xfer; - - /** URI being fetched */ - struct uri *uri; - /** Transport layer interface */ - struct interface socket; - - /** TX process */ - struct process process; - - /** HTTP response code */ - unsigned int response; - /** HTTP Content-Length */ - size_t content_length; - /** Received length */ - size_t rx_len; - /** RX state */ - enum http_rx_state rx_state; - /** Line buffer for received header lines */ - struct line_buffer linebuf; -}; - -/** - * 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 ); -}; - -/** - * Mark HTTP request as complete - * - * @v http HTTP request - * @v rc Return status code - */ -static void http_done ( 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->content_length && - ( http->content_length != http->rx_len ) ) { - DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n", - http, http->rx_len, http->content_length ); - rc = -EIO; - } - - /* Remove process */ - process_del ( &http->process ); - - /* Close all data transfer interfaces */ - intf_shutdown ( &http->socket, rc ); - intf_shutdown ( &http->xfer, rc ); -} - -/** - * 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 301: - case 302: - return 0; - case 404: - return -ENOENT; - case 403: - return -EPERM; - case 401: - return -EACCES; - default: - return -EIO; - } -} - -/** - * 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; - int rc; - - DBGC ( http, "HTTP %p response \"%s\"\n", http, response ); - - /* Check response starts with "HTTP/" */ - if ( strncmp ( response, "HTTP/", 5 ) != 0 ) - return -EIO; - - /* Locate and check response code */ - spc = strchr ( response, ' ' ); - if ( ! spc ) - return -EIO; - http->response = strtoul ( spc, NULL, 10 ); - if ( ( rc = http_response_to_rc ( http->response ) ) != 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 ) { - char *endp; - - http->content_length = strtoul ( value, &endp, 10 ); - if ( *endp != '\0' ) { - DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n", - http, value ); - return -EIO; - } - - /* Use seek() to notify recipient of filesize */ - xfer_seek ( &http->xfer, http->content_length ); - xfer_seek ( &http->xfer, 0 ); - - 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, - }, - { 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 transition to the data phase */ - if ( ! header[0] ) { - DBGC ( http, "HTTP %p start of data\n", http ); - empty_line_buffer ( &http->linebuf ); - http->rx_state = HTTP_RX_DATA; - 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 -EIO; - } - *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; -} - -/** 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 }, -}; - -/** - * Handle new data arriving via HTTP connection in the data phase - * - * @v http HTTP request - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int http_rx_data ( struct http_request *http, - struct io_buffer *iobuf ) { - int rc; - - /* Update received length */ - http->rx_len += iob_len ( iobuf ); - - /* Hand off data buffer */ - if ( ( rc = xfer_deliver_iob ( &http->xfer, iobuf ) ) != 0 ) - return rc; - - /* If we have reached the content-length, stop now */ - if ( http->content_length && - ( http->rx_len >= http->content_length ) ) { - http_done ( http, 0 ); - } - - return 0; -} - -/** - * 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; - ssize_t len; - int rc = 0; - - while ( iob_len ( iobuf ) ) { - switch ( http->rx_state ) { - case HTTP_RX_DEAD: - /* Do no further processing */ - goto done; - case HTTP_RX_DATA: - /* Once we're into the data phase, just fill - * the data buffer - */ - rc = http_rx_data ( http, iob_disown ( iobuf ) ); - goto done; - case HTTP_RX_RESPONSE: - case HTTP_RX_HEADER: - /* In the other phases, buffer and process a - * line at a time - */ - len = line_buffer ( &http->linebuf, iobuf->data, - iob_len ( iobuf ) ); - if ( len < 0 ) { - rc = len; - DBGC ( http, "HTTP %p could not buffer line: " - "%s\n", http, strerror ( rc ) ); - goto done; - } - iob_pull ( iobuf, 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_done ( http, rc ); - free_iob ( iobuf ); - return rc; -} - -/** - * HTTP process - * - * @v process Process - */ -static void http_step ( struct process *process ) { - struct http_request *http = - container_of ( process, struct http_request, process ); - 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 ); - uint8_t user_pw[ user_pw_len + 1 /* NUL */ ]; - char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; - int rc; - int request_len = unparse_uri ( NULL, 0, http->uri, - URI_PATH_BIT | URI_QUERY_BIT ); - - if ( xfer_window ( &http->socket ) ) { - char request[request_len + 1]; - - /* Construct path?query request */ - unparse_uri ( request, sizeof ( request ), http->uri, - URI_PATH_BIT | URI_QUERY_BIT ); - - /* We want to execute only once */ - process_del ( &http->process ); - - /* Construct authorisation, if applicable */ - if ( user ) { - /* Make "user:password" string from decoded fields */ - snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ), - "%s:%s", user, password ); - - /* Base64-encode the "user:password" string */ - base64_encode ( user_pw, user_pw_len, user_pw_base64 ); - } - - /* Send GET request */ - if ( ( rc = xfer_printf ( &http->socket, - "GET %s%s HTTP/1.0\r\n" - "User-Agent: iPXE/" VERSION "\r\n" - "%s%s%s" - "Host: %s\r\n" - "\r\n", - http->uri->path ? "" : "/", - request, - ( user ? - "Authorization: Basic " : "" ), - ( user ? user_pw_base64 : "" ), - ( user ? "\r\n" : "" ), - host ) ) != 0 ) { - http_done ( http, rc ); - } - } -} - -/** HTTP socket interface operations */ -static struct interface_operation http_socket_operations[] = { - INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ), - INTF_OP ( intf_close, struct http_request *, http_done ), -}; - -/** HTTP socket interface descriptor */ -static struct interface_descriptor http_socket_desc = - INTF_DESC_PASSTHRU ( struct http_request, socket, - http_socket_operations, xfer ); - -/** HTTP data transfer interface operations */ -static struct interface_operation http_xfer_operations[] = { - INTF_OP ( intf_close, struct http_request *, http_done ), -}; - -/** HTTP data transfer interface descriptor */ -static struct interface_descriptor http_xfer_desc = - INTF_DESC_PASSTHRU ( struct http_request, xfer, - http_xfer_operations, socket ); - -/** - * 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, - 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 ); - http->uri = uri_get ( uri ); - intf_init ( &http->socket, &http_socket_desc, &http->refcnt ); - process_init ( &http->process, http_step, &http->refcnt ); - - /* 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, &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_done ( http, rc ); - ref_put ( &http->refcnt ); - return rc; -} - /** * Initiate an HTTP connection * diff --git a/roms/ipxe/src/net/tcp/httpcore.c b/roms/ipxe/src/net/tcp/httpcore.c new file mode 100644 index 000000000..bccb35f5f --- /dev/null +++ b/roms/ipxe/src/net/tcp/httpcore.c @@ -0,0 +1,1363 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/base16.h> +#include <ipxe/md5.h> +#include <ipxe/blockdev.h> +#include <ipxe/acpi.h> +#include <ipxe/version.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, + /** Client would like to keep connection alive */ + HTTP_CLIENT_KEEPALIVE = 0x0004, + /** Server will keep connection alive */ + HTTP_SERVER_KEEPALIVE = 0x0008, + /** Discard the current request and try again */ + HTTP_TRY_AGAIN = 0x0010, + /** Provide Basic authentication details */ + HTTP_BASIC_AUTH = 0x0020, + /** Provide Digest authentication details */ + HTTP_DIGEST_AUTH = 0x0040, +}; + +/** HTTP receive state */ +enum http_rx_state { + HTTP_RX_RESPONSE = 0, + HTTP_RX_HEADER, + HTTP_RX_CHUNK_LEN, + /* In HTTP_RX_DATA, it is acceptable for the server to close + * the connection (unless we are in the middle of a chunked + * transfer). + */ + HTTP_RX_DATA, + /* In the following states, it is acceptable for the server to + * close the connection. + */ + 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; + /** Default port */ + unsigned int default_port; + /** Filter (if any) */ + int ( * filter ) ( struct interface *xfer, + const char *name, + struct interface **next ); + /** 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; + /** Response code */ + unsigned int code; + /** 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; + + /** Authentication realm (if any) */ + char *auth_realm; + /** Authentication nonce (if any) */ + char *auth_nonce; + /** Authentication opaque string (if any) */ + char *auth_opaque; +}; + +/** + * 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->auth_realm ); + free ( http->auth_nonce ); + free ( http->auth_opaque ); + 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; + + /* Prevent reconnection */ + http->flags &= ~HTTP_CLIENT_KEEPALIVE; + + /* 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 ); +} + +/** + * Open HTTP socket + * + * @v http HTTP request + * @ret rc Return status code + */ +static int http_socket_open ( struct http_request *http ) { + struct uri *uri = http->uri; + struct sockaddr_tcpip server; + struct interface *socket; + int rc; + + /* Open socket */ + memset ( &server, 0, sizeof ( server ) ); + server.st_port = htons ( uri_port ( uri, http->default_port ) ); + socket = &http->socket; + if ( http->filter ) { + if ( ( rc = http->filter ( socket, uri->host, &socket ) ) != 0 ) + return rc; + } + if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, + ( struct sockaddr * ) &server, + uri->host, NULL ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Mark HTTP request as completed successfully + * + * @v http HTTP request + */ +static void http_done ( struct http_request *http ) { + int rc; + + /* If we are not at an appropriate stage of the protocol + * (including being in the middle of a chunked transfer), + * force an error. + */ + if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) { + DBGC ( http, "HTTP %p connection closed unexpectedly in state " + "%d\n", http, http->rx_state ); + http_close ( http, -ECONNRESET ); + return; + } + + /* If we had a Content-Length, and the received content length + * isn't correct, force 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 ) ); + 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 */ + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) + intf_restart ( &http->partial, 0 ); + + /* Close everything unless we want to keep the connection alive */ + if ( ! ( http->flags & ( HTTP_CLIENT_KEEPALIVE | HTTP_TRY_AGAIN ) ) ) { + http_close ( http, 0 ); + return; + } + + /* If the server is not intending to keep the connection + * alive, then reopen the socket. + */ + if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) { + DBGC ( http, "HTTP %p reopening connection\n", http ); + intf_restart ( &http->socket, 0 ); + if ( ( rc = http_socket_open ( http ) ) != 0 ) { + http_close ( http, rc ); + return; + } + } + http->flags &= ~HTTP_SERVER_KEEPALIVE; + + /* Retry the request if applicable */ + if ( http->flags & HTTP_TRY_AGAIN ) { + http->flags &= ~HTTP_TRY_AGAIN; + http->flags |= HTTP_TX_PENDING; + http->rx_state = HTTP_RX_RESPONSE; + process_add ( &http->process ); + } +} + +/** + * 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; + + 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 store response code */ + spc = strchr ( response, ' ' ); + if ( ! spc ) + return -EINVAL_RESPONSE; + http->code = strtoul ( spc, NULL, 10 ); + + /* Move to receive headers */ + http->rx_state = ( ( http->flags & HTTP_HEAD_ONLY ) ? + HTTP_RX_TRAILER : 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, 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, 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; + + /* Do nothing more if we are retrying the request */ + if ( http->flags & HTTP_TRY_AGAIN ) + return 0; + + /* 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, char *value ){ + + if ( strcasecmp ( value, "chunked" ) == 0 ) { + /* Mark connection as using chunked transfer encoding */ + http->chunked = 1; + } + + return 0; +} + +/** + * Handle HTTP Connection header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_connection ( struct http_request *http, char *value ) { + + if ( strcasecmp ( value, "keep-alive" ) == 0 ) { + /* Mark connection as being kept alive by the server */ + http->flags |= HTTP_SERVER_KEEPALIVE; + } + + return 0; +} + +/** + * Handle WWW-Authenticate Basic header + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ +static int http_rx_basic_auth ( struct http_request *http, char *params ) { + + DBGC ( http, "HTTP %p Basic authentication required (%s)\n", + http, params ); + + /* If we received a 401 Unauthorized response, then retry + * using Basic authentication + */ + if ( ( http->code == 401 ) && + ( ! ( http->flags & HTTP_BASIC_AUTH ) ) && + ( http->uri->user != NULL ) ) { + http->flags |= ( HTTP_TRY_AGAIN | HTTP_BASIC_AUTH ); + } + + return 0; +} + +/** + * Parse Digest authentication parameter + * + * @v params Parameters + * @v name Parameter name (including trailing "=\"") + * @ret value Parameter value, or NULL + */ +static char * http_digest_param ( char *params, const char *name ) { + char *key; + char *value; + char *terminator; + + /* Locate parameter */ + key = strstr ( params, name ); + if ( ! key ) + return NULL; + + /* Extract value */ + value = ( key + strlen ( name ) ); + terminator = strchr ( value, '"' ); + if ( ! terminator ) + return NULL; + return strndup ( value, ( terminator - value ) ); +} + +/** + * Handle WWW-Authenticate Digest header + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ +static int http_rx_digest_auth ( struct http_request *http, char *params ) { + + DBGC ( http, "HTTP %p Digest authentication required (%s)\n", + http, params ); + + /* If we received a 401 Unauthorized response, then retry + * using Digest authentication + */ + if ( ( http->code == 401 ) && + ( ! ( http->flags & HTTP_DIGEST_AUTH ) ) && + ( http->uri->user != NULL ) ) { + + /* Extract realm */ + free ( http->auth_realm ); + http->auth_realm = http_digest_param ( params, "realm=\"" ); + if ( ! http->auth_realm ) { + DBGC ( http, "HTTP %p Digest prompt missing realm\n", + http ); + return -EINVAL_HEADER; + } + + /* Extract nonce */ + free ( http->auth_nonce ); + http->auth_nonce = http_digest_param ( params, "nonce=\"" ); + if ( ! http->auth_nonce ) { + DBGC ( http, "HTTP %p Digest prompt missing nonce\n", + http ); + return -EINVAL_HEADER; + } + + /* Extract opaque */ + free ( http->auth_opaque ); + http->auth_opaque = http_digest_param ( params, "opaque=\"" ); + if ( ! http->auth_opaque ) { + /* Not an error; "opaque" is optional */ + } + + http->flags |= ( HTTP_TRY_AGAIN | HTTP_DIGEST_AUTH ); + } + + return 0; +} + +/** An HTTP WWW-Authenticate header handler */ +struct http_auth_header_handler { + /** Scheme (e.g. "Basic") */ + const char *scheme; + /** Handle received parameters + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ + int ( * rx ) ( struct http_request *http, char *params ); +}; + +/** List of HTTP WWW-Authenticate header handlers */ +static struct http_auth_header_handler http_auth_header_handlers[] = { + { + .scheme = "Basic", + .rx = http_rx_basic_auth, + }, + { + .scheme = "Digest", + .rx = http_rx_digest_auth, + }, + { NULL, NULL }, +}; + +/** + * Handle HTTP WWW-Authenticate header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_www_authenticate ( struct http_request *http, char *value ) { + struct http_auth_header_handler *handler; + char *separator; + char *scheme; + char *params; + int rc; + + /* Extract scheme */ + separator = strchr ( value, ' ' ); + if ( ! separator ) { + DBGC ( http, "HTTP %p malformed WWW-Authenticate header\n", + http ); + return -EINVAL_HEADER; + } + *separator = '\0'; + scheme = value; + params = ( separator + 1 ); + + /* Hand off to header handler, if one exists */ + for ( handler = http_auth_header_handlers; handler->scheme; handler++ ){ + if ( strcasecmp ( scheme, handler->scheme ) == 0 ) { + if ( ( rc = handler->rx ( http, params ) ) != 0 ) + return rc; + break; + } + } + 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, 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, + }, + { + .header = "Connection", + .rx = http_rx_connection, + }, + { + .header = "WWW-Authenticate", + .rx = http_rx_www_authenticate, + }, + { 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 ); + + /* Handle response code */ + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) { + if ( ( rc = http_response_to_rc ( http->code ) ) != 0 ) + return rc; + } + + /* Move to next state */ + if ( http->rx_state == HTTP_RX_HEADER ) { + DBGC ( http, "HTTP %p start of data\n", http ); + http->rx_state = ( http->chunked ? + HTTP_RX_CHUNK_LEN : HTTP_RX_DATA ); + if ( ( http->partial_len != 0 ) && + ( ! ( http->flags & HTTP_TRY_AGAIN ) ) ) { + http->remaining = http->partial_len; + } + 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 ); + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) { + 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->flags & HTTP_TRY_AGAIN ) { + /* Discard all received data */ + iob_pull ( iobuf, data_len ); + } else 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 ) ); +} + +/** + * Close HTTP socket + * + * @v http HTTP request + * @v rc Reason for close + */ +static void http_socket_close ( struct http_request *http, int rc ) { + + /* If we have an error, terminate */ + if ( rc != 0 ) { + http_close ( http, rc ); + return; + } + + /* Mark HTTP request as complete */ + http_done ( http ); +} + +/** + * Generate HTTP Basic authorisation string + * + * @v http HTTP request + * @ret auth Authorisation string, or NULL on error + * + * The authorisation string is dynamically allocated, and must be + * freed by the caller. + */ +static char * http_basic_auth ( struct http_request *http ) { + const char *user = http->uri->user; + const char *password = + ( http->uri->password ? http->uri->password : "" ); + size_t user_pw_len = + ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) ); + char user_pw[ user_pw_len + 1 /* NUL */ ]; + size_t user_pw_base64_len = base64_encoded_len ( user_pw_len ); + char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; + char *auth; + int len; + + /* Sanity check */ + assert ( user != NULL ); + + /* Make "user:password" string from decoded fields */ + snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password ); + + /* Base64-encode the "user:password" string */ + base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 ); + + /* Generate the authorisation string */ + len = asprintf ( &auth, "Authorization: Basic %s\r\n", + user_pw_base64 ); + if ( len < 0 ) + return NULL; + + return auth; +} + +/** + * Generate HTTP Digest authorisation string + * + * @v http HTTP request + * @v method HTTP method (e.g. "GET") + * @v uri HTTP request URI (e.g. "/index.html") + * @ret auth Authorisation string, or NULL on error + * + * The authorisation string is dynamically allocated, and must be + * freed by the caller. + */ +static char * http_digest_auth ( struct http_request *http, + const char *method, const char *uri ) { + const char *user = http->uri->user; + const char *password = + ( http->uri->password ? http->uri->password : "" ); + const char *realm = http->auth_realm; + const char *nonce = http->auth_nonce; + const char *opaque = http->auth_opaque; + static const char colon = ':'; + uint8_t ctx[MD5_CTX_SIZE]; + uint8_t digest[MD5_DIGEST_SIZE]; + char ha1[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char ha2[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char response[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char *auth; + int len; + + /* Sanity checks */ + assert ( user != NULL ); + assert ( realm != NULL ); + assert ( nonce != NULL ); + + /* Generate HA1 */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, user, strlen ( user ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, realm, strlen ( realm ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, password, strlen ( password ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), ha1 ); + + /* Generate HA2 */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, method, strlen ( method ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, uri, strlen ( uri ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), ha2 ); + + /* Generate response */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, ha1, strlen ( ha1 ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, nonce, strlen ( nonce ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, ha2, strlen ( ha2 ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), response ); + + /* Generate the authorisation string */ + len = asprintf ( &auth, "Authorization: Digest username=\"%s\", " + "realm=\"%s\", nonce=\"%s\", uri=\"%s\", " + "%s%s%sresponse=\"%s\"\r\n", user, realm, nonce, uri, + ( opaque ? "opaque=\"" : "" ), + ( opaque ? opaque : "" ), + ( opaque ? "\", " : "" ), response ); + if ( len < 0 ) + return NULL; + + return auth; +} + +/** + * HTTP process + * + * @v http HTTP request + */ +static void http_step ( struct http_request *http ) { + size_t uri_len; + char *method; + char *uri; + char *range; + char *auth; + int len; + 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; + + /* 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_CLIENT_KEEPALIVE ); + } + + /* Determine method */ + method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" ); + + /* Construct path?query request */ + uri_len = ( unparse_uri ( NULL, 0, http->uri, + URI_PATH_BIT | URI_QUERY_BIT ) + + 1 /* possible "/" */ + 1 /* NUL */ ); + uri = malloc ( uri_len ); + if ( ! uri ) { + rc = -ENOMEM; + goto err_uri; + } + unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT ); + if ( ! uri[0] ) { + uri[0] = '/'; + uri[1] = '\0'; + } + + /* Calculate range request parameters if applicable */ + if ( http->partial_len ) { + len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n", + http->partial_start, + ( http->partial_start + http->partial_len + - 1 ) ); + if ( len < 0 ) { + rc = len; + goto err_range; + } + } else { + range = NULL; + } + + /* Construct authorisation, if applicable */ + if ( http->flags & HTTP_BASIC_AUTH ) { + auth = http_basic_auth ( http ); + if ( ! auth ) { + rc = -ENOMEM; + goto err_auth; + } + } else if ( http->flags & HTTP_DIGEST_AUTH ) { + auth = http_digest_auth ( http, method, uri ); + if ( ! auth ) { + rc = -ENOMEM; + goto err_auth; + } + } else { + auth = NULL; + } + + /* Mark request as transmitted */ + http->flags &= ~HTTP_TX_PENDING; + + /* Send request */ + if ( ( rc = xfer_printf ( &http->socket, + "%s %s HTTP/1.1\r\n" + "User-Agent: iPXE/%s\r\n" + "Host: %s%s%s\r\n" + "%s%s%s" + "\r\n", + method, uri, product_version, http->uri->host, + ( http->uri->port ? + ":" : "" ), + ( http->uri->port ? + http->uri->port : "" ), + ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ? + "Connection: keep-alive\r\n" : "" ), + ( range ? range : "" ), + ( auth ? auth : "" ) ) ) != 0 ) { + goto err_xfer; + } + + err_xfer: + free ( auth ); + err_auth: + free ( range ); + err_range: + free ( uri ); + err_uri: + 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; + + /* Schedule request */ + http->rx_state = HTTP_RX_RESPONSE; + http->flags = ( HTTP_TX_PENDING | HTTP_CLIENT_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_socket_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; + 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 ); + http->default_port = default_port; + http->filter = filter; + 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 */ + if ( ( rc = http_socket_open ( http ) ) != 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/roms/ipxe/src/net/tcp/https.c b/roms/ipxe/src/net/tcp/https.c index 805d108bb..6112acdae 100644 --- a/roms/ipxe/src/net/tcp/https.c +++ b/roms/ipxe/src/net/tcp/https.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/tcp/iscsi.c b/roms/ipxe/src/net/tcp/iscsi.c index cde3ed6db..c9daf1ff4 100644 --- a/roms/ipxe/src/net/tcp/iscsi.c +++ b/roms/ipxe/src/net/tcp/iscsi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -131,6 +132,14 @@ FEATURE ( FEATURE_PROTOCOL, "iSCSI", DHCP_EB_FEATURE_ISCSI, 1 ); __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 ); @@ -329,7 +338,8 @@ static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc, iscsi->command = NULL; /* Send SCSI response, if any */ - scsi_response ( &iscsi->data, rsp ); + if ( rsp ) + 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 @@ -562,20 +572,23 @@ static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) { 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 ); + 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 ); } @@ -793,13 +806,17 @@ 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 ); - iobuf = xfer_alloc_iob ( &iscsi->socket, len ); + 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 ); } @@ -1083,8 +1100,8 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, struct iscsi_string_type { /** String key * - * This is the portion up to and including the "=" sign, - * e.g. "InitiatorName=", "CHAP_A=", etc. + * This is the portion preceding the "=" sign, + * e.g. "InitiatorName", "CHAP_A", etc. */ const char *key; /** Handle iSCSI string value @@ -1098,13 +1115,13 @@ struct iscsi_string_type { /** 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 }, + { "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 } }; @@ -1118,16 +1135,35 @@ static struct iscsi_string_type iscsi_string_types[] = { 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++ ) { - key_len = strlen ( type->key ); if ( strncmp ( string, type->key, key_len ) != 0 ) continue; DBGC ( iscsi, "iSCSI %p handling %s\n", iscsi, string ); - if ( ( rc = type->handle ( iscsi, - ( string + key_len ) ) ) != 0 ) { + if ( ( rc = type->handle ( iscsi, value ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p could not handle %s: %s\n", iscsi, string, strerror ( rc ) ); return rc; @@ -1304,6 +1340,24 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi, * */ +/** + * 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 * @@ -1315,8 +1369,7 @@ static int iscsi_rx_login_response ( struct iscsi_session *iscsi, static void iscsi_start_tx ( struct iscsi_session *iscsi ) { assert ( iscsi->tx_state == ISCSI_TX_IDLE ); - assert ( ! process_running ( &iscsi->process ) ); - + /* Initialise TX BHS */ memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) ); @@ -1324,7 +1377,7 @@ static void iscsi_start_tx ( struct iscsi_session *iscsi ) { iscsi->tx_state = ISCSI_TX_BHS; /* Start transmission process */ - process_add ( &iscsi->process ); + iscsi_tx_resume ( iscsi ); } /** @@ -1371,27 +1424,6 @@ static int iscsi_tx_data ( struct iscsi_session *iscsi ) { } } -/** - * Transmit data padding of an iSCSI PDU - * - * @v iscsi iSCSI session - * @ret rc Return status code - * - * Handle transmission of any data padding in a PDU data segment. - * iscsi::tx_bhs will be valid when this is called. - */ -static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) { - static const char pad[] = { '\0', '\0', '\0' }; - struct iscsi_bhs_common *common = &iscsi->tx_bhs.common; - size_t pad_len; - - pad_len = ISCSI_DATA_PAD_LEN ( common->lengths ); - if ( ! pad_len ) - return 0; - - return xfer_deliver_raw ( &iscsi->socket, pad, pad_len ); -} - /** * Complete iSCSI PDU transmission * @@ -1405,7 +1437,7 @@ static void iscsi_tx_done ( struct iscsi_session *iscsi ) { struct iscsi_bhs_common *common = &iscsi->tx_bhs.common; /* Stop transmission process */ - process_del ( &iscsi->process ); + iscsi_tx_pause ( iscsi ); switch ( common->opcode & ISCSI_OPCODE_MASK ) { case ISCSI_OPCODE_DATA_OUT: @@ -1427,9 +1459,7 @@ static void iscsi_tx_done ( struct iscsi_session *iscsi ) { * * Constructs data to be sent for the current TX state */ -static void iscsi_tx_step ( struct process *process ) { - struct iscsi_session *iscsi = - container_of ( process, struct iscsi_session, process ); +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; @@ -1452,16 +1482,11 @@ static void iscsi_tx_step ( struct process *process ) { case ISCSI_TX_DATA: tx = iscsi_tx_data; tx_len = ISCSI_DATA_LEN ( common->lengths ); - next_state = ISCSI_TX_DATA_PADDING; - break; - case ISCSI_TX_DATA_PADDING: - tx = iscsi_tx_data_padding; - tx_len = ISCSI_DATA_PAD_LEN ( common->lengths ); next_state = ISCSI_TX_IDLE; break; case ISCSI_TX_IDLE: - /* Stop processing */ - iscsi_tx_done ( iscsi ); + /* Nothing to do; pause processing */ + iscsi_tx_pause ( iscsi ); return; default: assert ( 0 ); @@ -1470,7 +1495,10 @@ static void iscsi_tx_step ( struct process *process ) { /* Check for window availability, if needed */ if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) { - /* Cannot transmit at this point; stop processing */ + /* Cannot transmit at this point; pause + * processing and wait for window to reopen + */ + iscsi_tx_pause ( iscsi ); return; } @@ -1485,9 +1513,19 @@ static void iscsi_tx_step ( struct process *process ) { /* 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 * @@ -1694,6 +1732,8 @@ static int iscsi_vredirect ( struct iscsi_session *iscsi, int type, /** 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 ), }; @@ -2034,7 +2074,7 @@ static int iscsi_open ( struct interface *parent, struct uri *uri ) { 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_tx_step, + process_init_stopped ( &iscsi->process, &iscsi_process_desc, &iscsi->refcnt ); /* Parse root path */ diff --git a/roms/ipxe/src/net/tcp/syslogs.c b/roms/ipxe/src/net/tcp/syslogs.c new file mode 100644 index 000000000..dae6ba18b --- /dev/null +++ b/roms/ipxe/src/net/tcp/syslogs.c @@ -0,0 +1,274 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 = syslog_send ( &syslogs, syslogs_severity, + syslogs_buffer, "\n" ) ) != 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/roms/ipxe/src/net/tcpip.c b/roms/ipxe/src/net/tcpip.c index 4451bf111..8e187f7ec 100644 --- a/roms/ipxe/src/net/tcpip.c +++ b/roms/ipxe/src/net/tcpip.c @@ -97,8 +97,8 @@ int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, * 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 ) { +uint16_t generic_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ) { unsigned int cksum = ( ( ~partial ) & 0xffff ); unsigned int value; unsigned int i; diff --git a/roms/ipxe/src/net/tls.c b/roms/ipxe/src/net/tls.c index 5e22221d2..5e18f7266 100644 --- a/roms/ipxe/src/net/tls.c +++ b/roms/ipxe/src/net/tls.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -28,20 +29,143 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <time.h> #include <errno.h> #include <byteswap.h> +#include <ipxe/pending.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/asn1.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" ) +#define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER ) +#define EINFO_EINVAL_CHANGE_CIPHER \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + "Invalid Change Cipher record" ) +#define EINVAL_ALERT __einfo_error ( EINFO_EINVAL_ALERT ) +#define EINFO_EINVAL_ALERT \ + __einfo_uniqify ( EINFO_EINVAL, 0x02, \ + "Invalid Alert record" ) +#define EINVAL_HELLO __einfo_error ( EINFO_EINVAL_HELLO ) +#define EINFO_EINVAL_HELLO \ + __einfo_uniqify ( EINFO_EINVAL, 0x03, \ + "Invalid Server Hello record" ) +#define EINVAL_CERTIFICATE __einfo_error ( EINFO_EINVAL_CERTIFICATE ) +#define EINFO_EINVAL_CERTIFICATE \ + __einfo_uniqify ( EINFO_EINVAL, 0x04, \ + "Invalid Certificate" ) +#define EINVAL_CERTIFICATES __einfo_error ( EINFO_EINVAL_CERTIFICATES ) +#define EINFO_EINVAL_CERTIFICATES \ + __einfo_uniqify ( EINFO_EINVAL, 0x05, \ + "Invalid Server Certificate record" ) +#define EINVAL_HELLO_DONE __einfo_error ( EINFO_EINVAL_HELLO_DONE ) +#define EINFO_EINVAL_HELLO_DONE \ + __einfo_uniqify ( EINFO_EINVAL, 0x06, \ + "Invalid Server Hello Done record" ) +#define EINVAL_FINISHED __einfo_error ( EINFO_EINVAL_FINISHED ) +#define EINFO_EINVAL_FINISHED \ + __einfo_uniqify ( EINFO_EINVAL, 0x07, \ + "Invalid Server Finished record" ) +#define EINVAL_HANDSHAKE __einfo_error ( EINFO_EINVAL_HANDSHAKE ) +#define EINFO_EINVAL_HANDSHAKE \ + __einfo_uniqify ( EINFO_EINVAL, 0x08, \ + "Invalid Handshake record" ) +#define EINVAL_STREAM __einfo_error ( EINFO_EINVAL_STREAM ) +#define EINFO_EINVAL_STREAM \ + __einfo_uniqify ( EINFO_EINVAL, 0x09, \ + "Invalid stream-ciphered record" ) +#define EINVAL_BLOCK __einfo_error ( EINFO_EINVAL_BLOCK ) +#define EINFO_EINVAL_BLOCK \ + __einfo_uniqify ( EINFO_EINVAL, 0x0a, \ + "Invalid block-ciphered record" ) +#define EINVAL_PADDING __einfo_error ( EINFO_EINVAL_PADDING ) +#define EINFO_EINVAL_PADDING \ + __einfo_uniqify ( EINFO_EINVAL, 0x0b, \ + "Invalid block padding" ) +#define EINVAL_RX_STATE __einfo_error ( EINFO_EINVAL_RX_STATE ) +#define EINFO_EINVAL_RX_STATE \ + __einfo_uniqify ( EINFO_EINVAL, 0x0c, \ + "Invalid receive state" ) +#define EINVAL_MAC __einfo_error ( EINFO_EINVAL_MAC ) +#define EINFO_EINVAL_MAC \ + __einfo_uniqify ( EINFO_EINVAL, 0x0d, \ + "Invalid MAC" ) +#define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT ) +#define EINFO_EIO_ALERT \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + "Unknown alert level" ) +#define ENOMEM_CONTEXT __einfo_error ( EINFO_ENOMEM_CONTEXT ) +#define EINFO_ENOMEM_CONTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x01, \ + "Not enough space for crypto context" ) +#define ENOMEM_CERTIFICATE __einfo_error ( EINFO_ENOMEM_CERTIFICATE ) +#define EINFO_ENOMEM_CERTIFICATE \ + __einfo_uniqify ( EINFO_ENOMEM, 0x02, \ + "Not enough space for certificate" ) +#define ENOMEM_CHAIN __einfo_error ( EINFO_ENOMEM_CHAIN ) +#define EINFO_ENOMEM_CHAIN \ + __einfo_uniqify ( EINFO_ENOMEM, 0x03, \ + "Not enough space for certificate chain" ) +#define ENOMEM_TX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT ) +#define EINFO_ENOMEM_TX_PLAINTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x04, \ + "Not enough space for transmitted plaintext" ) +#define ENOMEM_TX_CIPHERTEXT __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT ) +#define EINFO_ENOMEM_TX_CIPHERTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x05, \ + "Not enough space for transmitted ciphertext" ) +#define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA ) +#define EINFO_ENOMEM_RX_DATA \ + __einfo_uniqify ( EINFO_ENOMEM, 0x07, \ + "Not enough space for received data" ) +#define ENOMEM_RX_CONCAT __einfo_error ( EINFO_ENOMEM_RX_CONCAT ) +#define EINFO_ENOMEM_RX_CONCAT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x08, \ + "Not enough space to concatenate received data" ) +#define ENOTSUP_CIPHER __einfo_error ( EINFO_ENOTSUP_CIPHER ) +#define EINFO_ENOTSUP_CIPHER \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ + "Unsupported cipher" ) +#define ENOTSUP_NULL __einfo_error ( EINFO_ENOTSUP_NULL ) +#define EINFO_ENOTSUP_NULL \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \ + "Refusing to use null cipher" ) +#define ENOTSUP_SIG_HASH __einfo_error ( EINFO_ENOTSUP_SIG_HASH ) +#define EINFO_ENOTSUP_SIG_HASH \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \ + "Unsupported signature and hash algorithm" ) +#define ENOTSUP_VERSION __einfo_error ( EINFO_ENOTSUP_VERSION ) +#define EINFO_ENOTSUP_VERSION \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \ + "Unsupported protocol version" ) +#define EPERM_ALERT __einfo_error ( EINFO_EPERM_ALERT ) +#define EINFO_EPERM_ALERT \ + __einfo_uniqify ( EINFO_EPERM, 0x01, \ + "Received fatal alert" ) +#define EPERM_VERIFY __einfo_error ( EINFO_EPERM_VERIFY ) +#define EINFO_EPERM_VERIFY \ + __einfo_uniqify ( EINFO_EPERM, 0x02, \ + "Handshake verification failed" ) +#define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION ) +#define EINFO_EPROTO_VERSION \ + __einfo_uniqify ( EINFO_EPROTO, 0x01, \ + "Illegal protocol version upgrade" ) + 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, @@ -63,10 +187,103 @@ static void tls_clear_cipher ( struct tls_session *tls, * TLS uses 24-bit integers in several places, which are awkward to * parse in C. */ -static unsigned long tls_uint24 ( uint8_t field24[3] ) { - return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] ); +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 ( ( ! is_pending ( &tls->client_negotiation ) ) && + ( ! is_pending ( &tls->server_negotiation ) ) ); +} + +/****************************************************************************** + * + * 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 @@ -82,14 +299,19 @@ static unsigned long tls_uint24 ( uint8_t field24[3] ) { static void free_tls ( struct refcnt *refcnt ) { struct tls_session *tls = container_of ( refcnt, struct tls_session, refcnt ); + struct io_buffer *iobuf; + struct io_buffer *tmp; /* 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 ); - x509_free_rsa_public_key ( &tls->rsa ); - free ( tls->rx_data ); + list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) { + list_del ( &iobuf->list ); + free_iob ( iobuf ); + } + x509_chain_put ( tls->chain ); /* Free TLS structure itself */ free ( tls ); @@ -103,12 +325,17 @@ static void free_tls ( struct refcnt *refcnt ) { */ static void tls_close ( struct tls_session *tls, int rc ) { + /* Remove pending operations, if applicable */ + pending_put ( &tls->client_negotiation ); + pending_put ( &tls->server_negotiation ); + /* Remove process */ process_del ( &tls->process ); - - /* Close ciphertext and plaintext streams */ + + /* Close all interfaces */ intf_shutdown ( &tls->cipherstream, rc ); intf_shutdown ( &tls->plainstream, rc ); + intf_shutdown ( &tls->validator, rc ); } /****************************************************************************** @@ -121,12 +348,25 @@ static void tls_close ( struct tls_session *tls, int rc ) { /** * Generate random data * + * @v tls TLS session * @v data Buffer to fill * @v len Length of buffer + * @ret rc Return status code */ -static void tls_generate_random ( void *data, size_t len ) { - /* FIXME: Some real random data source would be nice... */ - memset ( data, 0x01, len ); +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; } /** @@ -233,32 +473,40 @@ static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len, size_t subsecret_len; void *md5_secret; void *sha1_secret; - uint8_t out_md5[out_len]; - uint8_t out_sha1[out_len]; + uint8_t buf[out_len]; unsigned int i; va_start ( seeds, out_len ); - /* 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 ); + 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 + */ - /* Calculate MD5 portion */ - va_copy ( tmp, seeds ); - tls_p_hash_va ( tls, &md5_algorithm, md5_secret, subsecret_len, - out_md5, out_len, seeds ); - va_end ( tmp ); + /* 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 SHA1 portion */ - va_copy ( tmp, seeds ); - tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret, subsecret_len, - out_sha1, out_len, seeds ); - va_end ( tmp ); + /* 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 ); - /* XOR the two portions together into the final output buffer */ - for ( i = 0 ; i < out_len ; i++ ) { - *( ( uint8_t * ) out + i ) = ( out_md5[i] ^ out_sha1[i] ); + /* 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 ); @@ -323,9 +571,9 @@ static void tls_generate_master_secret ( struct tls_session *tls ) { 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->digest->digestsize; - size_t key_size = tx_cipherspec->key_len; - size_t iv_size = tx_cipherspec->cipher->blocksize; + 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; @@ -353,7 +601,7 @@ static int tls_generate_keys ( struct tls_session *tls ) { key += hash_size; /* TX key */ - if ( ( rc = cipher_setkey ( tx_cipherspec->cipher, + 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", @@ -365,7 +613,7 @@ static int tls_generate_keys ( struct tls_session *tls ) { key += key_size; /* RX key */ - if ( ( rc = cipher_setkey ( rx_cipherspec->cipher, + 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", @@ -377,13 +625,15 @@ static int tls_generate_keys ( struct tls_session *tls ) { key += key_size; /* TX initialisation vector */ - cipher_setiv ( tx_cipherspec->cipher, tx_cipherspec->cipher_ctx, key ); + 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->cipher, rx_cipherspec->cipher_ctx, key ); + 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; @@ -400,6 +650,70 @@ static int tls_generate_keys ( struct tls_session *tls ) { ****************************************************************************** */ +/** 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 * @@ -407,11 +721,14 @@ static int tls_generate_keys ( struct tls_session *tls ) { */ 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->pubkey = &pubkey_null; - cipherspec->cipher = &cipher_null; - cipherspec->digest = &digest_null; + memset ( cipherspec, 0, sizeof ( *cipherspec ) ); + cipherspec->suite = &tls_cipher_suite_null; } /** @@ -419,18 +736,15 @@ static void tls_clear_cipher ( struct tls_session *tls __unused, * * @v tls TLS session * @v cipherspec TLS cipher specification - * @v pubkey Public-key encryption elgorithm - * @v cipher Bulk encryption cipher algorithm - * @v digest MAC digest algorithm - * @v key_len Key length + * @v suite Cipher suite * @ret rc Return status code */ static int tls_set_cipher ( struct tls_session *tls, struct tls_cipherspec *cipherspec, - struct pubkey_algorithm *pubkey, - struct cipher_algorithm *cipher, - struct digest_algorithm *digest, - size_t key_len ) { + 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; @@ -439,13 +753,12 @@ static int tls_set_cipher ( struct tls_session *tls, /* Allocate dynamic storage */ total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize ); - dynamic = malloc ( total ); + dynamic = zalloc ( total ); if ( ! dynamic ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto " "context\n", tls, total ); - return -ENOMEM; + return -ENOMEM_CONTEXT; } - memset ( dynamic, 0, total ); /* Assign storage */ cipherspec->dynamic = dynamic; @@ -456,10 +769,7 @@ static int tls_set_cipher ( struct tls_session *tls, assert ( ( cipherspec->dynamic + total ) == dynamic ); /* Store parameters */ - cipherspec->pubkey = pubkey; - cipherspec->cipher = cipher; - cipherspec->digest = digest; - cipherspec->key_len = key_len; + cipherspec->suite = suite; return 0; } @@ -473,39 +783,28 @@ static int tls_set_cipher ( struct tls_session *tls, */ static int tls_select_cipher ( struct tls_session *tls, unsigned int cipher_suite ) { - struct pubkey_algorithm *pubkey = &pubkey_null; - struct cipher_algorithm *cipher = &cipher_null; - struct digest_algorithm *digest = &digest_null; - unsigned int key_len = 0; + struct tls_cipher_suite *suite; int rc; - switch ( cipher_suite ) { - case htons ( TLS_RSA_WITH_AES_128_CBC_SHA ): - key_len = ( 128 / 8 ); - cipher = &aes_cbc_algorithm; - digest = &sha1_algorithm; - break; - case htons ( TLS_RSA_WITH_AES_256_CBC_SHA ): - key_len = ( 256 / 8 ); - cipher = &aes_cbc_algorithm; - digest = &sha1_algorithm; - break; - default: + /* 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; + return -ENOTSUP_CIPHER; } /* Set ciphers */ - if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, pubkey, - cipher, digest, key_len ) ) != 0 ) + if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, + suite ) ) != 0 ) return rc; - if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending, pubkey, - cipher, digest, key_len ) ) != 0 ) + 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, - pubkey->name, cipher->name, ( key_len * 8 ), digest->name ); + 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; } @@ -523,12 +822,9 @@ static int tls_change_cipher ( struct tls_session *tls, struct tls_cipherspec *active ) { /* Sanity check */ - if ( /* FIXME (when pubkey is not hard-coded to RSA): - * ( pending->pubkey == &pubkey_null ) || */ - ( pending->cipher == &cipher_null ) || - ( pending->digest == &digest_null ) ) { + if ( pending->suite == &tls_cipher_suite_null ) { DBGC ( tls, "TLS %p refusing to use null cipher\n", tls ); - return -ENOTSUP; + return -ENOTSUP_NULL; } tls_clear_cipher ( tls, active ); @@ -536,6 +832,59 @@ static int tls_change_cipher ( struct tls_session *tls, 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 @@ -553,8 +902,10 @@ static int tls_change_cipher ( struct tls_session *tls, static void tls_add_handshake ( struct tls_session *tls, const void *data, size_t len ) { - digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len ); - digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len ); + digest_update ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx, + data, len ); + digest_update ( &sha256_algorithm, tls->handshake_sha256_ctx, + data, len ); } /** @@ -563,21 +914,15 @@ static void tls_add_handshake ( struct tls_session *tls, * @v tls TLS session * @v out Output buffer * - * Calculates the MD5+SHA1 digest over all handshake messages seen so - * far. + * 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 *md5 = &md5_algorithm; - struct digest_algorithm *sha1 = &sha1_algorithm; - uint8_t md5_ctx[md5->ctxsize]; - uint8_t sha1_ctx[sha1->ctxsize]; - void *md5_digest = out; - void *sha1_digest = ( out + md5->digestsize ); - - memcpy ( md5_ctx, tls->handshake_md5_ctx, sizeof ( md5_ctx ) ); - memcpy ( sha1_ctx, tls->handshake_sha1_ctx, sizeof ( sha1_ctx ) ); - digest_final ( md5, md5_ctx, md5_digest ); - digest_final ( sha1, sha1_ctx, sha1_digest ); + struct digest_algorithm *digest = tls->handshake_digest; + uint8_t ctx[ digest->ctxsize ]; + + memcpy ( ctx, tls->handshake_ctx, sizeof ( ctx ) ); + digest_final ( digest, ctx, out ); } /****************************************************************************** @@ -587,6 +932,15 @@ static void tls_verify_handshake ( struct tls_session *tls, void *out ) { ****************************************************************************** */ +/** + * Resume TX state machine + * + * @v tls TLS session + */ +static void tls_tx_resume ( struct tls_session *tls ) { + process_add ( &tls->process ); +} + /** * Transmit Handshake record * @@ -618,25 +972,134 @@ static int tls_send_client_hello ( struct tls_session *tls ) { uint8_t random[32]; uint8_t session_id_len; uint16_t cipher_suite_len; - uint16_t cipher_suites[2]; + 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; + uint16_t max_fragment_length_type; + uint16_t max_fragment_length_len; + struct { + uint8_t max; + } __attribute__ (( packed )) max_fragment_length; + } __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_TLS_1_0 ); + hello.version = htons ( tls->version ); memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) ); hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) ); - hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ); - hello.cipher_suites[1] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ); + 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 ) ); + hello.extensions.max_fragment_length_type + = htons ( TLS_MAX_FRAGMENT_LENGTH ); + hello.extensions.max_fragment_length_len + = htons ( sizeof ( hello.extensions.max_fragment_length ) ); + hello.extensions.max_fragment_length.max + = TLS_MAX_FRAGMENT_LENGTH_4096; 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_CERTIFICATE; + + /* 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 * @@ -644,39 +1107,130 @@ static int tls_send_client_hello ( struct tls_session *tls ) { * @ret rc Return status code */ static int tls_send_client_key_exchange ( struct tls_session *tls ) { - /* FIXME: Hack alert */ - RSA_CTX *rsa_ctx; - RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len, - tls->rsa.exponent, tls->rsa.exponent_len ); + 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[rsa_ctx->num_octets]; + 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 ) ); - key_xchg.type_length = ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) | - htonl ( sizeof ( key_xchg ) - - sizeof ( key_xchg.type_length ) ) ); - key_xchg.encrypted_pre_master_secret_len - = htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) ); - - /* FIXME: Hack alert */ - DBGC ( tls, "RSA encrypting plaintext, modulus, exponent:\n" ); - DBGC_HD ( tls, &tls->pre_master_secret, - sizeof ( tls->pre_master_secret ) ); - DBGC_HD ( tls, tls->rsa.modulus, tls->rsa.modulus_len ); - DBGC_HD ( tls, tls->rsa.exponent, tls->rsa.exponent_len ); - RSA_encrypt ( rsa_ctx, ( const uint8_t * ) &tls->pre_master_secret, - sizeof ( tls->pre_master_secret ), - key_xchg.encrypted_pre_master_secret, 0 ); - DBGC ( tls, "RSA encrypt done. Ciphertext:\n" ); - DBGC_HD ( tls, &key_xchg.encrypted_pre_master_secret, - sizeof ( key_xchg.encrypted_pre_master_secret ) ); - RSA_free ( rsa_ctx ); - - - return tls_send_handshake ( tls, &key_xchg, 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_SIG_HASH; + 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; } /** @@ -698,22 +1252,33 @@ static int tls_send_change_cipher ( struct tls_session *tls ) { * @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[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE]; + 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 ); + 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, sizeof ( digest ) ); + "client finished", digest_out, sizeof ( digest_out ) ); - return tls_send_handshake ( tls, &finished, sizeof ( finished ) ); + /* Transmit record */ + if ( ( rc = tls_send_handshake ( tls, &finished, + sizeof ( finished ) ) ) != 0 ) + return rc; + + /* Mark client as finished */ + pending_put ( &tls->client_negotiation ); + + return 0; } /** @@ -725,13 +1290,13 @@ static int tls_send_finished ( struct tls_session *tls ) { * @ret rc Return status code */ static int tls_new_change_cipher ( struct tls_session *tls, - void *data, size_t len ) { + 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; + return -EINVAL_CHANGE_CIPHER; } if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending, @@ -753,19 +1318,20 @@ static int tls_new_change_cipher ( struct tls_session *tls, * @v len Length of plaintext record * @ret rc Return status code */ -static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) { - struct { +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; - void *end = alert->next; + 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; + return -EINVAL_ALERT; } switch ( alert->level ) { @@ -776,11 +1342,11 @@ static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) { case TLS_ALERT_FATAL: DBGC ( tls, "TLS %p received fatal alert %d\n", tls, alert->description ); - return -EPERM; + return -EPERM_ALERT; default: DBGC ( tls, "TLS %p received unknown alert level %d" "(alert %d)\n", tls, alert->level, alert->description ); - return -EIO; + return -EIO_ALERT; } } @@ -793,35 +1359,53 @@ static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) { * @ret rc Return status code */ static int tls_new_server_hello ( struct tls_session *tls, - void *data, size_t len ) { - struct { + 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; - struct { + 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; - void *end = hello_b->next; + const void *end = hello_b->next; + uint16_t version; int rc; /* Sanity check */ - if ( end != ( data + len ) ) { - DBGC ( tls, "TLS %p received overlength Server Hello\n", tls ); + if ( end > ( data + len ) ) { + DBGC ( tls, "TLS %p received underlength Server Hello\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_HELLO; } - /* Check protocol version */ - if ( ntohs ( hello_a->version ) < TLS_VERSION_TLS_1_0 ) { + /* 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, ( ntohs ( hello_a->version ) >> 8 ), - ( ntohs ( hello_a->version ) & 0xff ) ); - return -ENOTSUP; + tls, ( version >> 8 ), ( version & 0xff ) ); + return -ENOTSUP_VERSION; + } + 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_VERSION; + } + 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 */ @@ -840,6 +1424,77 @@ static int tls_new_server_hello ( struct tls_session *tls, 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_CHAIN; + 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_CERTIFICATE; + 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 * @@ -849,19 +1504,13 @@ static int tls_new_server_hello ( struct tls_session *tls, * @ret rc Return status code */ static int tls_new_certificate ( struct tls_session *tls, - void *data, size_t len ) { - struct { + const void *data, size_t len ) { + const struct { uint8_t length[3]; uint8_t certificates[0]; } __attribute__ (( packed )) *certificate = data; - struct { - uint8_t length[3]; - uint8_t certificate[0]; - } __attribute__ (( packed )) *element = - ( ( void * ) certificate->certificates ); - size_t elements_len = tls_uint24 ( certificate->length ); - void *end = ( certificate->certificates + elements_len ); - struct asn1_cursor cursor; + size_t certificates_len = tls_uint24 ( certificate->length ); + const void *end = ( certificate->certificates + certificates_len ); int rc; /* Sanity check */ @@ -869,33 +1518,38 @@ static int tls_new_certificate ( struct tls_session *tls, DBGC ( tls, "TLS %p received overlength Server Certificate\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_CERTIFICATES; } - /* Traverse certificate chain */ - do { - cursor.data = element->certificate; - cursor.len = tls_uint24 ( element->length ); - if ( ( cursor.data + cursor.len ) > end ) { - DBGC ( tls, "TLS %p received corrupt 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; - // HACK - if ( ( rc = x509_rsa_public_key ( &cursor, - &tls->rsa ) ) != 0 ) { - DBGC ( tls, "TLS %p cannot determine RSA public key: " - "%s\n", tls, strerror ( rc ) ); - return rc; - } - return 0; + return 0; +} - element = ( cursor.data + cursor.len ); - } while ( element != end ); +/** + * 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 -EINVAL; + return 0; } /** @@ -907,30 +1561,28 @@ static int tls_new_certificate ( struct tls_session *tls, * @ret rc Return status code */ static int tls_new_server_hello_done ( struct tls_session *tls, - void *data, size_t len ) { - struct { + const void *data, size_t len ) { + const struct { char next[0]; } __attribute__ (( packed )) *hello_done = data; - void *end = hello_done->next; + 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; + return -EINVAL_HELLO_DONE; } - /* Check that we are ready to send the Client Key Exchange */ - if ( tls->tx_state != TLS_TX_NONE ) { - DBGC ( tls, "TLS %p received Server Hello Done while in " - "TX state %d\n", tls, tls->tx_state ); - return -EIO; + /* 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; } - /* Start sending the Client Key Exchange */ - tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE; - return 0; } @@ -943,12 +1595,40 @@ static int tls_new_server_hello_done ( struct tls_session *tls, * @ret rc Return status code */ static int tls_new_finished ( struct tls_session *tls, - void *data, size_t len ) { + 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_FINISHED; + } + + /* 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_VERIFY; + } + + /* Mark server as finished */ + pending_put ( &tls->server_negotiation ); + + /* Send notification of a window change */ + xfer_window_changed ( &tls->plainstream ); - /* FIXME: Handle this properly */ - tls->tx_state = TLS_TX_DATA; - ( void ) data; - ( void ) len; return 0; } @@ -961,12 +1641,12 @@ static int tls_new_finished ( struct tls_session *tls, * @ret rc Return status code */ static int tls_new_handshake ( struct tls_session *tls, - void *data, size_t len ) { - void *end = ( data + len ); + const void *data, size_t len ) { + const void *end = ( data + len ); int rc; while ( data != end ) { - struct { + const struct { uint8_t type; uint8_t length[3]; uint8_t payload[0]; @@ -980,7 +1660,7 @@ static int tls_new_handshake ( struct tls_session *tls, DBGC ( tls, "TLS %p received overlength Handshake\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_HANDSHAKE; } switch ( handshake->type ) { @@ -990,6 +1670,10 @@ static int tls_new_handshake ( struct tls_session *tls, 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 ); @@ -1028,29 +1712,69 @@ static int tls_new_handshake ( struct tls_session *tls, * * @v tls TLS session * @v type Record type - * @v data Plaintext record - * @v len Length of plaintext record + * @v rx_data List of received data buffers * @ret rc Return status code */ -static int tls_new_record ( struct tls_session *tls, - unsigned int type, void *data, size_t len ) { +static int tls_new_record ( struct tls_session *tls, unsigned int type, + struct list_head *rx_data ) { + struct io_buffer *iobuf; + int ( * handler ) ( struct tls_session *tls, const void *data, + size_t len ); + int rc; + /* Deliver data records to the plainstream interface */ + if ( type == TLS_TYPE_DATA ) { + + /* Fail unless we are ready to receive data */ + if ( ! tls_ready ( tls ) ) + return -ENOTCONN; + + /* Deliver each I/O buffer in turn */ + while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer, + list ) ) ) { + list_del ( &iobuf->list ); + if ( ( rc = xfer_deliver_iob ( &tls->plainstream, + iobuf ) ) != 0 ) { + DBGC ( tls, "TLS %p could not deliver data: " + "%s\n", tls, strerror ( rc ) ); + return rc; + } + } + return 0; + } + + /* For all other records, merge into a single I/O buffer */ + iobuf = iob_concatenate ( rx_data ); + if ( ! iobuf ) { + DBGC ( tls, "TLS %p could not concatenate non-data record " + "type %d\n", tls, type ); + return -ENOMEM_RX_CONCAT; + } + + /* Determine handler */ switch ( type ) { case TLS_TYPE_CHANGE_CIPHER: - return tls_new_change_cipher ( tls, data, len ); + handler = tls_new_change_cipher; + break; case TLS_TYPE_ALERT: - return tls_new_alert ( tls, data, len ); + handler = tls_new_alert; + break; case TLS_TYPE_HANDSHAKE: - return tls_new_handshake ( tls, data, len ); - case TLS_TYPE_DATA: - return xfer_deliver_raw ( &tls->plainstream, data, len ); + handler = tls_new_handshake; + break; default: /* RFC4346 says that we should just ignore unknown * record types. */ + handler = NULL; DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type ); - return 0; + break; } + + /* Handle record and free I/O buffer */ + rc = ( handler ? handler ( tls, iobuf->data, iob_len ( iobuf ) ) : 0 ); + free_iob ( iobuf ); + return rc; } /****************************************************************************** @@ -1060,10 +1784,57 @@ static int tls_new_record ( struct tls_session *tls, ****************************************************************************** */ +/** + * Initialise HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v seq Sequence number + * @v tlshdr TLS header + */ +static void tls_hmac_init ( struct tls_cipherspec *cipherspec, void *ctx, + uint64_t seq, struct tls_header *tlshdr ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_init ( digest, ctx, cipherspec->mac_secret, &digest->digestsize ); + seq = cpu_to_be64 ( seq ); + hmac_update ( digest, ctx, &seq, sizeof ( seq ) ); + hmac_update ( digest, ctx, tlshdr, sizeof ( *tlshdr ) ); +} + +/** + * Update HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v data Data + * @v len Length of data + */ +static void tls_hmac_update ( struct tls_cipherspec *cipherspec, void *ctx, + const void *data, size_t len ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_update ( digest, ctx, data, len ); +} + +/** + * Finalise HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v mac HMAC to fill in + */ +static void tls_hmac_final ( struct tls_cipherspec *cipherspec, void *ctx, + void *hmac ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_final ( digest, ctx, cipherspec->mac_secret, + &digest->digestsize, hmac ); +} + /** * Calculate HMAC * - * @v tls TLS session * @v cipherspec Cipher specification * @v seq Sequence number * @v tlshdr TLS header @@ -1071,21 +1842,15 @@ static int tls_new_record ( struct tls_session *tls, * @v len Length of data * @v mac HMAC to fill in */ -static void tls_hmac ( struct tls_session *tls __unused, - struct tls_cipherspec *cipherspec, +static void tls_hmac ( struct tls_cipherspec *cipherspec, uint64_t seq, struct tls_header *tlshdr, const void *data, size_t len, void *hmac ) { - struct digest_algorithm *digest = cipherspec->digest; - uint8_t digest_ctx[digest->ctxsize]; + struct digest_algorithm *digest = cipherspec->suite->digest; + uint8_t 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 ); + tls_hmac_init ( cipherspec, ctx, seq, tlshdr ); + tls_hmac_update ( cipherspec, ctx, data, len ); + tls_hmac_final ( cipherspec, ctx, hmac ); } /** @@ -1101,7 +1866,7 @@ static void tls_hmac ( struct tls_session *tls __unused, 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.digest->digestsize; + size_t mac_len = tls->tx_cipherspec.suite->digest->digestsize; void *plaintext; void *content; void *mac; @@ -1136,9 +1901,9 @@ static void * __malloc tls_assemble_stream ( struct tls_session *tls, 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.cipher->blocksize; - size_t iv_len = blocksize; - size_t mac_len = tls->tx_cipherspec.digest->digestsize; + 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; @@ -1146,8 +1911,8 @@ static void * tls_assemble_block ( struct tls_session *tls, void *mac; void *padding; - /* FIXME: TLSv1.1 has an explicit IV */ - iv_len = 0; + /* 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 ) ); @@ -1163,7 +1928,7 @@ static void * tls_assemble_block ( struct tls_session *tls, padding = ( mac + mac_len ); /* Fill in block-ciphered struct */ - memset ( iv, 0, iv_len ); + tls_generate_random ( tls, iv, iv_len ); memcpy ( content, data, len ); memcpy ( mac, digest, mac_len ); memset ( padding, padding_len, ( padding_len + 1 ) ); @@ -1185,25 +1950,25 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, 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->digest->digestsize; + 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_TLS_1_0 ); + 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 ); + tls_hmac ( cipherspec, tls->tx_seq, &plaintext_tlshdr, data, len, mac ); /* Allocate and assemble plaintext struct */ - if ( is_stream_cipher ( cipherspec->cipher ) ) { + if ( is_stream_cipher ( cipher ) ) { plaintext = tls_assemble_stream ( tls, data, len, mac, &plaintext_len ); } else { @@ -1213,7 +1978,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, if ( ! plaintext ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for " "plaintext\n", tls, plaintext_len ); - rc = -ENOMEM; + rc = -ENOMEM_TX_PLAINTEXT; goto done; } @@ -1226,20 +1991,19 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, if ( ! ciphertext ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for " "ciphertext\n", tls, ciphertext_len ); - rc = -ENOMEM; + rc = -ENOMEM_TX_CIPHERTEXT; goto done; } /* Assemble ciphertext */ tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) ); tlshdr->type = type; - tlshdr->version = htons ( TLS_VERSION_TLS_1_0 ); + tlshdr->version = htons ( tls->version ); tlshdr->length = htons ( plaintext_len ); memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx, - cipherspec->cipher->ctxsize ); - cipher_encrypt ( cipherspec->cipher, cipherspec->cipher_next_ctx, - plaintext, iob_put ( ciphertext, plaintext_len ), - plaintext_len ); + 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 ); @@ -1256,8 +2020,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, /* Update TX state machine to next record */ tls->tx_seq += 1; memcpy ( tls->tx_cipherspec.cipher_ctx, - tls->tx_cipherspec.cipher_next_ctx, - tls->tx_cipherspec.cipher->ctxsize ); + tls->tx_cipherspec.cipher_next_ctx, cipher->ctxsize ); done: free ( plaintext ); @@ -1269,36 +2032,25 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, * 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 + * @v rx_data List of received data buffers + * @v mac MAC to fill in * @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.digest->digestsize; - if ( plaintext_len < mac_len ) { - DBGC ( tls, "TLS %p received underlength record\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + struct list_head *rx_data, void **mac ) { + size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize; + struct io_buffer *iobuf; + + /* Extract MAC */ + iobuf = list_last_entry ( rx_data, struct io_buffer, list ); + assert ( iobuf != NULL ); + if ( iob_len ( iobuf ) < mac_len ) { + DBGC ( tls, "TLS %p received underlength MAC\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_STREAM; } - content_len = ( plaintext_len - mac_len ); - content = plaintext; - mac = ( content + content_len ); - - /* Fill in return values */ - *data = content; - *len = content_len; - *digest = mac; + iob_unput ( iobuf, mac_len ); + *mac = iobuf->tail; return 0; } @@ -1307,64 +2059,56 @@ static int tls_split_stream ( struct tls_session *tls, * 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 + * @v rx_data List of received data buffers + * @v mac MAC to fill in * @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; + struct list_head *rx_data, void **mac ) { + size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize; + struct io_buffer *iobuf; size_t iv_len; - void *content; - size_t content_len; - void *mac; - size_t mac_len; - void *padding; + uint8_t *padding_final; + uint8_t *padding; size_t padding_len; - unsigned int i; - /* Decompose block-ciphered data */ - 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 */ + iobuf = list_first_entry ( rx_data, struct io_buffer, list ); + iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? + tls->rx_cipherspec.suite->cipher->blocksize : 0 ); + if ( iob_len ( iobuf ) < iv_len ) { + DBGC ( tls, "TLS %p received underlength IV\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_BLOCK; } - iv_len = tls->rx_cipherspec.cipher->blocksize; - - /* FIXME: TLSv1.1 uses an explicit IV */ - iv_len = 0; - - mac_len = tls->rx_cipherspec.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; + iob_pull ( iobuf, iv_len ); + + /* Extract and verify padding */ + iobuf = list_last_entry ( rx_data, struct io_buffer, list ); + padding_final = ( iobuf->tail - 1 ); + padding_len = *padding_final; + if ( ( padding_len + 1 ) > iob_len ( iobuf ) ) { + DBGC ( tls, "TLS %p received underlength padding\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_BLOCK; } - 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 ) { + iob_unput ( iobuf, ( padding_len + 1 ) ); + for ( padding = iobuf->tail ; padding < padding_final ; padding++ ) { + if ( *padding != padding_len ) { DBGC ( tls, "TLS %p received bad padding\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + DBGC_HD ( tls, padding, padding_len ); + return -EINVAL_PADDING; } } - /* Fill in return values */ - *data = content; - *len = content_len; - *digest = mac; + /* Extract MAC */ + if ( iob_len ( iobuf ) < mac_len ) { + DBGC ( tls, "TLS %p received underlength MAC\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_BLOCK; + } + iob_unput ( iobuf, mac_len ); + *mac = iobuf->tail; return 0; } @@ -1374,69 +2118,65 @@ static int tls_split_block ( struct tls_session *tls, * * @v tls TLS session * @v tlshdr Record header - * @v ciphertext Ciphertext record + * @v rx_data List of received data buffers * @ret rc Return status code */ static int tls_new_ciphertext ( struct tls_session *tls, - struct tls_header *tlshdr, void *ciphertext ) { + struct tls_header *tlshdr, + struct list_head *rx_data ) { struct tls_header plaintext_tlshdr; struct tls_cipherspec *cipherspec = &tls->rx_cipherspec; - size_t record_len = ntohs ( tlshdr->length ); - void *plaintext = NULL; - void *data; - size_t len; + struct cipher_algorithm *cipher = cipherspec->suite->cipher; + struct digest_algorithm *digest = cipherspec->suite->digest; + uint8_t ctx[digest->ctxsize]; + uint8_t verify_mac[digest->digestsize]; + struct io_buffer *iobuf; void *mac; - size_t mac_len = cipherspec->digest->digestsize; - uint8_t verify_mac[mac_len]; + size_t len = 0; 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 received data */ + list_for_each_entry ( iobuf, &tls->rx_data, list ) { + cipher_decrypt ( cipher, cipherspec->cipher_ctx, + iobuf->data, iobuf->data, iob_len ( iobuf ) ); } - /* Decrypt the record */ - cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx, - ciphertext, plaintext, record_len ); - /* Split record into content and MAC */ - if ( is_stream_cipher ( cipherspec->cipher ) ) { - if ( ( rc = tls_split_stream ( tls, plaintext, record_len, - &data, &len, &mac ) ) != 0 ) - goto done; + if ( is_stream_cipher ( cipher ) ) { + if ( ( rc = tls_split_stream ( tls, rx_data, &mac ) ) != 0 ) + return rc; } else { - if ( ( rc = tls_split_block ( tls, plaintext, record_len, - &data, &len, &mac ) ) != 0 ) - goto done; + if ( ( rc = tls_split_block ( tls, rx_data, &mac ) ) != 0 ) + return rc; + } + + /* Calculate total length */ + DBGC2 ( tls, "Received plaintext data:\n" ); + list_for_each_entry ( iobuf, rx_data, list ) { + DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + len += iob_len ( iobuf ); } /* 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 ) { + tls_hmac_init ( cipherspec, ctx, tls->rx_seq, &plaintext_tlshdr ); + list_for_each_entry ( iobuf, rx_data, list ) { + tls_hmac_update ( cipherspec, ctx, iobuf->data, + iob_len ( iobuf ) ); + } + tls_hmac_final ( cipherspec, ctx, verify_mac ); + if ( memcmp ( mac, verify_mac, sizeof ( verify_mac ) ) != 0 ) { DBGC ( tls, "TLS %p failed MAC verification\n", tls ); - DBGC_HD ( tls, plaintext, record_len ); - goto done; + return -EINVAL_MAC; } - 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; + if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 ) + return rc; - rc = 0; - done: - free ( plaintext ); - return rc; + return 0; } /****************************************************************************** @@ -1455,7 +2195,7 @@ static int tls_new_ciphertext ( struct tls_session *tls, static size_t tls_plainstream_window ( struct tls_session *tls ) { /* Block window unless we are ready to accept data */ - if ( tls->tx_state != TLS_TX_DATA ) + if ( ! tls_ready ( tls ) ) return 0; return xfer_window ( &tls->cipherstream ); @@ -1475,7 +2215,7 @@ static int tls_plainstream_deliver ( struct tls_session *tls, int rc; /* Refuse unless we are ready to accept data */ - if ( tls->tx_state != TLS_TX_DATA ) { + if ( ! tls_ready ( tls ) ) { rc = -ENOTCONN; goto done; } @@ -1516,20 +2256,61 @@ static struct interface_descriptor tls_plainstream_desc = */ static int tls_newdata_process_header ( struct tls_session *tls ) { size_t data_len = ntohs ( tls->rx_header.length ); + size_t remaining = data_len; + size_t frag_len; + struct io_buffer *iobuf; + struct io_buffer *tmp; + int rc; + + /* Allocate data buffers now that we know the length */ + assert ( list_empty ( &tls->rx_data ) ); + while ( remaining ) { + + /* Calculate fragment length. Ensure that no block is + * smaller than TLS_RX_MIN_BUFSIZE (by increasing the + * allocation length if necessary). + */ + frag_len = remaining; + if ( frag_len > TLS_RX_BUFSIZE ) + frag_len = TLS_RX_BUFSIZE; + remaining -= frag_len; + if ( remaining < TLS_RX_MIN_BUFSIZE ) { + frag_len += remaining; + remaining = 0; + } + + /* Allocate buffer */ + iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 ); + if ( ! iobuf ) { + DBGC ( tls, "TLS %p could not allocate %zd of %zd " + "bytes for receive buffer\n", tls, + remaining, data_len ); + rc = -ENOMEM_RX_DATA; + goto err; + } - /* 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; + /* Ensure tailroom is exactly what we asked for. This + * will result in unaligned I/O buffers when the + * fragment length is unaligned, which can happen only + * before we switch to using a block cipher. + */ + iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) ); + + /* Add I/O buffer to list */ + list_add_tail ( &iobuf->list, &tls->rx_data ); } /* Move to data state */ tls->rx_state = TLS_RX_DATA; return 0; + + err: + list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) { + list_del ( &iobuf->list ); + free_iob ( iobuf ); + } + return rc; } /** @@ -1539,22 +2320,31 @@ static int tls_newdata_process_header ( struct tls_session *tls ) { * @ret rc Returned status code */ static int tls_newdata_process_data ( struct tls_session *tls ) { + struct io_buffer *iobuf; int rc; + /* Move current buffer to end of list */ + iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list ); + list_del ( &iobuf->list ); + list_add_tail ( &iobuf->list, &tls->rx_data ); + + /* Continue receiving data if any space remains */ + iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list ); + if ( iob_tailroom ( iobuf ) ) + return 0; + /* Process record */ if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header, - tls->rx_data ) ) != 0 ) + &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 */ + assert ( list_empty ( &tls->rx_data ) ); tls->rx_state = TLS_RX_HEADER; + iob_unput ( &tls->rx_header_iobuf, sizeof ( tls->rx_header ) ); return 0; } @@ -1571,45 +2361,43 @@ 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 ); + struct io_buffer *dest; 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 ); + dest = &tls->rx_header_iobuf; process = tls_newdata_process_header; break; case TLS_RX_DATA: - buf = tls->rx_data; - buf_len = ntohs ( tls->rx_header.length ); + dest = list_first_entry ( &tls->rx_data, + struct io_buffer, list ); + assert ( dest != NULL ); process = tls_newdata_process_data; break; default: assert ( 0 ); - rc = -EINVAL; + rc = -EINVAL_RX_STATE; 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; + frag_len = iob_len ( iobuf ); + if ( frag_len > iob_tailroom ( dest ) ) + frag_len = iob_tailroom ( dest ); + memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len ); iob_pull ( iobuf, frag_len ); /* Process data if buffer is now full */ - if ( tls->rx_rcvd == buf_len ) { + if ( iob_tailroom ( dest ) == 0 ) { if ( ( rc = process ( tls ) ) != 0 ) { tls_close ( tls, rc ); goto done; } - tls->rx_rcvd = 0; } } rc = 0; @@ -1623,6 +2411,7 @@ static int tls_cipherstream_deliver ( struct tls_session *tls, 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 ), }; @@ -1631,6 +2420,79 @@ 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 @@ -1641,40 +2503,49 @@ static struct interface_descriptor tls_cipherstream_desc = /** * TLS TX state machine * - * @v process TLS process + * @v tls TLS session */ -static void tls_step ( struct process *process ) { - struct tls_session *tls = - container_of ( process, struct tls_session, process ); +static void tls_tx_step ( struct tls_session *tls ) { int rc; /* Wait for cipherstream to become ready */ if ( ! xfer_window ( &tls->cipherstream ) ) return; - switch ( tls->tx_state ) { - case TLS_TX_NONE: - /* Nothing to do */ - break; - case TLS_TX_CLIENT_HELLO: + /* 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_state = TLS_TX_NONE; - break; - case TLS_TX_CLIENT_KEY_EXCHANGE: + 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 send Client Key Exchange: " - "%s\n", tls, strerror ( rc ) ); + DBGC ( tls, "TLS %p could not send Client Key " + "Exchange: %s\n", tls, strerror ( rc ) ); goto err; } - tls->tx_state = TLS_TX_CHANGE_CIPHER; - break; - case TLS_TX_CHANGE_CIPHER: + 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: " @@ -1689,30 +2560,31 @@ static void tls_step ( struct process *process ) { goto err; } tls->tx_seq = 0; - tls->tx_state = TLS_TX_FINISHED; - break; - case TLS_TX_FINISHED: + 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_state = TLS_TX_NONE; - break; - case TLS_TX_DATA: - /* Nothing to do */ - break; - default: - assert ( 0 ); + 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 @@ -1720,35 +2592,60 @@ static void tls_step ( struct process *process ) { ****************************************************************************** */ -int add_tls ( struct interface *xfer, struct interface **next ) { +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 ) - return -ENOMEM; + 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 = 0; - tls_generate_random ( &tls->client_random.random, - ( sizeof ( tls->client_random.random ) ) ); - tls->pre_master_secret.version = htons ( TLS_VERSION_TLS_1_0 ); - tls_generate_random ( &tls->pre_master_secret.random, - ( sizeof ( tls->pre_master_secret.random ) ) ); - digest_init ( &md5_algorithm, tls->handshake_md5_ctx ); - digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx ); - tls->tx_state = TLS_TX_CLIENT_HELLO; - process_init ( &tls->process, tls_step, &tls->refcnt ); + 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; + iob_populate ( &tls->rx_header_iobuf, &tls->rx_header, 0, + sizeof ( tls->rx_header ) ); + INIT_LIST_HEAD ( &tls->rx_data ); + + /* Add pending operations for server and client Finished messages */ + pending_get ( &tls->client_negotiation ); + pending_get ( &tls->server_negotiation ); /* 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/roms/ipxe/src/net/udp.c b/roms/ipxe/src/net/udp.c index 5f452535c..20badb7f0 100644 --- a/roms/ipxe/src/net/udp.c +++ b/roms/ipxe/src/net/udp.c @@ -386,10 +386,9 @@ static int udp_xfer_deliver ( struct udp_connection *udp, struct xfer_metadata *meta ) { /* Transmit data, if possible */ - udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ), - ( ( struct sockaddr_tcpip * ) meta->dest ), meta->netdev ); - - return 0; + return udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ), + ( ( struct sockaddr_tcpip * ) meta->dest ), + meta->netdev ); } /** UDP data transfer interface operations */ diff --git a/roms/ipxe/src/net/udp/dhcp.c b/roms/ipxe/src/net/udp/dhcp.c index a0b74dfe5..e63c3e422 100644 --- a/roms/ipxe/src/net/udp/dhcp.c +++ b/roms/ipxe/src/net/udp/dhcp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -85,13 +86,11 @@ static uint8_t dhcp_request_options_data[] = { 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", @@ -116,6 +115,14 @@ struct setting use_cached_setting __setting ( SETTING_MISC ) = { .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 * @@ -137,23 +144,6 @@ static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) { } } -/** - * Calculate DHCP transaction ID for a network device - * - * @v netdev Network device - * @ret xid DHCP XID - * - * Extract the least significant bits of the hardware address for use - * as the transaction ID. - */ -static uint32_t dhcp_xid ( struct net_device *netdev ) { - uint32_t xid; - - memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len - - sizeof ( xid ) ), sizeof ( xid ) ); - return xid; -} - /**************************************************************************** * * DHCP session @@ -219,6 +209,8 @@ struct dhcp_session { 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; @@ -916,6 +908,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr, * @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 @@ -927,7 +920,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr, */ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, - const void *options, size_t options_len, + uint32_t xid, const void *options, size_t options_len, void *data, size_t max_len ) { struct dhcphdr *dhcphdr = data; int rc; @@ -938,14 +931,29 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, /* Initialise DHCP packet content */ memset ( dhcphdr, 0, max_len ); - dhcphdr->xid = dhcp_xid ( netdev ); + 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 ); + dhcphdr->hlen = netdev->ll_protocol->ll_addr_len; + memcpy ( dhcphdr->chaddr, netdev->ll_addr, + netdev->ll_protocol->ll_addr_len ); memcpy ( dhcphdr->options, options, options_len ); + /* If the local link-layer address functions only as a name + * (i.e. cannot be used as a destination address), then + * request broadcast responses. + */ + if ( netdev->ll_protocol->flags & LL_NAME_ONLY ) + dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST ); + + /* If the network device already has an IPv4 address then + * unicast responses from the DHCP server may be rejected, so + * request broadcast responses. + */ + if ( ipv4_has_any_addr ( netdev ) ) + dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST ); + /* Initialise DHCP packet structure */ memset ( dhcppkt, 0, sizeof ( *dhcppkt ) ); dhcppkt_init ( dhcppkt, data, max_len ); @@ -964,6 +972,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, * @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 @@ -974,7 +983,8 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, */ int dhcp_create_request ( struct dhcp_packet *dhcppkt, struct net_device *netdev, unsigned int msgtype, - struct in_addr ciaddr, void *data, size_t max_len ) { + 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; @@ -985,7 +995,7 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt, int rc; /* Create DHCP packet */ - if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, + if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid, dhcp_request_options_data, sizeof ( dhcp_request_options_data ), data, max_len ) ) != 0 ) { @@ -1099,7 +1109,8 @@ static int dhcp_tx ( struct dhcp_session *dhcp ) { /* Create basic DHCP packet in temporary buffer */ if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype, - dhcp->local.sin_addr, iobuf->data, + 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 ) ); @@ -1187,7 +1198,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp, &server_id, sizeof ( server_id ) ); /* Check for matching transaction ID */ - if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) { + 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 ), @@ -1311,6 +1322,10 @@ int start_dhcp ( struct interface *job, struct net_device *netdev ) { 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, diff --git a/roms/ipxe/src/net/udp/dns.c b/roms/ipxe/src/net/udp/dns.c index d1435e769..613541f5a 100644 --- a/roms/ipxe/src/net/udp/dns.c +++ b/roms/ipxe/src/net/udp/dns.c @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -222,18 +223,24 @@ static char * dns_qualify_name ( const char *string ) { * DNS names consist of "<length>element" pairs. */ static char * dns_make_name ( const char *string, char *buf ) { - char *length_byte = buf++; + char *length_byte; char c; - while ( ( c = *(string++) ) ) { - if ( c == '.' ) { - *length_byte = buf - length_byte - 1; - length_byte = buf; + 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)++; } - *(buf++) = c; - } - *length_byte = buf - length_byte - 1; - *(buf++) = '\0'; + } while ( c ); + return buf; } @@ -421,7 +428,7 @@ static int dns_xfer_deliver ( struct dns_request *dns, } /* Determine what to do next based on the type of query we - * issued and the reponse we received + * issued and the response we received */ switch ( qtype ) { @@ -594,14 +601,6 @@ struct setting dns_setting __setting ( SETTING_IPv4_EXTRA ) = { .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 * diff --git a/roms/ipxe/src/net/udp/slam.c b/roms/ipxe/src/net/udp/slam.c index 0de138cdf..e1b584fec 100644 --- a/roms/ipxe/src/net/udp/slam.c +++ b/roms/ipxe/src/net/udp/slam.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/net/udp/syslog.c b/roms/ipxe/src/net/udp/syslog.c index 6d9fc2165..00101008b 100644 --- a/roms/ipxe/src/net/udp/syslog.c +++ b/roms/ipxe/src/net/udp/syslog.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -25,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include <stdint.h> +#include <stdlib.h> #include <byteswap.h> #include <ipxe/xfer.h> #include <ipxe/open.h> @@ -32,11 +34,19 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/dhcp.h> #include <ipxe/settings.h> #include <ipxe/console.h> -#include <ipxe/ansiesc.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 ), }; @@ -50,6 +60,41 @@ static struct interface_descriptor syslogger_desc = /** The syslog UDP interface */ static struct interface syslogger = INTF_INIT ( syslogger_desc ); +/****************************************************************************** + * + * Console driver + * + ****************************************************************************** + */ + +/** Host name (for log messages) */ +static char *syslog_hostname; + +/** Domain name (for log messages) */ +static char *syslog_domain; + +/** + * Transmit formatted syslog message + * + * @v xfer Data transfer interface + * @v severity Severity + * @v message Message + * @v terminator Message terminator + * @ret rc Return status code + */ +int syslog_send ( struct interface *xfer, unsigned int severity, + const char *message, const char *terminator ) { + + return xfer_printf ( xfer, "<%d>%s%s%s%sipxe: %s%s", + SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY, + severity ), + ( syslog_hostname ? syslog_hostname : "" ), + ( syslog_domain ? "." : "" ), + ( syslog_domain ? syslog_domain : "" ), + ( ( syslog_hostname || syslog_domain ) ? " " : ""), + message, terminator ); +} + /****************************************************************************** * * Console driver @@ -60,22 +105,42 @@ static struct interface syslogger = INTF_INIT ( syslogger_desc ); /** Syslog line buffer */ static char syslog_buffer[SYSLOG_BUFSIZE]; -/** Index into syslog line buffer */ -static unsigned int syslog_idx; +/** Syslog severity */ +static unsigned int syslog_severity = SYSLOG_DEFAULT_SEVERITY; -/** Syslog recursion marker */ -static int syslog_entered; +/** + * 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_ansiesc_handlers[] = { +static struct ansiesc_handler syslog_handlers[] = { + { ANSIESC_LOG_PRIORITY, syslog_handle_priority }, { 0, NULL } }; -/** Syslog ANSI escape sequence context */ -static struct ansiesc_context syslog_ansiesc_ctx = { - .handlers = syslog_ansiesc_handlers, +/** 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 * @@ -84,47 +149,20 @@ static struct ansiesc_context syslog_ansiesc_ctx = { static void syslog_putchar ( int character ) { int rc; - /* Do nothing if we have no log server */ - if ( ! logserver.st_family ) - return; - /* Ignore if we are already mid-logging */ if ( syslog_entered ) return; - /* Strip ANSI escape sequences */ - character = ansiesc_process ( &syslog_ansiesc_ctx, character ); - if ( character < 0 ) - return; - - /* Ignore carriage return */ - if ( character == '\r' ) + /* Fill line buffer */ + if ( line_putchar ( &syslog_line, character ) == 0 ) return; - /* Treat newline as a terminator */ - if ( character == '\n' ) - character = 0; - - /* Add character to buffer */ - syslog_buffer[syslog_idx++] = character; - - /* Do nothing more unless we reach end-of-line (or end-of-buffer) */ - if ( ( character != 0 ) && - ( syslog_idx < ( sizeof ( syslog_buffer ) - 1 /* NUL */ ) ) ) { - return; - } - - /* Reset to start of buffer */ - syslog_idx = 0; - /* Guard against re-entry */ syslog_entered = 1; /* Send log message */ - if ( ( rc = xfer_printf ( &syslogger, "<%d>ipxe: %s", - SYSLOG_PRIORITY ( SYSLOG_FACILITY, - SYSLOG_SEVERITY ), - syslog_buffer ) ) != 0 ) { + if ( ( rc = syslog_send ( &syslogger, syslog_severity, + syslog_buffer, "" ) ) != 0 ) { DBG ( "SYSLOG could not send log message: %s\n", strerror ( rc ) ); } @@ -136,6 +174,8 @@ static void syslog_putchar ( int character ) { /** Syslog console driver */ struct console_driver syslog_console __console_driver = { .putchar = syslog_putchar, + .disabled = 1, + .usage = CONSOLE_SYSLOG, }; /****************************************************************************** @@ -165,12 +205,26 @@ static int apply_syslog_settings ( void ) { int len; int rc; + /* Fetch hostname and domain name */ + free ( syslog_hostname ); + if ( ( len = fetch_string_setting_copy ( NULL, &hostname_setting, + &syslog_hostname ) ) < 0 ) { + rc = len; + DBG ( "SYSLOG could not fetch hostname: %s\n", strerror ( rc )); + } + free ( syslog_domain ); + if ( ( len = fetch_string_setting_copy ( NULL, &domain_setting, + &syslog_domain ) ) < 0 ) { + rc = len; + DBG ( "SYSLOG could not fetch domain: %s\n", strerror ( rc ) ); + } + /* Fetch log server */ + syslog_console.disabled = 1; old_addr.s_addr = sin_logserver->sin_addr.s_addr; - logserver.st_family = 0; if ( ( len = fetch_ipv4_setting ( NULL, &syslog_setting, &sin_logserver->sin_addr ) ) >= 0 ) { - sin_logserver->sin_family = AF_INET; + syslog_console.disabled = 0; } /* Do nothing unless log server has changed */ @@ -181,7 +235,7 @@ static int apply_syslog_settings ( void ) { intf_restart ( &syslogger, 0 ); /* Do nothing unless we have a log server */ - if ( ! logserver.st_family ) { + if ( syslog_console.disabled ) { DBG ( "SYSLOG has no log server\n" ); return 0; } diff --git a/roms/ipxe/src/net/udp/tftp.c b/roms/ipxe/src/net/udp/tftp.c index 7cd211e41..a6c64b4ab 100644 --- a/roms/ipxe/src/net/udp/tftp.c +++ b/roms/ipxe/src/net/udp/tftp.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -1214,14 +1215,6 @@ struct uri_opener mtftp_uri_opener __uri_opener = { ****************************************************************************** */ -/** 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, -}; - /** * Apply TFTP configuration settings * diff --git a/roms/ipxe/src/net/validator.c b/roms/ipxe/src/net/validator.c new file mode 100644 index 000000000..d61cb92f4 --- /dev/null +++ b/roms/ipxe/src/net/validator.c @@ -0,0 +1,576 @@ +/* + * 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. + */ + +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/ocsp.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; + /** OCSP check */ + struct ocsp_check *ocsp; + /** Data buffer */ + struct xfer_buffer buffer; + /** Action to take upon completed transfer */ + int ( * done ) ( struct validator *validator, const void *data, + size_t len ); +}; + +/** + * 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 ); + ocsp_put ( validator->ocsp ); + 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"; + +/** + * 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; +} + +/** + * 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 ); + + /* Set completion handler */ + validator->done = validator_append; + + /* 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; +} + +/**************************************************************************** + * + * OCSP checks + * + */ + +/** + * Validate OCSP response + * + * @v validator Certificate validator + * @v data Raw OCSP response + * @v len Length of raw data + * @ret rc Return status code + */ +static int validator_ocsp_validate ( struct validator *validator, + const void *data, size_t len ) { + time_t now; + int rc; + + /* Record OCSP response */ + if ( ( rc = ocsp_response ( validator->ocsp, data, len ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not record OCSP " + "response: %s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Validate OCSP response */ + now = time ( NULL ); + if ( ( rc = ocsp_validate ( validator->ocsp, now ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not validate OCSP " + "response: %s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Drop reference to OCSP check */ + ocsp_put ( validator->ocsp ); + validator->ocsp = NULL; + + return 0; +} + +/** + * Start OCSP check + * + * @v validator Certificate validator + * @v cert Certificate to check + * @v issuer Issuing certificate + * @ret rc Return status code + */ +static int validator_start_ocsp ( struct validator *validator, + struct x509_certificate *cert, + struct x509_certificate *issuer ) { + const char *uri_string; + int rc; + + /* Create OCSP check */ + assert ( validator->ocsp == NULL ); + if ( ( rc = ocsp_check ( cert, issuer, &validator->ocsp ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not create OCSP check: " + "%s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Set completion handler */ + validator->done = validator_ocsp_validate; + + /* Open URI */ + uri_string = validator->ocsp->uri_string; + DBGC ( validator, "VALIDATOR %p performing OCSP check at %s\n", + validator, uri_string ); + 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 ) ); + return rc; + } + + return 0; +} + +/**************************************************************************** + * + * 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 transfer failed: %s\n", + validator, strerror ( rc ) ); + goto err_transfer; + } + DBGC2 ( validator, "VALIDATOR %p transfer complete\n", validator ); + + /* Process completed download */ + assert ( validator->done != NULL ); + if ( ( rc = validator->done ( 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_transfer: + 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_link *link; + struct x509_certificate *cert; + struct x509_certificate *issuer = NULL; + struct x509_certificate *last; + 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 there is a certificate that could be validated using + * OCSP, try it. + */ + list_for_each_entry ( link, &validator->chain->links, list ) { + cert = issuer; + issuer = link->cert; + if ( ! cert ) + continue; + if ( ! issuer->valid ) + continue; + /* The issuer is valid, but this certificate is not + * yet valid. If OCSP is applicable, start it. + */ + if ( cert->extensions.auth_info.ocsp.uri && + ( ! cert->extensions.auth_info.ocsp.good ) ) { + /* Start OCSP */ + if ( ( rc = validator_start_ocsp ( validator, cert, + issuer ) ) != 0 ) { + validator_finished ( validator, rc ); + return; + } + return; + } + /* Otherwise, this is a permanent failure */ + validator_finished ( validator, rc ); + return; + } + + /* If chain ends with a self-issued certificate, then there is + * nothing more to do. + */ + last = x509_last ( validator->chain ); + 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/roms/ipxe/src/net/vlan.c b/roms/ipxe/src/net/vlan.c index 9ac560f1e..f7281f5d7 100644 --- a/roms/ipxe/src/net/vlan.c +++ b/roms/ipxe/src/net/vlan.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -91,12 +92,13 @@ static int vlan_transmit ( struct net_device *netdev, 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 ) ) != 0 ) { + &net_proto, &flags ) ) != 0 ) { DBGC ( netdev, "VLAN %s could not parse link-layer header: " "%s\n", netdev->name, strerror ( rc ) ); return rc; @@ -214,10 +216,12 @@ struct net_device * vlan_find ( struct net_device *trunk, unsigned int tag ) { * @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 ) { + 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; diff --git a/roms/ipxe/src/tests/aes_cbc_test.c b/roms/ipxe/src/tests/aes_cbc_test.c new file mode 100644 index 000000000..4ae3a92e5 --- /dev/null +++ b/roms/ipxe/src/tests/aes_cbc_test.c @@ -0,0 +1,193 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 ) { + struct cipher_algorithm *cipher = &aes_cbc_algorithm; + + /* Correctness tests */ + aes_cbc_ok ( &test_128 ); + aes_cbc_ok ( &test_256 ); + + /* Speed tests */ + DBG ( "AES128 encryption required %ld cycles per byte\n", + cbc_cost_encrypt ( cipher, test_128.key_len ) ); + DBG ( "AES128 decryption required %ld cycles per byte\n", + cbc_cost_decrypt ( cipher, test_128.key_len ) ); + DBG ( "AES256 encryption required %ld cycles per byte\n", + cbc_cost_encrypt ( cipher, test_256.key_len ) ); + DBG ( "AES256 decryption required %ld cycles per byte\n", + cbc_cost_decrypt ( cipher, test_256.key_len ) ); +} + +/** 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/roms/ipxe/src/tests/base64_test.c b/roms/ipxe/src/tests/base64_test.c new file mode 100644 index 000000000..c088298ca --- /dev/null +++ b/roms/ipxe/src/tests/base64_test.c @@ -0,0 +1,124 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Base64 tests + * + * Test vectors generated using "base64 -w 0" + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <string.h> +#include <ipxe/base64.h> +#include <ipxe/test.h> + +/** A Base64 test */ +struct base64_test { + /** Raw data */ + const void *data; + /** Length of raw data */ + size_t len; + /** Base64-encoded data */ + const char *encoded; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a base64 test */ +#define BASE64( name, DATA, ENCODED ) \ + static const uint8_t name ## _data[] = DATA; \ + static struct base64_test name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + .encoded = ENCODED, \ + } + +/** Empty data test */ +BASE64 ( empty_test, DATA(), "" ); + +/** "Hello world" test */ +BASE64 ( hw_test, + DATA ( 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' ), + "SGVsbG8gd29ybGQ=" ); + +/** Random data test */ +BASE64 ( random_test, + DATA ( 0x36, 0x03, 0x84, 0xdc, 0x4e, 0x03, 0x46, 0xa0, 0xb5, 0x2d, + 0x03, 0x6e, 0xd0, 0x56, 0xed, 0xa0, 0x37, 0x02, 0xac, 0xc6, + 0x65, 0xd1 ), + "NgOE3E4DRqC1LQNu0FbtoDcCrMZl0Q==" ); + +/** + * Report a base64 encoding test result + * + * @v test Base64 test + */ +#define base64_encode_ok( test ) do { \ + size_t len = base64_encoded_len ( (test)->len ); \ + char buf[ len + 1 /* NUL */ ]; \ + ok ( len == strlen ( (test)->encoded ) ); \ + base64_encode ( (test)->data, (test)->len, buf ); \ + ok ( strcmp ( (test)->encoded, buf ) == 0 ); \ + } while ( 0 ) + +/** + * Report a base64 decoding test result + * + * @v test Base64 test + */ +#define base64_decode_ok( test ) do { \ + size_t max_len = base64_decoded_max_len ( (test)->encoded ); \ + uint8_t buf[max_len]; \ + int len; \ + len = base64_decode ( (test)->encoded, buf ); \ + ok ( len >= 0 ); \ + ok ( ( size_t ) len <= max_len ); \ + ok ( ( size_t ) len == (test)->len ); \ + ok ( memcmp ( (test)->data, buf, len ) == 0 ); \ + } while ( 0 ) + +/** + * Perform Base64 self-tests + * + */ +static void base64_test_exec ( void ) { + + base64_encode_ok ( &empty_test ); + base64_decode_ok ( &empty_test ); + + base64_encode_ok ( &hw_test ); + base64_decode_ok ( &hw_test ); + + base64_encode_ok ( &random_test ); + base64_decode_ok ( &random_test ); +} + +/** Base64 self-test */ +struct self_test base64_test __self_test = { + .name = "base64", + .exec = base64_test_exec, +}; diff --git a/roms/ipxe/src/tests/bigint_test.c b/roms/ipxe/src/tests/bigint_test.c new file mode 100644 index 000000000..75a80622f --- /dev/null +++ b/roms/ipxe/src/tests/bigint_test.c @@ -0,0 +1,2437 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/bofm_test.c b/roms/ipxe/src/tests/bofm_test.c index 6f2e6c673..e430d12d4 100644 --- a/roms/ipxe/src/tests/bofm_test.c +++ b/roms/ipxe/src/tests/bofm_test.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/tests/byteswap_test.c b/roms/ipxe/src/tests/byteswap_test.c new file mode 100644 index 000000000..a500218be --- /dev/null +++ b/roms/ipxe/src/tests/byteswap_test.c @@ -0,0 +1,92 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/cbc_test.c b/roms/ipxe/src/tests/cbc_test.c new file mode 100644 index 000000000..ada991b21 --- /dev/null +++ b/roms/ipxe/src/tests/cbc_test.c @@ -0,0 +1,171 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * CBC self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ipxe/crypto.h> +#include <ipxe/profile.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 ); +} + +/** + * Calculate CBC encryption or decryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @v op Encryption or decryption operation + * @ret cost Cost (in cycles per byte) + */ +static unsigned long cbc_cost ( struct cipher_algorithm *cipher, + size_t key_len, + void ( * op ) ( struct cipher_algorithm *cipher, + void *ctx, const void *src, + void *dst, size_t len ) ) { + static uint8_t random[8192]; /* Too large for stack */ + uint8_t key[key_len]; + uint8_t iv[cipher->blocksize]; + uint8_t ctx[cipher->ctxsize]; + union profiler profiler; + unsigned long long elapsed; + unsigned long cost; + unsigned int i; + int rc; + + /* Fill buffer with pseudo-random data */ + srand ( 0x1234568 ); + for ( i = 0 ; i < sizeof ( random ) ; i++ ) + random[i] = rand(); + for ( i = 0 ; i < sizeof ( key ) ; i++ ) + key[i] = rand(); + for ( i = 0 ; i < sizeof ( iv ) ; i++ ) + iv[i] = rand(); + + /* Initialise cipher */ + rc = cipher_setkey ( cipher, ctx, key, key_len ); + assert ( rc == 0 ); + cipher_setiv ( cipher, ctx, iv ); + + /* Time operation */ + profile ( &profiler ); + op ( cipher, ctx, random, random, sizeof ( random ) ); + elapsed = profile ( &profiler ); + + /* Round to nearest whole number of cycles per byte */ + cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) ); + + return cost; +} + +/** + * Calculate CBC encryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @ret cost Cost (in cycles per byte) + */ +unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cbc_cost ( cipher, key_len, cipher_encrypt ); +} + +/** + * Calculate CBC decryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @ret cost Cost (in cycles per byte) + */ +unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cbc_cost ( cipher, key_len, cipher_decrypt ); +} diff --git a/roms/ipxe/src/tests/cbc_test.h b/roms/ipxe/src/tests/cbc_test.h new file mode 100644 index 000000000..ad9e6f341 --- /dev/null +++ b/roms/ipxe/src/tests/cbc_test.h @@ -0,0 +1,57 @@ +#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 ); +extern unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ); +extern unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_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/roms/ipxe/src/tests/cms_test.c b/roms/ipxe/src/tests/cms_test.c new file mode 100644 index 000000000..9899b06aa --- /dev/null +++ b/roms/ipxe/src/tests/cms_test.c @@ -0,0 +1,1438 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/crc32_test.c b/roms/ipxe/src/tests/crc32_test.c new file mode 100644 index 000000000..873f633a5 --- /dev/null +++ b/roms/ipxe/src/tests/crc32_test.c @@ -0,0 +1,116 @@ +/* + * 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. + */ + +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/roms/ipxe/src/tests/digest_test.c b/roms/ipxe/src/tests/digest_test.c new file mode 100644 index 000000000..6428cc728 --- /dev/null +++ b/roms/ipxe/src/tests/digest_test.c @@ -0,0 +1,105 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Digest self-tests + * + */ + +#include <stdlib.h> +#include <string.h> +#include <ipxe/crypto.h> +#include <ipxe/profile.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 ); +} + +/** + * Calculate digest algorithm cost + * + * @v digest Digest algorithm + * @ret cost Cost (in cycles per byte) + */ +unsigned long digest_cost ( struct digest_algorithm *digest ) { + static uint8_t random[8192]; /* Too large for stack */ + uint8_t ctx[digest->ctxsize]; + uint8_t out[digest->digestsize]; + union profiler profiler; + unsigned long long elapsed; + unsigned long cost; + unsigned int i; + + /* Fill buffer with pseudo-random data */ + srand ( 0x1234568 ); + for ( i = 0 ; i < sizeof ( random ) ; i++ ) + random[i] = rand(); + + /* Time digest calculation */ + profile ( &profiler ); + digest_init ( digest, ctx ); + digest_update ( digest, ctx, random, sizeof ( random ) ); + digest_final ( digest, ctx, out ); + elapsed = profile ( &profiler ); + + /* Round to nearest whole number of cycles per byte */ + cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) ); + + return cost; +} diff --git a/roms/ipxe/src/tests/digest_test.h b/roms/ipxe/src/tests/digest_test.h new file mode 100644 index 000000000..49e06d1cb --- /dev/null +++ b/roms/ipxe/src/tests/digest_test.h @@ -0,0 +1,37 @@ +#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 ); +extern unsigned long digest_cost ( struct digest_algorithm *digest ); + +/** + * 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/roms/ipxe/src/tests/entropy_sample.c b/roms/ipxe/src/tests/entropy_sample.c new file mode 100644 index 000000000..95a662e3e --- /dev/null +++ b/roms/ipxe/src/tests/entropy_sample.c @@ -0,0 +1,72 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/hash_df_test.c b/roms/ipxe/src/tests/hash_df_test.c new file mode 100644 index 000000000..74c8d0f4d --- /dev/null +++ b/roms/ipxe/src/tests/hash_df_test.c @@ -0,0 +1,898 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/hmac_drbg_test.c b/roms/ipxe/src/tests/hmac_drbg_test.c new file mode 100644 index 000000000..8cbf1cc8b --- /dev/null +++ b/roms/ipxe/src/tests/hmac_drbg_test.c @@ -0,0 +1,1386 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/list_test.c b/roms/ipxe/src/tests/list_test.c new file mode 100644 index 000000000..35cbd5e5f --- /dev/null +++ b/roms/ipxe/src/tests/list_test.c @@ -0,0 +1,483 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/md5_test.c b/roms/ipxe/src/tests/md5_test.c new file mode 100644 index 000000000..ba5f24c3e --- /dev/null +++ b/roms/ipxe/src/tests/md5_test.c @@ -0,0 +1,100 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 long cost; + unsigned int i; + unsigned int j; + + /* Correctness test */ + 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 ); + } + } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "MD5 required %ld cycles per byte\n", cost ); +} + +/** MD5 self-test */ +struct self_test md5_test __self_test = { + .name = "md5", + .exec = md5_test_exec, +}; diff --git a/roms/ipxe/src/tests/memcpy_test.c b/roms/ipxe/src/tests/memcpy_test.c index 7626e6398..b405a9f2f 100644 --- a/roms/ipxe/src/tests/memcpy_test.c +++ b/roms/ipxe/src/tests/memcpy_test.c @@ -1,39 +1,261 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * memcpy() self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> #include <string.h> +#include <ipxe/test.h> +#include <ipxe/profile.h> -/* - * This file exists for testing the compilation of memcpy() with the - * various constant-length optimisations. +/* Provide global functions to allow inspection of generated code */ + +void memcpy_0 ( void *dest, void *src ) { memcpy ( dest, src, 0 ); } +void memcpy_1 ( void *dest, void *src ) { memcpy ( dest, src, 1 ); } +void memcpy_2 ( void *dest, void *src ) { memcpy ( dest, src, 2 ); } +void memcpy_3 ( void *dest, void *src ) { memcpy ( dest, src, 3 ); } +void memcpy_4 ( void *dest, void *src ) { memcpy ( dest, src, 4 ); } +void memcpy_5 ( void *dest, void *src ) { memcpy ( dest, src, 5 ); } +void memcpy_6 ( void *dest, void *src ) { memcpy ( dest, src, 6 ); } +void memcpy_7 ( void *dest, void *src ) { memcpy ( dest, src, 7 ); } +void memcpy_8 ( void *dest, void *src ) { memcpy ( dest, src, 8 ); } +void memcpy_9 ( void *dest, void *src ) { memcpy ( dest, src, 9 ); } +void memcpy_10 ( void *dest, void *src ) { memcpy ( dest, src, 10 ); } +void memcpy_11 ( void *dest, void *src ) { memcpy ( dest, src, 11 ); } +void memcpy_12 ( void *dest, void *src ) { memcpy ( dest, src, 12 ); } +void memcpy_13 ( void *dest, void *src ) { memcpy ( dest, src, 13 ); } +void memcpy_14 ( void *dest, void *src ) { memcpy ( dest, src, 14 ); } +void memcpy_15 ( void *dest, void *src ) { memcpy ( dest, src, 15 ); } +void memcpy_16 ( void *dest, void *src ) { memcpy ( dest, src, 16 ); } +void memcpy_17 ( void *dest, void *src ) { memcpy ( dest, src, 17 ); } +void memcpy_18 ( void *dest, void *src ) { memcpy ( dest, src, 18 ); } +void memcpy_19 ( void *dest, void *src ) { memcpy ( dest, src, 19 ); } +void memcpy_20 ( void *dest, void *src ) { memcpy ( dest, src, 20 ); } +void memcpy_21 ( void *dest, void *src ) { memcpy ( dest, src, 21 ); } +void memcpy_22 ( void *dest, void *src ) { memcpy ( dest, src, 22 ); } +void memcpy_23 ( void *dest, void *src ) { memcpy ( dest, src, 23 ); } +void memcpy_24 ( void *dest, void *src ) { memcpy ( dest, src, 24 ); } +void memcpy_25 ( void *dest, void *src ) { memcpy ( dest, src, 25 ); } +void memcpy_26 ( void *dest, void *src ) { memcpy ( dest, src, 26 ); } +void memcpy_27 ( void *dest, void *src ) { memcpy ( dest, src, 27 ); } +void memcpy_28 ( void *dest, void *src ) { memcpy ( dest, src, 28 ); } +void memcpy_29 ( void *dest, void *src ) { memcpy ( dest, src, 29 ); } +void memcpy_30 ( void *dest, void *src ) { memcpy ( dest, src, 30 ); } +void memcpy_31 ( void *dest, void *src ) { memcpy ( dest, src, 31 ); } + +/** + * Force a call to the variable-length implementation of memcpy() + * + * @v dest Destination address + * @v src Source address + * @v len Length of data + * @ret dest Destination address + */ +__attribute__ (( noinline )) void * memcpy_var ( void *dest, const void *src, + size_t len ) { + return memcpy ( dest, src, len ); +} + +/** + * Perform a constant-length memcpy() test + * + * ... Data to copy + */ +#define MEMCPY_TEST_CONSTANT( ... ) do { \ + static const uint8_t src[] = { __VA_ARGS__ }; \ + uint8_t dest_const[ 1 + sizeof ( src ) + 1 ]; \ + uint8_t dest_var[ 1 + sizeof ( src ) + 1 ]; \ + \ + dest_const[0] = 0x33; \ + dest_const[ sizeof ( dest_const ) - 1 ] = 0x44; \ + memcpy ( ( dest_const + 1 ), src, \ + ( sizeof ( dest_const ) - 2 ) ); \ + ok ( dest_const[0] == 0x33 ); \ + ok ( dest_const[ sizeof ( dest_const ) - 1 ] == 0x44 ); \ + ok ( memcmp ( ( dest_const + 1 ), src, \ + ( sizeof ( dest_const ) - 2 ) ) == 0 ); \ + \ + dest_var[0] = 0x55; \ + dest_var[ sizeof ( dest_var ) - 1 ] = 0x66; \ + memcpy_var ( ( dest_var + 1 ), src, \ + ( sizeof ( dest_var ) - 2 ) ); \ + ok ( dest_var[0] == 0x55 ); \ + ok ( dest_var[ sizeof ( dest_var ) - 1 ] == 0x66 ); \ + ok ( memcmp ( ( dest_var + 1 ), src, \ + ( sizeof ( dest_var ) - 2 ) ) == 0 ); \ + } while ( 0 ) + +/** + * Test memcpy() speed + * + * @v dest_offset Destination alignment offset + * @v src_offset Source alignment offset + * @v len Length of data to copy + */ +static void memcpy_test_speed ( unsigned int dest_offset, + unsigned int src_offset, size_t len ) { + uint8_t *dest; + uint8_t *src; + unsigned int i; + unsigned long elapsed; + + /* Allocate blocks */ + dest = malloc ( len + dest_offset ); + assert ( dest != NULL ); + src = malloc ( len + src_offset ); + assert ( src != NULL ); + + /* Generate random source data */ + for ( i = 0 ; i < len ; i++ ) + src[ src_offset + i ] = random(); + + /* Perform memcpy() */ + simple_profile(); + memcpy ( ( dest + dest_offset ), ( src + src_offset ), len ); + elapsed = simple_profile(); + + /* Check copied data */ + ok ( memcmp ( ( dest + dest_offset ), ( src + src_offset ), + len ) == 0 ); + + /* Free blocks */ + free ( dest ); + free ( src ); + + DBG ( "MEMCPY copied %zd bytes (+%d => +%d) in %ld ticks\n", + len, src_offset, dest_offset, elapsed ); +} + +/** + * Perform memcpy() self-tests * */ +static void memcpy_test_exec ( void ) { + unsigned int dest_offset; + unsigned int src_offset; + + /* Constant-length tests */ + MEMCPY_TEST_CONSTANT ( ); + MEMCPY_TEST_CONSTANT ( 0x86 ); + MEMCPY_TEST_CONSTANT ( 0x8c, 0xd3 ); + MEMCPY_TEST_CONSTANT ( 0x4e, 0x08, 0xed ); + MEMCPY_TEST_CONSTANT ( 0xcc, 0x61, 0x8f, 0x70 ); + MEMCPY_TEST_CONSTANT ( 0x6d, 0x28, 0xe0, 0x9e, 0x6d ); + MEMCPY_TEST_CONSTANT ( 0x7d, 0x13, 0x4f, 0xef, 0x17, 0xb3 ); + MEMCPY_TEST_CONSTANT ( 0x38, 0xa7, 0xd4, 0x8d, 0x44, 0x01, 0xfd ); + MEMCPY_TEST_CONSTANT ( 0x45, 0x9f, 0xf4, 0xf9, 0xf3, 0x0f, 0x99, 0x43 ); + MEMCPY_TEST_CONSTANT ( 0x69, 0x8c, 0xf6, 0x12, 0x79, 0x70, 0xd8, 0x1e, + 0x9d ); + MEMCPY_TEST_CONSTANT ( 0xbe, 0x53, 0xb4, 0xb7, 0xdd, 0xe6, 0x35, 0x10, + 0x3c, 0xe7 ); + MEMCPY_TEST_CONSTANT ( 0xaf, 0x41, 0x8a, 0x88, 0xb1, 0x4e, 0x52, 0xd4, + 0xe6, 0xc3, 0x76 ); + MEMCPY_TEST_CONSTANT ( 0xdf, 0x43, 0xe4, 0x5d, 0xad, 0x17, 0x35, 0x38, + 0x1a, 0x1d, 0x57, 0x58 ); + MEMCPY_TEST_CONSTANT ( 0x20, 0x52, 0x83, 0x92, 0xb9, 0x85, 0xa4, 0x06, + 0x94, 0xe0, 0x3d, 0x57, 0xd4 ); + MEMCPY_TEST_CONSTANT ( 0xf1, 0x67, 0x31, 0x9e, 0x32, 0x98, 0x27, 0xe9, + 0x8e, 0x62, 0xb4, 0x82, 0x7e, 0x02 ); + MEMCPY_TEST_CONSTANT ( 0x93, 0xc1, 0x55, 0xe3, 0x60, 0xce, 0xac, 0x1e, + 0xae, 0x9d, 0xca, 0xec, 0x92, 0xb3, 0x38 ); + MEMCPY_TEST_CONSTANT ( 0xb3, 0xc1, 0xfa, 0xe7, 0x8a, 0x1c, 0xe4, 0xce, + 0x85, 0xe6, 0x3c, 0xab, 0x1c, 0xa2, 0xaf, 0x7a ); + MEMCPY_TEST_CONSTANT ( 0x9b, 0x6e, 0x1c, 0x48, 0x82, 0xd3, 0x6e, 0x58, + 0xa7, 0xb0, 0xe6, 0xea, 0x6d, 0xee, 0xc8, 0xf8, + 0xaf ); + MEMCPY_TEST_CONSTANT ( 0x86, 0x6d, 0xb0, 0xf5, 0xf2, 0xc9, 0xcd, 0xfe, + 0xfb, 0x38, 0x67, 0xbc, 0x51, 0x9d, 0x25, 0xbc, + 0x09, 0x88 ); + MEMCPY_TEST_CONSTANT ( 0x58, 0xa4, 0x96, 0x9e, 0x98, 0x36, 0xdb, 0xae, + 0x8a, 0x08, 0x7c, 0x64, 0xf9, 0xfb, 0x25, 0xb4, + 0x8e, 0xf3, 0xed ); + MEMCPY_TEST_CONSTANT ( 0xc6, 0x3b, 0x84, 0x3c, 0x76, 0x24, 0x8e, 0x42, + 0x11, 0x1f, 0x09, 0x2e, 0x24, 0xbb, 0x67, 0x71, + 0x3a, 0xca, 0x60, 0xdd ); + MEMCPY_TEST_CONSTANT ( 0x8e, 0x2d, 0xa9, 0x58, 0x87, 0xe2, 0xac, 0x4b, + 0xc8, 0xbf, 0xa2, 0x4e, 0xee, 0x3a, 0xa6, 0x71, + 0x76, 0xee, 0x42, 0x05, 0x6e ); + MEMCPY_TEST_CONSTANT ( 0x8a, 0xda, 0xdf, 0x7b, 0x55, 0x41, 0x8c, 0xcd, + 0x42, 0x40, 0x18, 0xe2, 0x60, 0xc4, 0x7d, 0x64, + 0x00, 0xd5, 0xef, 0xa1, 0x7b, 0x31 ); + MEMCPY_TEST_CONSTANT ( 0xd9, 0x25, 0xcb, 0xbb, 0x9c, 0x1d, 0xdd, 0xcd, + 0xde, 0x96, 0xd9, 0x74, 0x13, 0x95, 0xfe, 0x68, + 0x0b, 0x3d, 0x30, 0x8d, 0x0c, 0x1e, 0x6d ); + MEMCPY_TEST_CONSTANT ( 0x2d, 0x0d, 0x02, 0x33, 0xd6, 0xbe, 0x6c, 0xa6, + 0x0a, 0xab, 0xe5, 0xda, 0xe2, 0xab, 0x78, 0x3c, + 0xd3, 0xdd, 0xea, 0xfa, 0x1a, 0xe4, 0xf4, 0xb3 ); + MEMCPY_TEST_CONSTANT ( 0x6a, 0x34, 0x39, 0xea, 0x29, 0x5f, 0xa6, 0x18, + 0xc1, 0x53, 0x39, 0x78, 0xdb, 0x40, 0xf2, 0x98, + 0x78, 0xcf, 0xee, 0xfd, 0xcd, 0xf8, 0x56, 0xf8, + 0x30 ); + MEMCPY_TEST_CONSTANT ( 0xe4, 0xe5, 0x5a, 0x8d, 0xcf, 0x04, 0x29, 0x7c, + 0xa7, 0xd8, 0x43, 0xbf, 0x0b, 0xbf, 0xe7, 0x68, + 0xf7, 0x8c, 0x81, 0xf9, 0x3f, 0xad, 0xa4, 0x40, + 0x38, 0x82 ); + MEMCPY_TEST_CONSTANT ( 0x71, 0xcd, 0x3d, 0x26, 0xde, 0x11, 0x23, 0xd5, + 0x42, 0x6e, 0x63, 0x72, 0x53, 0xfc, 0x28, 0x06, + 0x4b, 0xe0, 0x2c, 0x07, 0x6b, 0xe8, 0xd9, 0x5f, + 0xf8, 0x74, 0xed ); + MEMCPY_TEST_CONSTANT ( 0x05, 0xb2, 0xae, 0x81, 0x91, 0xc9, 0xa2, 0x5f, + 0xa9, 0x1b, 0x25, 0x7f, 0x32, 0x0c, 0x04, 0x00, + 0xf1, 0x46, 0xab, 0x77, 0x1e, 0x12, 0x27, 0xe7, + 0xf6, 0x1e, 0x0c, 0x29 ); + MEMCPY_TEST_CONSTANT ( 0x0e, 0xca, 0xa5, 0x56, 0x3d, 0x99, 0x99, 0xf9, + 0x6e, 0xdd, 0x93, 0x98, 0xec, 0x8b, 0x5c, 0x71, + 0x0c, 0xb0, 0xe6, 0x12, 0xf2, 0x10, 0x1a, 0xbe, + 0x4a, 0xe0, 0xe3, 0x00, 0xf8 ); + MEMCPY_TEST_CONSTANT ( 0x40, 0xa8, 0x28, 0x5b, 0x12, 0x0d, 0x80, 0x8e, + 0x8a, 0xd9, 0x92, 0x7a, 0x6e, 0x48, 0x8d, 0x14, + 0x4b, 0xc6, 0xce, 0x21, 0x2f, 0x0e, 0x47, 0xbd, + 0xf1, 0xca, 0x0e, 0x1f, 0x65, 0xc4 ); + MEMCPY_TEST_CONSTANT ( 0x84, 0x83, 0x44, 0xe8, 0x1c, 0xbf, 0x23, 0x05, + 0xdf, 0xed, 0x3b, 0xb7, 0x0b, 0x4a, 0x05, 0xec, + 0xb7, 0x6f, 0x1c, 0xfe, 0x05, 0x05, 0x4e, 0xd1, + 0x50, 0x88, 0x81, 0x87, 0x68, 0xf6, 0x66 ); + MEMCPY_TEST_CONSTANT ( 0x0d, 0x1d, 0xcf, 0x3e, 0x7c, 0xf8, 0x12, 0x1b, + 0x96, 0x7f, 0xff, 0x27, 0xca, 0xfe, 0xd3, 0x8b, + 0x10, 0xb9, 0x5d, 0x05, 0xad, 0x50, 0xed, 0x35, + 0x32, 0x9c, 0xe6, 0x3b, 0x73, 0xe0, 0x7d ); + + /* Speed tests */ + memcpy_test_speed ( 0, 0, 64 ); + memcpy_test_speed ( 0, 0, 128 ); + memcpy_test_speed ( 0, 0, 256 ); + for ( dest_offset = 0 ; dest_offset < 4 ; dest_offset++ ) { + for ( src_offset = 0 ; src_offset < 4 ; src_offset++ ) { + memcpy_test_speed ( dest_offset, src_offset, 4096 ); + } + } +} -#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 ); } +/** memcpy() self-test */ +struct self_test memcpy_test __self_test = { + .name = "memcpy", + .exec = memcpy_test_exec, +}; diff --git a/roms/ipxe/src/tests/ocsp_test.c b/roms/ipxe/src/tests/ocsp_test.c new file mode 100644 index 000000000..24405db80 --- /dev/null +++ b/roms/ipxe/src/tests/ocsp_test.c @@ -0,0 +1,1450 @@ +/* + * 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. + */ + +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 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, &barclays_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, 0xd4, 0xb4, 0x3b, 0x8e, 0x3d, 0x02, 0x49, + 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73, 0x14, 0xdd, 0xe8, 0x59, + 0x44, 0x52, 0xe4, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, + 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, + 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x10, 0x49, 0x83, 0xfc, + 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1, + 0xf1, 0x48, 0xe3 ), + 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 ( &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 ( 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/roms/ipxe/src/tests/pubkey_test.h b/roms/ipxe/src/tests/pubkey_test.h new file mode 100644 index 000000000..7678453a9 --- /dev/null +++ b/roms/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/roms/ipxe/src/tests/rsa_test.c b/roms/ipxe/src/tests/rsa_test.c new file mode 100644 index 000000000..3b32c74bc --- /dev/null +++ b/roms/ipxe/src/tests/rsa_test.c @@ -0,0 +1,492 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/settings_test.c b/roms/ipxe/src/tests/settings_test.c new file mode 100644 index 000000000..028f8163b --- /dev/null +++ b/roms/ipxe/src/tests/settings_test.c @@ -0,0 +1,278 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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, 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/roms/ipxe/src/tests/sha1_test.c b/roms/ipxe/src/tests/sha1_test.c new file mode 100644 index 000000000..bcf761bdd --- /dev/null +++ b/roms/ipxe/src/tests/sha1_test.c @@ -0,0 +1,105 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 long cost; + unsigned int i; + unsigned int j; + + /* Correctness test */ + 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 ); + } + } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "SHA1 required %ld cycles per byte\n", cost ); +} + +/** SHA-1 self-test */ +struct self_test sha1_test __self_test = { + .name = "sha1", + .exec = sha1_test_exec, +}; diff --git a/roms/ipxe/src/tests/sha256_test.c b/roms/ipxe/src/tests/sha256_test.c new file mode 100644 index 000000000..06a8cae25 --- /dev/null +++ b/roms/ipxe/src/tests/sha256_test.c @@ -0,0 +1,108 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 long cost; + unsigned int i; + unsigned int j; + + /* Correctness test */ + 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 ); + } + } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "SHA256 required %ld cycles per byte\n", cost ); +} + +/** SHA-256 self-test */ +struct self_test sha256_test __self_test = { + .name = "sha256", + .exec = sha256_test_exec, +}; diff --git a/roms/ipxe/src/tests/string_test.c b/roms/ipxe/src/tests/string_test.c new file mode 100644 index 000000000..88181cc21 --- /dev/null +++ b/roms/ipxe/src/tests/string_test.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 (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 ); + +/** @file + * + * String self-tests + * + * memcpy() tests are handled separately + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ipxe/test.h> + +/** + * Perform string self-tests + * + */ +static void string_test_exec ( void ) { + + /* Test strlen() */ + ok ( strlen ( "" ) == 0 ); + ok ( strlen ( "Hello" ) == 5 ); + ok ( strlen ( "Hello world!" ) == 12 ); + ok ( strlen ( "Hello\0world!" ) == 5 ); + + /* Test strnlen() */ + ok ( strnlen ( "", 0 ) == 0 ); + ok ( strnlen ( "", 10 ) == 0 ); + ok ( strnlen ( "Hello", 0 ) == 0 ); + ok ( strnlen ( "Hello", 3 ) == 3 ); + ok ( strnlen ( "Hello", 5 ) == 5 ); + ok ( strnlen ( "Hello", 16 ) == 5 ); + ok ( strnlen ( "Hello world!", 5 ) == 5 ); + ok ( strnlen ( "Hello world!", 11 ) == 11 ); + ok ( strnlen ( "Hello world!", 16 ) == 12 ); + + /* Test strchr() */ + ok ( strchr ( "", 'a' ) == NULL ); + ok ( *(strchr ( "Testing", 'e' )) == 'e' ); + ok ( *(strchr ( "Testing", 'g' )) == 'g' ); + ok ( strchr ( "Testing", 'x' ) == NULL ); + + /* Test strcmp() */ + ok ( strcmp ( "", "" ) == 0 ); + ok ( strcmp ( "Hello", "Hello" ) == 0 ); + ok ( strcmp ( "Hello", "hello" ) != 0 ); + ok ( strcmp ( "Hello", "Hello world!" ) != 0 ); + ok ( strcmp ( "Hello world!", "Hello" ) != 0 ); + + /* Test strncmp() */ + ok ( strncmp ( "", "", 0 ) == 0 ); + ok ( strncmp ( "", "", 15 ) == 0 ); + ok ( strncmp ( "Goodbye", "Goodbye", 16 ) == 0 ); + ok ( strncmp ( "Goodbye", "Hello", 16 ) != 0 ); + ok ( strncmp ( "Goodbye", "Goodbye world", 32 ) != 0 ); + ok ( strncmp ( "Goodbye", "Goodbye world", 7 ) == 0 ); + + /* Test memcmp() */ + ok ( memcmp ( "", "", 0 ) == 0 ); + ok ( memcmp ( "Foo", "Foo", 3 ) == 0 ); + ok ( memcmp ( "Foo", "Bar", 3 ) != 0 ); + + /* Test memset() */ + { + static uint8_t test[7] = { '>', 1, 1, 1, 1, 1, '<' }; + static const uint8_t expected[7] = { '>', 0, 0, 0, 0, 0, '<' }; + memset ( ( test + 1 ), 0, ( sizeof ( test ) - 2 ) ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + { + static uint8_t test[4] = { '>', 0, 0, '<' }; + static const uint8_t expected[4] = { '>', 0xeb, 0xeb, '<' }; + memset ( ( test + 1 ), 0xeb, ( sizeof ( test ) - 2 ) ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + + /* Test memmove() */ + { + static uint8_t test[11] = + { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, '<' }; + static const uint8_t expected[11] = + { '>', 3, 4, 5, 6, 7, 8, 7, 8, 9, '<' }; + memmove ( ( test + 1 ), ( test + 3 ), 6 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + { + static uint8_t test[12] = + { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '<' }; + static const uint8_t expected[12] = + { '>', 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, '<' }; + memmove ( ( test + 6 ), ( test + 1 ), 5 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + + /* Test memswap() */ + { + static uint8_t test[8] = + { '>', 1, 2, 3, 7, 8, 9, '<' }; + static const uint8_t expected[8] = + { '>', 7, 8, 9, 1, 2, 3, '<' }; + memswap ( ( test + 1 ), ( test + 4 ), 3 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } +} + +/** String self-test */ +struct self_test string_test __self_test = { + .name = "string", + .exec = string_test_exec, +}; diff --git a/roms/ipxe/src/tests/tcpip_test.c b/roms/ipxe/src/tests/tcpip_test.c new file mode 100644 index 000000000..13423c397 --- /dev/null +++ b/roms/ipxe/src/tests/tcpip_test.c @@ -0,0 +1,213 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * TCP/IP self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ipxe/test.h> +#include <ipxe/profile.h> +#include <ipxe/tcpip.h> + +/** A TCP/IP fixed-data test */ +struct tcpip_test { + /** Data */ + const void *data; + /** Length of data */ + size_t len; +}; + +/** A TCP/IP pseudorandom-data test */ +struct tcpip_random_test { + /** Seed */ + unsigned int seed; + /** Length of data */ + size_t len; + /** Alignment offset */ + size_t offset; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a TCP/IP fixed-data test */ +#define TCPIP_TEST( name, DATA ) \ + static const uint8_t __attribute__ (( aligned ( 16 ) )) \ + name ## _data[] = DATA; \ + static struct tcpip_test name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + } + +/** Define a TCP/IP pseudorandom-data test */ +#define TCPIP_RANDOM_TEST( name, SEED, LEN, OFFSET ) \ + static struct tcpip_random_test name = { \ + .seed = SEED, \ + .len = LEN, \ + .offset = OFFSET, \ + } + +/** Buffer for pseudorandom-data tests */ +static uint8_t __attribute__ (( aligned ( 16 ) )) + tcpip_data[ 4096 + 7 /* offset */ ]; + +/** Empty data */ +TCPIP_TEST ( empty, DATA() ); + +/** Single byte */ +TCPIP_TEST ( one_byte, DATA ( 0xeb ) ); + +/** Double byte */ +TCPIP_TEST ( two_bytes, DATA ( 0xba, 0xbe ) ); + +/** Final wrap-around carry (big-endian) */ +TCPIP_TEST ( final_carry_big, + DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ) ); + +/** Final wrap-around carry (little-endian) */ +TCPIP_TEST ( final_carry_little, + DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 ) ); + +/** Random data (aligned) */ +TCPIP_RANDOM_TEST ( random_aligned, 0x12345678UL, 4096, 0 ); + +/** Random data (unaligned, +1) */ +TCPIP_RANDOM_TEST ( random_unaligned_1, 0x12345678UL, 4096, 1 ); + +/** Random data (unaligned, +2) */ +TCPIP_RANDOM_TEST ( random_unaligned_2, 0x12345678UL, 4096, 2 ); + +/** Random data (aligned, truncated) */ +TCPIP_RANDOM_TEST ( random_aligned_truncated, 0x12345678UL, 4095, 0 ); + +/** Random data (unaligned start and finish) */ +TCPIP_RANDOM_TEST ( partial, 0xcafebabe, 121, 5 ); + +/** + * Calculate TCP/IP checksum + * + * @v data Data to sum + * @v len Length of data + * @ret cksum Checksum + * + * This is a reference implementation taken from RFC1071 (and modified + * to fix compilation without warnings under gcc). + */ +static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) { + unsigned long sum = 0; + + while ( len > 1 ) { + sum += *( ( uint16_t * ) data ); + data += 2; + len -= 2; + } + + if ( len > 0 ) + sum += *( ( uint8_t * ) data ); + + while ( sum >> 16 ) + sum = ( ( sum & 0xffff ) + ( sum >> 16 ) ); + + return ~sum; +} + +/** + * Report TCP/IP fixed-data test result + * + * @v test TCP/IP test + */ +#define tcpip_ok( test ) do { \ + uint16_t expected; \ + uint16_t generic_sum; \ + uint16_t sum; \ + expected = rfc_tcpip_chksum ( (test)->data, (test)->len ); \ + generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, \ + (test)->data, \ + (test)->len ); \ + ok ( generic_sum == expected ); \ + sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, (test)->data, \ + (test)->len ); \ + ok ( sum == expected ); \ + } while ( 0 ) + +/** + * Report TCP/IP pseudorandom-data test result + * + * @v test TCP/IP test + */ +#define tcpip_random_ok( test ) do { \ + uint8_t *data = ( tcpip_data + (test)->offset ); \ + uint16_t expected; \ + uint16_t generic_sum; \ + uint16_t sum; \ + unsigned long elapsed; \ + unsigned int i; \ + assert ( ( (test)->len + (test)->offset ) <= \ + sizeof ( tcpip_data ) ); \ + srandom ( (test)->seed ); \ + for ( i = 0 ; i < (test)->len ; i++ ) \ + data[i] = random(); \ + expected = rfc_tcpip_chksum ( data, (test)->len ); \ + generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, \ + data, \ + (test)->len ); \ + ok ( generic_sum == expected ); \ + simple_profile(); \ + sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, \ + (test)->len ); \ + elapsed = simple_profile(); \ + ok ( sum == expected ); \ + DBG ( "TCPIP checksummed %zd bytes (+%zd) in %ld ticks\n", \ + (test)->len, (test)->offset, elapsed ); \ + } while ( 0 ) + +/** + * Perform TCP/IP self-tests + * + */ +static void tcpip_test_exec ( void ) { + + tcpip_ok ( &empty ); + tcpip_ok ( &one_byte ); + tcpip_ok ( &two_bytes ); + tcpip_ok ( &final_carry_big ); + tcpip_ok ( &final_carry_little ); + tcpip_random_ok ( &random_aligned ); + tcpip_random_ok ( &random_unaligned_1 ); + tcpip_random_ok ( &random_unaligned_2 ); + tcpip_random_ok ( &random_aligned_truncated ); + tcpip_random_ok ( &partial ); +} + +/** TCP/IP self-test */ +struct self_test tcpip_test __self_test = { + .name = "tcpip", + .exec = tcpip_test_exec, +}; diff --git a/roms/ipxe/src/tests/test.c b/roms/ipxe/src/tests/test.c new file mode 100644 index 000000000..62f7c97d9 --- /dev/null +++ b/roms/ipxe/src/tests/test.c @@ -0,0 +1,174 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/tests.c b/roms/ipxe/src/tests/tests.c new file mode 100644 index 000000000..af969ec8f --- /dev/null +++ b/roms/ipxe/src/tests/tests.c @@ -0,0 +1,48 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Self-test collection + * + */ + +/* Drag in all applicable self-tests */ +REQUIRE_OBJECT ( memcpy_test ); +REQUIRE_OBJECT ( string_test ); +REQUIRE_OBJECT ( list_test ); +REQUIRE_OBJECT ( byteswap_test ); +REQUIRE_OBJECT ( base64_test ); +REQUIRE_OBJECT ( settings_test ); +REQUIRE_OBJECT ( time_test ); +REQUIRE_OBJECT ( tcpip_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/roms/ipxe/src/tests/time_test.c b/roms/ipxe/src/tests/time_test.c new file mode 100644 index 000000000..28acebee6 --- /dev/null +++ b/roms/ipxe/src/tests/time_test.c @@ -0,0 +1,183 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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/roms/ipxe/src/tests/x509_test.c b/roms/ipxe/src/tests/x509_test.c new file mode 100644 index 000000000..c014bd2e0 --- /dev/null +++ b/roms/ipxe/src/tests/x509_test.c @@ -0,0 +1,948 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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, + ¬_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 ( ¬_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 ( ¬_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 ( ¬_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 ( ¬_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 ( ¬_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 ( ¬_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/roms/ipxe/src/usr/autoboot.c b/roms/ipxe/src/usr/autoboot.c index c5c5f3e78..0587f2044 100644 --- a/roms/ipxe/src/usr/autoboot.c +++ b/roms/ipxe/src/usr/autoboot.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -119,54 +120,38 @@ struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA ) = { * * @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; +int uriboot ( struct uri *filename, struct uri *root_path, int drive, + unsigned int flags ) { + struct image *image; int rc; - /* Treat empty URIs as absent */ - if ( filename && ( ! uri_has_path ( filename ) ) ) - filename = NULL; - if ( root_path && ( ! uri_is_absolute ( 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" ); - 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; - } - /* Hook SAN device, if applicable */ if ( root_path ) { - drive = san_hook ( root_path, 0 ); - if ( drive < 0 ) { - rc = drive; + if ( ( rc = san_hook ( root_path, drive ) ) != 0 ) { printf ( "Could not open SAN device: %s\n", strerror ( rc ) ); goto err_san_hook; } - printf ( "Registered as SAN device %#02x\n", drive ); - } else { - drive = -ENODEV; + printf ( "Registered SAN device %#02x\n", drive ); } /* Describe SAN device, if applicable */ - if ( ( drive >= 0 ) && ( ( rc = san_describe ( drive ) ) != 0 ) ) { - printf ( "Could not describe SAN device %#02x: %s\n", - drive, strerror ( rc ) ); - goto err_san_describe; + 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; + } } /* Allow a root-path-only boot with skip-san enabled to succeed */ @@ -174,9 +159,11 @@ int uriboot ( struct uri *filename, struct uri *root_path ) { /* Attempt filename boot if applicable */ if ( filename ) { - if ( ( rc = imgdownload ( filename, NULL, NULL, - register_and_boot_image ) ) != 0 ) { - printf ( "\nCould not chain image: %s\n", + if ( ( rc = imgdownload ( filename, &image ) ) != 0 ) + goto err_download; + image->flags |= IMAGE_AUTO_UNREGISTER; + 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, @@ -192,7 +179,7 @@ int uriboot ( struct uri *filename, struct uri *root_path ) { } /* Attempt SAN boot if applicable */ - if ( root_path ) { + 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 ); @@ -207,19 +194,18 @@ int uriboot ( struct uri *filename, struct uri *root_path ) { } } + err_download: err_san_describe: /* Unhook SAN device, if applicable */ - if ( drive >= 0 ) { + if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) { if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) { - printf ( "Unregistering SAN device %#02x\n", drive ); san_unhook ( drive ); + printf ( "Unregistered SAN device %#02x\n", drive ); } else { - printf ( "Preserving connection to SAN device %#02x\n", - drive ); + printf ( "Preserving SAN device %#02x\n", drive ); } } err_san_hook: - err_no_boot: return rc; } @@ -360,19 +346,51 @@ int netboot ( struct net_device *netdev ) { goto err_pxe_menu_boot; } - /* Fetch next server, filename and root path */ + /* 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; + } /* Boot using next server, filename and root path */ - if ( ( rc = uriboot ( filename, root_path ) ) != 0 ) + if ( ( rc = uriboot ( filename, root_path, san_default_drive(), + ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 ) goto err_uriboot; err_uriboot: + err_no_boot: uri_put ( root_path ); err_root_path: uri_put ( filename ); diff --git a/roms/ipxe/src/usr/dhcpmgmt.c b/roms/ipxe/src/usr/dhcpmgmt.c index e651dfda1..b61c01aa3 100644 --- a/roms/ipxe/src/usr/dhcpmgmt.c +++ b/roms/ipxe/src/usr/dhcpmgmt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -37,10 +38,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ 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 */ @@ -52,12 +49,8 @@ int dhcp ( struct net_device *netdev ) { 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 ( ")" ); - + printf ( "DHCP (%s %s)", netdev->name, + netdev->ll_protocol->ntoa ( netdev->ll_addr ) ); if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) { rc = monojob_wait ( "" ); } else if ( rc > 0 ) { diff --git a/roms/ipxe/src/usr/fcmgmt.c b/roms/ipxe/src/usr/fcmgmt.c index 1af723d13..2657ba0cf 100644 --- a/roms/ipxe/src/usr/fcmgmt.c +++ b/roms/ipxe/src/usr/fcmgmt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -74,8 +75,7 @@ void fcpeerstat ( struct fc_peer *peer ) { } list_for_each_entry ( ulp, &peer->ulps, list ) { - printf ( " [Type %02x usage %d link:", - ulp->type, ulp->usage ); + printf ( " [Type %02x link:", ulp->type ); if ( fc_link_ok ( &ulp->link ) ) { printf ( " up, params" ); param = ulp->param; diff --git a/roms/ipxe/src/usr/ifmgmt.c b/roms/ipxe/src/usr/ifmgmt.c index 049851596..94e6e8754 100644 --- a/roms/ipxe/src/usr/ifmgmt.c +++ b/roms/ipxe/src/usr/ifmgmt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -113,6 +114,9 @@ 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; diff --git a/roms/ipxe/src/usr/imgmgmt.c b/roms/ipxe/src/usr/imgmgmt.c index dbf792b75..ef4e2c366 100644 --- a/roms/ipxe/src/usr/imgmgmt.c +++ b/roms/ipxe/src/usr/imgmgmt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -36,132 +37,24 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** - * Register an image and leave it registered - * - * @v image Executable image - * @ret rc Return status code - * - * This function assumes an ownership of the passed image. - */ -int register_and_put_image ( struct image *image ) { - int rc; - - rc = register_image ( image ); - image_put ( image ); - return rc; -} - -/** - * Register and probe an image - * - * @v image Executable image - * @ret rc Return status code - * - * This function assumes an ownership of the passed image. - */ -int register_and_probe_image ( struct image *image ) { - int rc; - - if ( ( rc = register_and_put_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_probe ( image ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Register and select an image - * - * @v image Executable image - * @ret rc Return status code - * - * This function assumes an ownership of the passed image. - */ -int register_and_select_image ( struct image *image ) { - int rc; - - if ( ( rc = register_and_probe_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_select ( image ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Register and boot an image - * - * @v image Image - * @ret rc Return status code - * - * This function assumes an ownership of the passed image. - */ -int register_and_boot_image ( struct image *image ) { - int rc; - - if ( ( rc = register_and_select_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_exec ( image ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Register and replace image - * - * @v image Image - * @ret rc Return status code - * - * This function assumes an ownership of the passed image. - */ -int register_and_replace_image ( struct image *image ) { - int rc; - - if ( ( rc = register_and_probe_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_replace ( image ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Download an image + * Download a new image * * @v uri URI - * @v name Image name, or NULL to use default - * @v cmdline Command line, or NULL for no command line - * @v action Action to take upon a successful download + * @v image Image to fill in * @ret rc Return status code */ -int imgdownload ( struct uri *uri, const char *name, const char *cmdline, - int ( * action ) ( struct image *image ) ) { - struct image *image; +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(); - if ( ! image ) - return -ENOMEM; - - /* Set image name */ - if ( name ) - image_set_name ( image, name ); - - /* Set image URI */ - image_set_uri ( image, uri ); - - /* Set image command line */ - image_set_cmdline ( image, cmdline ); + *image = alloc_image ( uri ); + if ( ! *image ) { + rc = -ENOMEM; + goto err_alloc_image; + } /* Redact password portion of URI, if necessary */ password = uri->password; @@ -172,51 +65,75 @@ int imgdownload ( struct uri *uri, const char *name, const char *cmdline, uri->password = password; /* Create downloader */ - if ( ( rc = create_downloader ( &monojob, image, LOCATION_URI, + if ( ( rc = create_downloader ( &monojob, *image, LOCATION_URI, uri ) ) != 0 ) { - image_put ( image ); - return rc; + 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 ) { - image_put ( image ); - return rc; + 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; } - /* Act upon downloaded image. This action assumes our - * ownership of the image. + /* Drop local reference to image. Image is guaranteed to + * remain in scope since it is registered. */ - if ( ( rc = action ( image ) ) != 0 ) - return rc; + image_put ( *image ); return 0; + + err_register_image: + err_monojob_wait: + err_create_downloader: + image_put ( *image ); + err_alloc_image: + return rc; } /** - * Download an image + * Download a new image * - * @v uri_string URI as a string (e.g. "http://www.nowhere.com/vmlinuz") - * @v name Image name, or NULL to use default - * @v cmdline Command line, or NULL for no command line - * @v action Action to take upon a successful download + * @v uri_string URI string + * @v image Image to fill in * @ret rc Return status code */ -int imgdownload_string ( const char *uri_string, const char *name, - const char *cmdline, - int ( * action ) ( struct image *image ) ) { +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, name, cmdline, action ); + 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 * @@ -226,18 +143,13 @@ 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->flags & IMAGE_AUTO_UNREGISTER ) + printf ( " [AUTOFREE]" ); if ( image->cmdline ) printf ( " \"%s\"", image->cmdline ); printf ( "\n" ); } - -/** - * Free an image - * - * @v image Executable/loadable image - */ -void imgfree ( struct image *image ) { - unregister_image ( image ); -} diff --git a/roms/ipxe/src/usr/imgtrust.c b/roms/ipxe/src/usr/imgtrust.c new file mode 100644 index 000000000..afb41529f --- /dev/null +++ b/roms/ipxe/src/usr/imgtrust.c @@ -0,0 +1,110 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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 <ipxe/validator.h> +#include <ipxe/monojob.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; + struct cms_signer_info *info; + 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; + + /* Complete all certificate chains */ + list_for_each_entry ( info, &sig->info, list ) { + if ( ( rc = create_validator ( &monojob, info->chain ) ) != 0 ) + goto err_create_validator; + if ( ( rc = monojob_wait ( NULL ) ) != 0 ) + goto err_validator_wait; + } + + /* 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: + err_validator_wait: + err_create_validator: + 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/roms/ipxe/src/usr/iwmgmt.c b/roms/ipxe/src/usr/iwmgmt.c index 29f623c37..a486bceb3 100644 --- a/roms/ipxe/src/usr/iwmgmt.c +++ b/roms/ipxe/src/usr/iwmgmt.c @@ -13,13 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdio.h> -#include <ipxe/console.h> #include <string.h> #include <errno.h> #include <ipxe/net80211.h> diff --git a/roms/ipxe/src/usr/lotest.c b/roms/ipxe/src/usr/lotest.c index 7f9f2fd07..c4b0b4413 100644 --- a/roms/ipxe/src/usr/lotest.c +++ b/roms/ipxe/src/usr/lotest.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -47,12 +48,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @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 ) { + const void *ll_source __unused, + unsigned int flags __unused ) { free_iob ( iobuf ); return -ENOTSUP; } @@ -82,6 +85,86 @@ static struct net_protocol lotest_protocol __net_protocol = { .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 * @@ -94,9 +177,6 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver, size_t mtu ) { uint8_t buf[mtu]; struct io_buffer *iobuf; - const void *ll_dest; - const void *ll_source; - uint16_t net_proto; unsigned int i; unsigned int successes; int rc; @@ -137,7 +217,7 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver, if ( ! iobuf ) { printf ( "\nFailed to allocate I/O buffer" ); rc = -ENOMEM; - goto done; + break; } iob_reserve ( iobuf, MAX_LL_HEADER_LEN ); memcpy ( iob_put ( iobuf, sizeof ( buf ) ), @@ -149,64 +229,17 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver, sender->ll_addr ) ) != 0 ) { printf ( "\nFailed to transmit packet: %s", strerror ( rc ) ); - goto done; + break; } - /* Poll until packet arrives */ - do { - /* Check for cancellation */ - if ( iskey() && ( getchar() == CTRL_C ) ) { - rc = -ECANCELED; - goto done; - } - /* Poll network devices */ - net_poll(); - } while ( ( iobuf = netdev_rx_dequeue ( receiver ) ) == NULL ); - - /* Check received packet */ - if ( ( rc = receiver->ll_protocol->pull ( receiver, iobuf, - &ll_dest, &ll_source, - &net_proto ) ) != 0 ){ - printf ( "\nFailed to strip link-layer header: %s", - strerror ( rc ) ); - goto done; - } - if ( net_proto == lotest_protocol.net_proto ) { - if ( iob_len ( iobuf ) != sizeof ( buf ) ) { - printf ( "\nLength mismatch: sent %zd, " - "received %zd", - sizeof ( buf ), iob_len ( iobuf ) ); - DBG ( "\nSent:\n" ); - DBG_HDA ( 0, buf, sizeof ( buf ) ); - DBG ( "Received:\n" ); - DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto done; - } - if ( memcmp ( iobuf->data, buf, sizeof ( buf ) ) != 0){ - printf ( "\nContent mismatch" ); - DBG ( "\nSent:\n" ); - DBG_HDA ( 0, buf, sizeof ( buf ) ); - DBG ( "Received:\n" ); - DBG_HDA ( 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto done; - } - } else { - printf ( "\nReceived spurious packet type %04x\n", - ntohs ( net_proto ) ); - /* Continue; this allows for the fact that - * there may have been packets outstanding on - * the wire when we started the test. - */ + /* Wait for received packet */ + if ( ( rc = loopback_wait ( receiver, buf, + sizeof ( buf ) ) ) != 0 ) { + break; } - - free_iob ( iob_disown ( iobuf ) ); } - done: printf ( "\n"); - free_iob ( iobuf ); netdev_rx_unfreeze ( receiver ); /* Dump final statistics */ diff --git a/roms/ipxe/src/usr/nslookup.c b/roms/ipxe/src/usr/nslookup.c new file mode 100644 index 000000000..c931ec5a1 --- /dev/null +++ b/roms/ipxe/src/usr/nslookup.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You 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 ); + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ipxe/resolv.h> +#include <ipxe/tcpip.h> +#include <ipxe/monojob.h> +#include <ipxe/settings.h> +#include <usr/nslookup.h> + +/** @file + * + * Standalone name resolution + * + */ + +/** A name resolution request */ +struct nslookup { + /** Reference count for this object */ + struct refcnt refcnt; + + /** Job control interface */ + struct interface job; + /** Data transfer interface */ + struct interface resolver; + + /** Setting name */ + const char *setting_name; +}; + +/** + * Terminate name resolution + * + * @v nslookup Name resolution request + * @v rc Reason for termination + */ +static void nslookup_close ( struct nslookup *nslookup, int rc ) { + + /* Shut down interfaces */ + intf_shutdown ( &nslookup->resolver, rc ); + intf_shutdown ( &nslookup->job, rc ); +} + +/** + * Handle resolved name + * + * @v nslookup Name resolution request + * @v sa Completed socket address + */ +static void nslookup_resolv_done ( struct nslookup *nslookup, + struct sockaddr *sa ) { + struct sockaddr_in *sin; + struct setting_type *type; + void *data; + size_t len; + int rc; + + /* Extract address */ + switch ( sa->sa_family ) { + case AF_INET: + sin = ( ( struct sockaddr_in * ) sa ); + data = &sin->sin_addr; + len = sizeof ( sin->sin_addr ); + type = &setting_type_ipv4; + break; + default: + rc = -ENOTSUP; + goto err; + } + + /* Save in specified setting */ + if ( ( rc = store_named_setting ( nslookup->setting_name, type, + data, len ) ) != 0 ) + goto err; + + err: + /* Terminate name resolution */ + nslookup_close ( nslookup, rc ); +} + +/** Name resolution resolver interface operations */ +static struct interface_operation nslookup_resolver_operations[] = { + INTF_OP ( resolv_done, struct nslookup *, nslookup_resolv_done ), + INTF_OP ( intf_close, struct nslookup *, nslookup_close ), +}; + +/** Name resolution resolver interface descriptor */ +static struct interface_descriptor nslookup_resolver_desc = + INTF_DESC_PASSTHRU ( struct nslookup, resolver, + nslookup_resolver_operations, job ); + +/** Name resolution job control interface operations */ +static struct interface_operation nslookup_job_operations[] = { + INTF_OP ( intf_close, struct nslookup *, nslookup_close ), +}; + +/** Name resolution job control interface descriptor */ +static struct interface_descriptor nslookup_job_desc = + INTF_DESC_PASSTHRU ( struct nslookup, job, + nslookup_job_operations, resolver ); + +/** + * Initiate standalone name resolution + * + * @v job Parent interface + * @v name Name to resolve + * @v setting_name Setting name + * @ret rc Return status code + */ +static int resolv_setting ( struct interface *job, const char *name, + const char *setting_name ) { + struct nslookup *nslookup; + struct sockaddr sa; + char *setting_name_copy; + int rc; + + /* Allocate and initialise structure */ + nslookup = zalloc ( sizeof ( *nslookup ) + strlen ( setting_name ) + + 1 /* NUL */ ); + if ( ! nslookup ) + return -ENOMEM; + ref_init ( &nslookup->refcnt, NULL ); + intf_init ( &nslookup->job, &nslookup_job_desc, &nslookup->refcnt ); + intf_init ( &nslookup->resolver, &nslookup_resolver_desc, + &nslookup->refcnt ); + setting_name_copy = ( ( void * ) ( nslookup + 1 ) ); + strcpy ( setting_name_copy, setting_name ); + nslookup->setting_name = setting_name_copy; + + /* Start name resolution */ + memset ( &sa, 0, sizeof ( sa ) ); + if ( ( rc = resolv ( &nslookup->resolver, name, &sa ) ) != 0 ) + goto err_resolv; + + /* Attach parent interface, mortalise self, and return */ + intf_plug_plug ( &nslookup->job, job ); + ref_put ( &nslookup->refcnt ); + return 0; + + err_resolv: + ref_put ( &nslookup->refcnt ); + return rc; +} + +/** + * Perform (blocking) standalone name resolution + * + * @v name Name to resolve + * @v setting_name Setting name + * @ret rc Return status code + */ +int nslookup ( const char *name, const char *setting_name ) { + int rc; + + /* Perform name resolution */ + if ( ( rc = resolv_setting ( &monojob, name, setting_name ) ) == 0 ) + rc = monojob_wait ( NULL ); + if ( rc != 0 ) { + printf ( "Could not resolve %s: %s\n", name, strerror ( rc ) ); + return rc; + } + + return 0; +} diff --git a/roms/ipxe/src/usr/prompt.c b/roms/ipxe/src/usr/prompt.c index 3c353a686..ede037457 100644 --- a/roms/ipxe/src/usr/prompt.c +++ b/roms/ipxe/src/usr/prompt.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/usr/pxemenu.c b/roms/ipxe/src/usr/pxemenu.c index 75789e2dc..d50ee6ba9 100644 --- a/roms/ipxe/src/usr/pxemenu.c +++ b/roms/ipxe/src/usr/pxemenu.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -377,7 +378,7 @@ int pxe_menu_boot ( struct net_device *netdev ) { return -ENOMEM; /* Attempt boot */ - rc = uriboot ( uri, NULL ); + rc = uriboot ( uri, NULL, 0, URIBOOT_NO_SAN ); uri_put ( uri ); return rc; } diff --git a/roms/ipxe/src/usr/route.c b/roms/ipxe/src/usr/route.c index 1da7135bc..e393e38d4 100644 --- a/roms/ipxe/src/usr/route.c +++ b/roms/ipxe/src/usr/route.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/roms/ipxe/src/util/Makefile b/roms/ipxe/src/util/Makefile index d72661e21..4a6a7c7c6 100644 --- a/roms/ipxe/src/util/Makefile +++ b/roms/ipxe/src/util/Makefile @@ -1,17 +1,11 @@ BLIB = ../bin/blib.a CFLAGS = -Os -all : hijack prototester mucurses_test +all : hijack mucurses_test hijack : hijack.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wall -lpcap -o $@ $< -prototester.o : prototester.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wall -o $@ -c $< -idirafter ../include - -prototester : prototester.o $(BLIB) - $(CC) -o $@ $< -lc $(BLIB) - mucurses_test.o : mucurses_test.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -Wall -o $@ -c $< @@ -19,4 +13,4 @@ mucurses_test : mucurses_test.o $(BLIB) $(CC) -o $@ $< -lc $(BLIB) clean : - rm -f hijack prototester mucurses_test *.o + rm -f hijack mucurses_test *.o diff --git a/roms/ipxe/src/util/Option/ROM.pm b/roms/ipxe/src/util/Option/ROM.pm index 9fea4d344..fb37ce4b0 100644 --- a/roms/ipxe/src/util/Option/ROM.pm +++ b/roms/ipxe/src/util/Option/ROM.pm @@ -14,7 +14,8 @@ package Option::ROM; # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME @@ -169,13 +170,17 @@ use Exporter 'import'; use constant ROM_SIGNATURE => 0xaa55; use constant PCI_SIGNATURE => 'PCIR'; +use constant PCI_LAST_IMAGE => 0x80; use constant PNP_SIGNATURE => '$PnP'; +use constant IPXE_SIGNATURE => 'iPXE'; -our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE ); +our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE + PNP_SIGNATURE IPXE_SIGNATURE ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; use constant JMP_NEAR => 0xe9; +use constant CALL_NEAR => 0xe8; sub pack_init { my $dest = shift; @@ -199,6 +204,9 @@ sub unpack_init { } elsif ( $jump == JMP_NEAR ) { my $offset = unpack ( "xS", $instr ); return ( $offset + 6 ); + } elsif ( $jump == CALL_NEAR ) { + my $offset = unpack ( "xS", $instr ); + return ( $offset + 6 ); } elsif ( $jump == 0 ) { return 0; } else { @@ -229,6 +237,7 @@ sub new { init => { offset => 0x03, length => 0x03, pack => \&pack_init, unpack => \&unpack_init }, checksum => { offset => 0x06, length => 0x01, pack => "C" }, + ipxe_header => { offset => 0x10, length => 0x02, pack => "S" }, bofm_header => { offset => 0x14, length => 0x02, pack => "S" }, undi_header => { offset => 0x16, length => 0x02, pack => "S" }, pci_header => { offset => 0x18, length => 0x02, pack => "S" }, @@ -241,6 +250,53 @@ sub new { =pod +=item C<< set ( $data ) >> + +Set option ROM contents. + +=cut + +sub set { + my $hash = shift; + my $self = tied(%$hash); + my $data = shift; + + # Store data + $self->{data} = \$data; + + # Split out any data belonging to the next image + delete $self->{next_image}; + my $length = ( $hash->{length} * 512 ); + my $pci_header = $hash->pci_header(); + if ( ( $length < length $data ) && + ( defined $pci_header ) && + ( ! ( $pci_header->{last_image} & PCI_LAST_IMAGE ) ) ) { + my $remainder = substr ( $data, $length ); + $data = substr ( $data, 0, $length ); + $self->{next_image} = new Option::ROM; + $self->{next_image}->set ( $remainder ); + } +} + +=pod + +=item C<< get () >> + +Get option ROM contents. + +=cut + +sub get { + my $hash = shift; + my $self = tied(%$hash); + + my $data = ${$self->{data}}; + $data .= $self->{next_image}->get() if $self->{next_image}; + return $data; +} + +=pod + =item C<< load ( $filename ) >> Load option ROM contents from the file C<$filename>. @@ -256,8 +312,8 @@ sub load { 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; + read $fh, my $data, -s $fh; + $hash->set ( $data ); close $fh; } @@ -279,7 +335,8 @@ sub save { open my $fh, ">$filename" or croak "Cannot open $filename for writing: $!"; - print $fh ${$self->{data}}; + my $data = $hash->get(); + print $fh $data; close $fh; } @@ -339,6 +396,60 @@ sub pnp_header { =pod +=item C<< undi_header () >> + +Return a C<Option::ROM::UNDI> object representing the ROM's UNDI header, +if present. + +=cut + +sub undi_header { + my $hash = shift; + my $self = tied(%$hash); + + my $offset = $hash->{undi_header}; + return undef unless $offset != 0; + + return Option::ROM::UNDI->new ( $self->{data}, $offset ); +} + +=pod + +=item C<< ipxe_header () >> + +Return a C<Option::ROM::iPXE> object representing the ROM's iPXE +header, if present. + +=cut + +sub ipxe_header { + my $hash = shift; + my $self = tied(%$hash); + + my $offset = $hash->{ipxe_header}; + return undef unless $offset != 0; + + return Option::ROM::iPXE->new ( $self->{data}, $offset ); +} + +=pod + +=item C<< next_image () >> + +Return a C<Option::ROM> object representing the next image within the +ROM, if present. + +=cut + +sub next_image { + my $hash = shift; + my $self = tied(%$hash); + + return $self->{next_image}; +} + +=pod + =item C<< checksum () >> Calculate the byte checksum of the ROM. @@ -499,4 +610,119 @@ sub product { return unpack ( "Z*", $raw ); } +############################################################################## +# +# Option::ROM::UNDI +# +############################################################################## + +package Option::ROM::UNDI; + +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 => 0x16, + fields => { + signature => { offset => 0x00, length => 0x04, pack => "a4" }, + struct_length => { offset => 0x04, length => 0x01, pack => "C" }, + checksum => { offset => 0x05, length => 0x01, pack => "C" }, + struct_revision =>{ offset => 0x06, length => 0x01, pack => "C" }, + version_revision =>{ offset => 0x07, length => 0x01, pack => "C" }, + version_minor => { offset => 0x08, length => 0x01, pack => "C" }, + version_major => { offset => 0x09, length => 0x01, pack => "C" }, + loader_entry => { offset => 0x0a, length => 0x02, pack => "S" }, + stack_size => { offset => 0x0c, length => 0x02, pack => "S" }, + data_size => { offset => 0x0e, length => 0x02, pack => "S" }, + code_size => { offset => 0x10, length => 0x02, pack => "S" }, + bus_type => { offset => 0x12, length => 0x04, pack => "a4" }, + }, + }; + bless $hash, $class; + + # Retrieve true length of structure + my $self = tied ( %$hash ); + $self->{length} = $hash->{struct_length}; + + 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 ); +} + +############################################################################## +# +# Option::ROM::iPXE +# +############################################################################## + +package Option::ROM::iPXE; + +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_length => { offset => 0x04, length => 0x01, pack => "C" }, + checksum => { offset => 0x05, length => 0x01, pack => "C" }, + shrunk_length => { offset => 0x06, length => 0x01, pack => "C" }, + build_id => { offset => 0x08, length => 0x04, pack => "L" }, + }, + }; + bless $hash, $class; + + # Retrieve true length of structure + my $self = tied ( %$hash ); + $self->{length} = $hash->{struct_length}; + + 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 ); +} + 1; diff --git a/roms/ipxe/src/util/catrom.pl b/roms/ipxe/src/util/catrom.pl index fe37e6b6e..da99d7b97 100755 --- a/roms/ipxe/src/util/catrom.pl +++ b/roms/ipxe/src/util/catrom.pl @@ -3,46 +3,27 @@ use warnings; use strict; -use bytes; +use FindBin; +use lib "$FindBin::Bin"; +use Option::ROM qw ( :all ); -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; + # Read ROM file + my $rom = new Option::ROM; + $rom->load ( $romfile ); - ( 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; + # Tag final image as non-final in all except the final ROM + if ( @romfiles ) { + my $image = $rom; + $image = $image->next_image() while $image->next_image(); + $image->pci_header->{last_image} &= ~PCI_LAST_IMAGE; + $image->fix_checksum(); + } - print $romdata; + # Write ROM file to STDOUT + $rom->save ( "-" ); } diff --git a/roms/ipxe/src/util/disrom.pl b/roms/ipxe/src/util/disrom.pl index 1fb4cc3cb..574957acd 100755 --- a/roms/ipxe/src/util/disrom.pl +++ b/roms/ipxe/src/util/disrom.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; @@ -27,55 +28,88 @@ my $romfile = shift || "-"; my $rom = new Option::ROM; $rom->load ( $romfile ); -die "Not an option ROM image\n" - unless $rom->{signature} == ROM_SIGNATURE; +do { -my $romlength = ( $rom->{length} * 512 ); -my $filelength = $rom->length; -die "ROM image truncated (is $filelength, should be $romlength)\n" - if $filelength < $romlength; + die "Not an option ROM image\n" + unless $rom->{signature} == ROM_SIGNATURE; -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 $romlength = ( $rom->{length} * 512 ); + my $filelength = $rom->length; + die "ROM image truncated (is $filelength, should be $romlength)\n" + if $filelength < $romlength; -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 "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 $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"; -} + 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 ); + printf " %-16s 0x%02x\n", "Code type:", $pci->{code_type}; + 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"; + } + + my $undi = $rom->undi_header(); + if ( $undi ) { + printf "UNDI header:\n\n"; + printf " %-16s %s\n", "Signature:", $undi->{signature}; + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $undi->{checksum}, + ( ( $undi->checksum == 0 ) ? "" : "INCORRECT: " ), $undi->checksum; + printf " %-16s %d.%d.%d\n", "UNDI version:", $undi->{version_major}, + $undi->{version_minor}, $undi->{version_revision}; + printf " %-16s 0x%04x\n", "Loader entry:", $undi->{loader_entry}; + printf " %-16s 0x%04x\n", "Stack size:", $undi->{stack_size}; + printf " %-16s 0x%04x\n", "Data size:", $undi->{data_size}; + printf " %-16s 0x%04x\n", "Code size:", $undi->{code_size}; + printf " %-16s %s\n", "Bus type:", $undi->{bus_type}; + printf "\n"; + } + + my $ipxe = $rom->ipxe_header(); + if ( $ipxe ) { + printf "iPXE header:\n\n"; + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $ipxe->{checksum}, + ( ( $ipxe->checksum == 0 ) ? "" : "INCORRECT: " ), $ipxe->checksum; + printf " %-16s 0x%02x (%d)\n", "Shrunk length:", + $ipxe->{shrunk_length}, ( $ipxe->{shrunk_length} * 512 ); + printf " %-16s 0x%08x\n", "Build ID:", $ipxe->{build_id}; + printf "\n"; + } + +} while ( $rom = $rom->next_image ); diff --git a/roms/ipxe/src/util/efirom.c b/roms/ipxe/src/util/efirom.c index d0bdace62..abee496dd 100644 --- a/roms/ipxe/src/util/efirom.c +++ b/roms/ipxe/src/util/efirom.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include <stdint.h> @@ -56,18 +57,6 @@ static void * xmalloc ( size_t len ) { return ptr; } -/** - * Get file size - * - * @v file File - * @v len File size - */ -static size_t file_size ( FILE *file ) { - ssize_t len; - - return len; -} - /** * Read information from PE headers * @@ -239,15 +228,15 @@ static int parse_options ( const int argc, char **argv, } int main ( int argc, char **argv ) { - struct options opts = { - }; - unsigned int infile_index; + 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] ); diff --git a/roms/ipxe/src/util/einfo.c b/roms/ipxe/src/util/einfo.c index 06736f219..354d475fa 100644 --- a/roms/ipxe/src/util/einfo.c +++ b/roms/ipxe/src/util/einfo.c @@ -13,13 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, 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> @@ -49,7 +51,8 @@ struct einfo { * @v infile Filename * @v opts Command-line options */ -static void einfo ( const char *infile, struct options *opts ) { +static void einfo ( const char *infile, + struct options *opts __attribute__ (( unused )) ) { int fd; struct stat stat; size_t len; @@ -85,15 +88,16 @@ static void einfo ( const char *infile, struct options *opts ) { for ( einfo = start ; ( ( void * ) einfo ) < ( start + len ) ; einfo = ( ( ( void * ) einfo ) + einfo->size ) ) { printf ( "%08x\t%s\t%d\t%s\n", einfo->error, - ( ( ( void * ) einfo ) + einfo->file ), + ( ( ( char * ) einfo ) + einfo->file ), einfo->line, - ( ( ( void * ) einfo ) + einfo->desc ) ); + ( ( ( char * ) einfo ) + einfo->desc ) ); } + /* Unmap file */ + munmap ( start, len ); } - /* Unmap and close file */ - munmap ( start, len ); + /* Close file */ close ( fd ); } @@ -115,8 +119,7 @@ static void print_help ( const char *program_name ) { * @v opts Options structure to populate */ static int parse_options ( const int argc, char **argv, - struct options *opts ) { - char *end; + struct options *opts __attribute__ (( unused )) ) { int c; while (1) { @@ -147,7 +150,7 @@ static int parse_options ( const int argc, char **argv, int main ( int argc, char **argv ) { struct options opts = { }; - unsigned int infile_index; + int infile_index; const char *infile; /* Parse command-line arguments */ diff --git a/roms/ipxe/src/util/elf2efi.c b/roms/ipxe/src/util/elf2efi.c index e66292966..b28c7ef33 100644 --- a/roms/ipxe/src/util/elf2efi.c +++ b/roms/ipxe/src/util/elf2efi.c @@ -13,7 +13,8 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #define _GNU_SOURCE @@ -405,6 +406,10 @@ static struct pe_section * process_section ( bfd *bfd, 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 */ @@ -459,7 +464,8 @@ static struct pe_section * process_section ( bfd *bfd, * @v rel Relocation entry * @v pe_reltab PE relocation table to fill in */ -static void process_reloc ( bfd *bfd, asection *section, arelent *rel, +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); @@ -608,8 +614,11 @@ static void write_pe_file ( struct pe_header *pe_header, struct pe_section *section; unsigned long fpos = 0; + /* Align length of headers */ + fpos = pe_header->nt.OptionalHeader.SizeOfHeaders = + efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders ); + /* 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; @@ -637,7 +646,7 @@ static void write_pe_file ( struct pe_header *pe_header, for ( section = pe_sections ; section ; section = section->next ) { if ( fseek ( pe, section->hdr.PointerToRawData, SEEK_SET ) != 0 ) { - eprintf ( "Could not seek to %lx: %s\n", + eprintf ( "Could not seek to %x: %s\n", section->hdr.PointerToRawData, strerror ( errno ) ); exit ( 1 ); @@ -786,7 +795,7 @@ int main ( int argc, char **argv ) { struct options opts = { .subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, }; - unsigned int infile_index; + int infile_index; const char *infile; const char *outfile; diff --git a/roms/ipxe/src/util/fixrom.pl b/roms/ipxe/src/util/fixrom.pl index c3a31f41e..dcc38fe4b 100755 --- a/roms/ipxe/src/util/fixrom.pl +++ b/roms/ipxe/src/util/fixrom.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; @@ -28,7 +29,13 @@ 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(); + my $image = $rom; + while ( $image ) { + $image->pnp_header->fix_checksum() if $image->pnp_header; + $image->undi_header->fix_checksum() if $image->undi_header; + $image->ipxe_header->fix_checksum() if $image->ipxe_header; + $image->fix_checksum(); + $image = $image->next_image(); + } $rom->save ( $romfile ); } diff --git a/roms/ipxe/src/util/fnrec.pl b/roms/ipxe/src/util/fnrec.pl index 9a2b3d81f..cc7312b61 100755 --- a/roms/ipxe/src/util/fnrec.pl +++ b/roms/ipxe/src/util/fnrec.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME diff --git a/roms/ipxe/src/util/geniso b/roms/ipxe/src/util/geniso index 790e7171d..48ea2f2aa 100755 --- a/roms/ipxe/src/util/geniso +++ b/roms/ipxe/src/util/geniso @@ -56,7 +56,7 @@ do g=${g//[^a-z0-9]}.krn case "$first" in "") - echo DEFAULT $g + echo DEFAULT $b ;; esac first=$g diff --git a/roms/ipxe/src/util/genkeymap.pl b/roms/ipxe/src/util/genkeymap.pl index d556df275..7a5024bf8 100755 --- a/roms/ipxe/src/util/genkeymap.pl +++ b/roms/ipxe/src/util/genkeymap.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME @@ -124,8 +125,10 @@ sub keysym_to_ascii { return unless $keysym; # Sanity check - die "Unexpected keysym ".sprintf ( "0x%04x\n", $keysym )."\n" - if $keysym & 0xf000; + if ( $keysym & 0xf000 ) { + warn "Unexpected keysym ".sprintf ( "0x%04x", $keysym )."\n"; + return; + } # Extract type and value my $type = ( $keysym >> 8 ); diff --git a/roms/ipxe/src/util/get-pci-ids b/roms/ipxe/src/util/get-pci-ids index 6501a7f7c..424662212 100755 --- a/roms/ipxe/src/util/get-pci-ids +++ b/roms/ipxe/src/util/get-pci-ids @@ -16,7 +16,8 @@ # You 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. # Known bugs/limitations: diff --git a/roms/ipxe/src/util/iccfix.c b/roms/ipxe/src/util/iccfix.c index 8b555c545..528bf4b26 100644 --- a/roms/ipxe/src/util/iccfix.c +++ b/roms/ipxe/src/util/iccfix.c @@ -2,6 +2,7 @@ #include <stddef.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> @@ -49,7 +50,7 @@ static int ICCFIX ( void *elf ) { ( align >= ICC_ALIGN_HACK_FACTOR ) ) { new_align = ( align / ICC_ALIGN_HACK_FACTOR ); shdr->sh_addralign = new_align; - dprintf ( "Section \"%s\": alignment %d->%d\n", + dprintf ( "Section \"%s\": alignment %ld->%ld\n", name, align, new_align ); } } diff --git a/roms/ipxe/src/util/licence.pl b/roms/ipxe/src/util/licence.pl index c37685d3a..0e43c7b4c 100755 --- a/roms/ipxe/src/util/licence.pl +++ b/roms/ipxe/src/util/licence.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/roms/ipxe/src/util/mergerom.pl b/roms/ipxe/src/util/mergerom.pl index f9c52502d..f5c1632b0 100755 --- a/roms/ipxe/src/util/mergerom.pl +++ b/roms/ipxe/src/util/mergerom.pl @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; @@ -43,9 +44,6 @@ 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 ); @@ -84,15 +82,36 @@ foreach my $rom ( @roms ) { merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset ); } + # Update iPXE header, if present + my $baserom_ipxe = $baserom->ipxe_header; + my $rom_ipxe = $rom->ipxe_header; + if ( $baserom_ipxe ) { + + # Update shrunk length + $baserom_ipxe->{shrunk_length} = ( $baserom->{length} + + ( $rom_ipxe ? + $rom_ipxe->{shrunk_length} : + $rom->{length} ) ); + + # Fix checksum + $baserom_ipxe->fix_checksum(); + } + + # Update base length + $baserom->{length} += $rom->{length}; + # Fix checksum for this ROM segment $rom->fix_checksum(); + # Add this ROM to base ROM + my $data = substr ( $baserom->get(), 0, $baserom->length() ); + $data .= $rom->get(); + $data .= $baserom->next_image()->get() if $baserom->next_image(); + $baserom->set ( $data ); + $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/roms/ipxe/src/util/niclist.pl b/roms/ipxe/src/util/niclist.pl new file mode 100755 index 000000000..0600c8232 --- /dev/null +++ b/roms/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 + + + +

    Network cards supported by iPXE

    + + +EOM + + # Output HTML header + push @output, "" + . join("", + map { "" } + @$column_names + ) + . ""; + + push @output, <<"EOM"; + + +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!! + . join("", + map { "" } + @columns + ) + . ""; + $counter++; + } + + push @output, <<'EOM'; + +
    " . HTML::Entities::encode($_) . "
    " . HTML::Entities::encode( $_ || "" ) . "
    + + + + + +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/roms/ipxe/src/util/nrv2b.c b/roms/ipxe/src/util/nrv2b.c index 6bac4cdda..031f5d9cb 100644 --- a/roms/ipxe/src/util/nrv2b.c +++ b/roms/ipxe/src/util/nrv2b.c @@ -77,7 +77,7 @@ static __inline__ void Error(char *message) /* These will be a complete waste of time on a lo-endian */ /* system, but it only gets done once so WTF. */ -static unsigned long i86ul_to_host(unsigned long ul) +static unsigned long __attribute__ (( unused )) i86ul_to_host(unsigned long ul) { unsigned long res = 0; int i; @@ -209,7 +209,7 @@ struct ucl_compress #define SWD_HSIZE 16384 #define SWD_MAX_CHAIN 2048 -#define SWD_BEST_OFF 1 +#undef SWD_BEST_OFF #define HEAD3(b,p) \ (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1)) @@ -375,7 +375,6 @@ static int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len) { unsigned int i = 0; - int c = 0; if (s->n == 0) s->n = N; @@ -439,7 +438,7 @@ static void swd_exit(struct ucl_swd *s) { /* unused s */ - + ( void ) s; } #define swd_pos2off(s,pos) \ diff --git a/roms/ipxe/src/util/parserom.pl b/roms/ipxe/src/util/parserom.pl old mode 100644 new mode 100755 index cf9f7c69b..e278e6336 --- a/roms/ipxe/src/util/parserom.pl +++ b/roms/ipxe/src/util/parserom.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/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 @@ -28,6 +28,7 @@ sub rom { $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"; @@ -49,7 +50,6 @@ while ( ) { \s*.*\s* # Driver data \)/x ) { ( my $vendor, my $device, my $image, my $desc ) = ( lc $1, lc $2, $3, $4 ); - next if ( $vendor eq "ffff" ) || ( $device eq "ffff" ); rom ( "pci", lc "${vendor}${device}", $desc, $vendor, $device ); rom ( "pci", $image, $desc, $vendor, $device, 1 ); } elsif ( /^\s*ISA_ROM\s*\( diff --git a/roms/ipxe/src/util/romcheck.pl b/roms/ipxe/src/util/romcheck.pl new file mode 100755 index 000000000..f47bb07e8 --- /dev/null +++ b/roms/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/roms/ipxe/src/util/zbin.c b/roms/ipxe/src/util/zbin.c index f0df5ea0d..0dabaf1e3 100644 --- a/roms/ipxe/src/util/zbin.c +++ b/roms/ipxe/src/util/zbin.c @@ -218,7 +218,8 @@ static int process_zinfo_pack ( struct input_file *input, return 0; } -static int process_zinfo_payl ( struct input_file *input, +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; @@ -229,20 +230,22 @@ static int process_zinfo_payl ( struct input_file *input, if ( DEBUG ) { fprintf ( stderr, "PAYL at %#zx\n", output->hdr_len ); } + return 0; } -static int process_zinfo_add ( struct input_file *input, +static int process_zinfo_add ( struct input_file *input + __attribute__ (( unused )), struct output_file *output, size_t len, - struct zinfo_add *add, + struct zinfo_add *add, size_t offset, size_t datasize ) { - size_t offset = add->offset; void *target; signed long addend; unsigned long size; signed long val; unsigned long mask; + offset += add->offset; if ( ( offset + datasize ) > output->len ) { fprintf ( stderr, "Add at %#zx outside output buffer\n", offset ); @@ -316,42 +319,90 @@ 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 ); + &zinfo->add, 0, 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 ); + &zinfo->add, 0, 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 ); + &zinfo->add, 0, 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 ); + &zinfo->add, 0, 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 ); + &zinfo->add, 0, 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 ); + &zinfo->add, 0, 4 ); +} + +static int process_zinfo_adpb ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 1 ); +} + +static int process_zinfo_adpw ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 2 ); +} + +static int process_zinfo_adpl ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 4 ); +} + +static int process_zinfo_appb ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 1 ); +} + +static int process_zinfo_appw ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 2 ); +} + +static int process_zinfo_appl ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 4 ); } struct zinfo_processor { @@ -371,6 +422,12 @@ static struct zinfo_processor zinfo_processors[] = { { "ADHB", process_zinfo_adhb }, { "ADHW", process_zinfo_adhw }, { "ADHL", process_zinfo_adhl }, + { "ADPB", process_zinfo_adpb }, + { "ADPW", process_zinfo_adpw }, + { "ADPL", process_zinfo_adpl }, + { "APPB", process_zinfo_appb }, + { "APPW", process_zinfo_appw }, + { "APPL", process_zinfo_appl }, }; static int process_zinfo ( struct input_file *input, diff --git a/roms/openbios/.gitignore b/roms/openbios/.gitignore index e6b5c5930..38e6dd89e 100644 --- a/roms/openbios/.gitignore +++ b/roms/openbios/.gitignore @@ -1,2 +1,3 @@ obj-* .stgit-* +config-host.mak diff --git a/roms/openbios/Makefile b/roms/openbios/Makefile index 74e462c8c..172f4507b 100644 --- a/roms/openbios/Makefile +++ b/roms/openbios/Makefile @@ -1,5 +1,4 @@ -ODIRS=$(wildcard obj-*) -TARGETS=$(subst obj-,,$(ODIRS)) +include config-host.mak all: requirements info build @@ -16,18 +15,24 @@ clean: $(MAKE) -C $$dir clean; \ done -build: - @printf "Building..." +build: start-build @for dir in $(ODIRS); do \ $(MAKE) -C $$dir > $$dir/build.log 2>&1 && echo "ok." || \ ( echo "error:"; tail -15 $$dir/build.log; exit 1 ) \ done -build-verbose: +SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGETS)) +SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) + +quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) + +build-verbose: start-build $(SUBDIR_RULES) + +subdir-%: + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C obj-$* V="$(V)" all,) + +start-build: @echo "Building..." - @for dir in $(ODIRS); do \ - $(MAKE) -C $$dir || exit 1; \ - done run: @echo "Running..." diff --git a/roms/openbios/Makefile.target b/roms/openbios/Makefile.target index 934b95a02..a7363e667 100644 --- a/roms/openbios/Makefile.target +++ b/roms/openbios/Makefile.target @@ -6,7 +6,6 @@ include config.mak ODIR := . -SRCDIR := .. HOSTCC := gcc HOSTCFLAGS+= -O2 -g -DFCOMPILER -DBOOTSTRAP $(CROSSCFLAGS) @@ -36,8 +35,15 @@ CFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d' INCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include AS_FLAGS+= -g +# FCode tokeniser +TOKE := toke + quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) +VPATH_SUFFIXES = %.c %.h %.S %.fs +set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) +$(call set-vpath, $(SRCDIR)) + # # pre rules # diff --git a/roms/openbios/VERSION b/roms/openbios/VERSION index d3827e75a..9459d4ba2 100644 --- a/roms/openbios/VERSION +++ b/roms/openbios/VERSION @@ -1 +1 @@ -1.0 +1.1 diff --git a/roms/openbios/arch/amd64/build.xml b/roms/openbios/arch/amd64/build.xml index 595f41fa0..8f436d001 100644 --- a/roms/openbios/arch/amd64/build.xml +++ b/roms/openbios/arch/amd64/build.xml @@ -1,5 +1,6 @@ + diff --git a/roms/openbios/arch/amd64/init.fs b/roms/openbios/arch/amd64/init.fs index 5b65dd103..fda3acdc8 100644 --- a/roms/openbios/arch/amd64/init.fs +++ b/roms/openbios/arch/amd64/init.fs @@ -1,3 +1,5 @@ +include config.fs + :noname ." Type 'help' for detailed information" cr \ ." boot secondary slave cdrom: " cr @@ -74,3 +76,8 @@ finish-device " keyboard" input ; CONSOLE-IN-initializer +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/roms/openbios/arch/ppc/build.xml b/roms/openbios/arch/ppc/build.xml index 846879941..29f6601f9 100644 --- a/roms/openbios/arch/ppc/build.xml +++ b/roms/openbios/arch/ppc/build.xml @@ -5,24 +5,28 @@ + + + + diff --git a/roms/openbios/arch/ppc/ppc.fs b/roms/openbios/arch/ppc/ppc.fs index ae1f640ee..0414f22c4 100644 --- a/roms/openbios/arch/ppc/ppc.fs +++ b/roms/openbios/arch/ppc/ppc.fs @@ -1,3 +1,8 @@ +include config.fs + +\ ------------------------------------------------------------------------- +\ registers +\ ------------------------------------------------------------------------- 0 value %cr 0 value %ctr @@ -45,3 +50,19 @@ 0 value %sprg1 0 value %sprg2 0 value %sprg3 + +\ ------------------------------------------------------------------------- +\ Load VGA FCode driver blob +\ ------------------------------------------------------------------------- + +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] + +\ ------------------------------------------------------------------------- +\ other +\ ------------------------------------------------------------------------- + +\ Set by BootX when booting Mac OS X +defer spin diff --git a/roms/openbios/arch/ppc/qemu/init.c b/roms/openbios/arch/ppc/qemu/init.c index 5e7fe03fa..345fc69e1 100644 --- a/roms/openbios/arch/ppc/qemu/init.c +++ b/roms/openbios/arch/ppc/qemu/init.c @@ -59,6 +59,14 @@ unexpected_excep(int vector) } } +extern void __divide_error(void); + +void +__divide_error(void) +{ + return; +} + enum { ARCH_PREP = 0, ARCH_MAC99, @@ -68,7 +76,7 @@ enum { int is_apple(void) { - return 1; + return is_oldworld() || is_newworld(); } int is_oldworld(void) @@ -255,7 +263,7 @@ cpu_generic_init(const struct cpudef *cpu) push_str("timebase-frequency"); fword("property"); - PUSH(fw_cfg_read_i32(FW_CFG_PPC_CPUFREQ)); + PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ)); fword("encode-int"); push_str("clock-frequency"); fword("property"); @@ -613,6 +621,22 @@ static void kvm_of_init(void) fword("finish-device"); } +/* + * filll ( addr bytes quad -- ) + */ + +static void ffilll(void) +{ + const u32 longval = POP(); + u32 bytes = POP(); + u32 *laddr = (u32 *)cell2pointer(POP()); + u32 len; + + for (len = 0; len < bytes / sizeof(u32); len++) { + *laddr++ = longval; + } +} + void arch_of_init(void) { @@ -720,6 +744,9 @@ arch_of_init(void) push_str("MacRISC"); fword("encode-string"); fword("encode+"); + push_str("MacRISC2"); + fword("encode-string"); + fword("encode+"); push_str("Power Macintosh"); fword("encode-string"); fword("encode+"); @@ -831,7 +858,7 @@ arch_of_init(void) } /* Setup default boot devices */ - snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt", boot_path, boot_path); + snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path); push_str(buf); fword("encode-string"); push_str("boot-device"); @@ -877,6 +904,9 @@ arch_of_init(void) device_end(); + /* Implementation of filll word (required by BootX) */ + bind_func("filll", ffilll); + bind_func("platform-boot", boot); bind_func("(go)", go); } diff --git a/roms/openbios/arch/ppc/qemu/main.c b/roms/openbios/arch/ppc/qemu/main.c index f9c1a531d..30a4375a0 100644 --- a/roms/openbios/arch/ppc/qemu/main.c +++ b/roms/openbios/arch/ppc/qemu/main.c @@ -39,141 +39,6 @@ #define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args) #define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args) -static char * -get_device( const char *path ) -{ - int i; - static char buf[1024]; - - for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++) - buf[i] = path[i]; - buf[i] = 0; - - return buf; -} - -static int -get_partition( const char *path ) -{ - while ( *path && *path != ':' ) - path++; - - if (!*path) - return -1; - path++; - - if (!strchr(path, ',')) /* check if there is a ',' */ - return -1; - - return atol(path); -} - -static char * -get_filename( const char * path , char **dirname) -{ - static char buf[1024]; - char *filename; - - while ( *path && *path != ':' ) - path++; - - if (!*path) { - *dirname = NULL; - return NULL; - } - path++; - - while ( *path && isdigit(*path) ) - path++; - - if (*path == ',') - path++; - - strncpy(buf, path, sizeof(buf)); - buf[sizeof(buf) - 1] = 0; - - filename = strrchr(buf, '\\'); - if (filename) { - *dirname = buf; - (*filename++) = 0; - } else { - *dirname = NULL; - filename = buf; - } - - return filename; -} - - -static void -encode_bootpath( const char *spec, const char *args ) -{ - char path[1024]; - phandle_t chosen_ph = find_dev("/chosen"); - char *filename, *directory; - int partition; - - if (spec) - return; - - filename = get_filename(spec, &directory); - partition = get_partition(spec); - if (partition == -1) - snprintf(path, sizeof(path), "%s:,%s\\%s", get_device(spec), - directory, filename); - else - snprintf(path, sizeof(path), "%s:%d,%s\\%s", get_device(spec), - partition, directory, filename); - - ELF_DPRINTF("bootpath %s bootargs %s\n", path, args); - set_property( chosen_ph, "bootpath", path, strlen(path)+1 ); - if (args) - set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); -} - -#define OLDWORLD_BOOTCODE_BASEADDR (0x3f4000) - -static void -oldworld_boot( void ) -{ - int fd; - int len, total; - const char *path = "hd:,%BOOT"; - char *bootcode; - - if ((fd = open_io(path)) == -1) { - ELF_DPRINTF("Can't open %s\n", path); - return; - } - - - total = 0; - bootcode = (char*)OLDWORLD_BOOTCODE_BASEADDR; - while(1) { - if (seek_io(fd, total) == -1) - break; - len = read_io(fd, bootcode, 512); - bootcode += len; - total += len; - } - - close_io( fd ); - - if (total == 0) { - ELF_DPRINTF("Can't read %s\n", path); - return; - } - - encode_bootpath(path, "Linux"); - - if( ofmem_claim( OLDWORLD_BOOTCODE_BASEADDR, total, 0 ) == -1 ) - fatal_error("Claim failed!\n"); - - call_elf(0, 0, OLDWORLD_BOOTCODE_BASEADDR); - - return; -} - static void check_preloaded_kernel(void) { unsigned long kernel_image, kernel_size; @@ -213,9 +78,5 @@ boot( void ) check_preloaded_kernel(); } - if (boot_device == 'c') { - oldworld_boot(); - } - update_nvram(); } diff --git a/roms/openbios/arch/ppc/qemu/ofmem.c b/roms/openbios/arch/ppc/qemu/ofmem.c index 25555a0f8..20e9a1adb 100644 --- a/roms/openbios/arch/ppc/qemu/ofmem.c +++ b/roms/openbios/arch/ppc/qemu/ofmem.c @@ -311,10 +311,32 @@ ea_to_phys(unsigned long ea, ucell *mode) return phys; } +/* Converts a global variable (from .data or .bss) into a pointer that + can be accessed from real mode */ +static void * +global_ptr_real(void *p) +{ + return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base()); +} + +/* Return the next slot to evict, in the range of [0..7] */ +static int +next_evicted_slot(void) +{ + static int next_grab_slot; + int *next_grab_slot_va; + int r; + + next_grab_slot_va = global_ptr_real(&next_grab_slot); + r = *next_grab_slot_va; + *next_grab_slot_va = (r + 1) % 8; + + return r; +} + static void hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode) { - static int next_grab_slot = 0; uint64_t vsid_mask, page_mask, pgidx, hash; uint64_t htab_mask, mask, avpn; unsigned long pgaddr; @@ -349,10 +371,8 @@ hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode) found = 1; /* out of slots, just evict one */ - if (!found) { - i = next_grab_slot + 1; - next_grab_slot = (next_grab_slot + 1) % 8; - } + if (!found) + i = next_evicted_slot() + 1; i--; { mPTE_64_t p = { @@ -381,7 +401,6 @@ static void hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode) { #ifndef __powerpc64__ - static int next_grab_slot = 0; unsigned long *upte, cmp, hash1; int i, vsid, found; mPTE_t *pp; @@ -407,10 +426,8 @@ hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode) found = 1; /* out of slots, just evict one */ - if (!found) { - i = next_grab_slot + 1; - next_grab_slot = (next_grab_slot + 1) % 8; - } + if (!found) + i = next_evicted_slot() + 1; i--; upte[i * 2] = cmp; upte[i * 2 + 1] = (phys & ~0xfff) | mode; @@ -532,11 +549,22 @@ ofmem_init(void) { ofmem_t *ofmem = ofmem_arch_get_private(); - ofmem_claim_phys(0, get_ram_bottom(), 0); - ofmem_claim_virt(0, get_ram_bottom(), 0); - ofmem_map(0, 0, get_ram_bottom(), 0); + /* Map the memory (don't map page 0 to allow catching of NULL dereferences) */ + ofmem_claim_phys(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + + /* Mark the first page as non-free */ + ofmem_claim_phys(0, PAGE_SIZE, 0); + ofmem_claim_virt(0, PAGE_SIZE, 0); - ofmem_claim_phys(get_ram_top(), ofmem->ramsize - get_ram_top(), 0); - ofmem_claim_virt(get_ram_top(), ofmem->ramsize - get_ram_top(), 0); - ofmem_map(get_ram_top(), get_ram_top(), ofmem->ramsize - get_ram_top(), 0); + /* Map everything at the top of physical RAM 1:1, minus the OpenBIOS ROM in RAM copy */ + ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + ofmem_claim_virt(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + ofmem_map(get_ram_top(), get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + + /* Map the OpenBIOS ROM in RAM copy */ + ofmem_claim_phys(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_SIZE, 0); + ofmem_claim_virt(OF_CODE_START, OF_CODE_SIZE, 0); + ofmem_map(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_START, OF_CODE_SIZE, 0); } diff --git a/roms/openbios/arch/ppc/qemu/qemu.fs b/roms/openbios/arch/ppc/qemu/qemu.fs index 339a5e92b..458af1bc7 100644 --- a/roms/openbios/arch/ppc/qemu/qemu.fs +++ b/roms/openbios/arch/ppc/qemu/qemu.fs @@ -46,6 +46,39 @@ then ; +variable keyboard-phandle 0 keyboard-phandle ! + +: (find-keyboard-device) ( phandle -- ) + recursive + keyboard-phandle @ 0= if \ Return first match + >dn.child @ + begin ?dup while + dup dup " device_type" rot get-package-property 0= if + drop dup cstrlen + " keyboard" strcmp 0= if + dup to keyboard-phandle + then + then + (find-keyboard-device) + >dn.peer @ + repeat + else + drop + then +; + +\ create the keyboard devalias +:noname + device-tree @ (find-keyboard-device) + keyboard-phandle @ if + active-package + " /aliases" find-device + keyboard-phandle @ get-package-path + encode-string " keyboard" property + active-package! + then +; SYSTEM-initializer + \ ------------------------------------------------------------------------- \ pre-booting \ ------------------------------------------------------------------------- diff --git a/roms/openbios/arch/ppc/qemu/start.S b/roms/openbios/arch/ppc/qemu/start.S index 77ced189e..db8e860a8 100644 --- a/roms/openbios/arch/ppc/qemu/start.S +++ b/roms/openbios/arch/ppc/qemu/start.S @@ -295,8 +295,15 @@ call_isi_exception: exception_return: EXCEPTION_EPILOGUE -_GLOBAL(__divide_error): trap_error: + lis r1, 0x8000 /* r1=0x80000000 */ + add. r1,r1,r1 /* r1=r1+r1 (high 32bit !0) */ + beq 1f + + mfmsr r1 /* unset MSR_SF */ + clrldi r1,r1,1 + mtmsrd r1 +1: mflr r3 LOAD_REG_FUNC(r4, unexpected_excep) mtctr r4 diff --git a/roms/openbios/arch/sparc32/boot.h b/roms/openbios/arch/sparc32/boot.h index fa701e55c..55e391ac5 100644 --- a/roms/openbios/arch/sparc32/boot.h +++ b/roms/openbios/arch/sparc32/boot.h @@ -22,9 +22,6 @@ extern void go(void); extern unsigned int qemu_mem_size; extern void collect_sys_info(struct sys_info *info); -// console.c -void cls(void); - // romvec.c extern struct linux_arguments_v0 obp_arg; extern const void *romvec; diff --git a/roms/openbios/arch/sparc32/build.xml b/roms/openbios/arch/sparc32/build.xml index 47ad01ae8..035c25c41 100644 --- a/roms/openbios/arch/sparc32/build.xml +++ b/roms/openbios/arch/sparc32/build.xml @@ -3,6 +3,7 @@ + diff --git a/roms/openbios/arch/sparc32/console.c b/roms/openbios/arch/sparc32/console.c index 2bcdf0216..91587fcfb 100644 --- a/roms/openbios/arch/sparc32/console.c +++ b/roms/openbios/arch/sparc32/console.c @@ -9,10 +9,8 @@ #include "kernel/kernel.h" #include "drivers/drivers.h" #include "openbios.h" -#include "libopenbios/console.h" #include "libopenbios/ofmem.h" - -void cls(void); +#include "libopenbios/video.h" #ifdef CONFIG_DEBUG_CONSOLE @@ -30,26 +28,26 @@ void cls(void); unsigned char *vmem; volatile uint32_t *dac; -static void video_putchar(int c) -{ - char buf; - - buf = c & 0xff; - - console_draw_fstr(&buf, 1); -} - -static void video_cls(void) -{ - memset((void *)vmem, 0, VMEM_SIZE); -} - void tcx_init(uint64_t base) { vmem = (unsigned char *)ofmem_map_io(base + VMEM_BASE, VMEM_SIZE); dac = (uint32_t *)ofmem_map_io(base + DAC_BASE, DAC_SIZE); +} - console_init(); +/* ( r g b index -- ) */ +void tcx_hw_set_color(void) +{ + int index = POP(); + int b = POP(); + int g = POP(); + int r = POP(); + + if( VIDEO_DICT_VALUE(video.depth) == 8 ) { + dac[0] = index << 24; + dac[1] = r << 24; // Red + dac[1] = g << 24; // Green + dac[1] = b << 24; // Blue + } } #endif @@ -62,9 +60,6 @@ int putchar(int c) { #ifdef CONFIG_DEBUG_CONSOLE_SERIAL serial_putchar(c); -#endif -#ifdef CONFIG_DEBUG_CONSOLE_VIDEO - video_putchar(c); #endif return c; } @@ -95,15 +90,4 @@ int getchar(void) return 0; } -void cls(void) -{ -#ifdef CONFIG_DEBUG_CONSOLE_SERIAL - serial_cls(); -#endif -#ifdef CONFIG_DEBUG_CONSOLE_VIDEO - video_cls(); -#endif -} - - #endif // CONFIG_DEBUG_CONSOLE diff --git a/roms/openbios/arch/sparc32/entry.S b/roms/openbios/arch/sparc32/entry.S index 24c4cbff0..4bdd7a65d 100644 --- a/roms/openbios/arch/sparc32/entry.S +++ b/roms/openbios/arch/sparc32/entry.S @@ -452,6 +452,7 @@ highmem: wr %g3, PSR_ET, %psr WRITE_PAUSE + set 0, %fp call __switch_context_nosave nop diff --git a/roms/openbios/arch/sparc32/init.fs b/roms/openbios/arch/sparc32/init.fs index 7306eab0d..e2cd571a7 100644 --- a/roms/openbios/arch/sparc32/init.fs +++ b/roms/openbios/arch/sparc32/init.fs @@ -32,7 +32,7 @@ \ preopen device nodes (and store the ihandles under /chosen) :noname " memory" " /memory" preopen - " mmu" " /cpus/@0" preopen + " mmu" " /virtual-memory" preopen ; SYSTEM-initializer device-end @@ -45,3 +45,9 @@ device-end : obmem ( -- space ) 0 ; + +\ Load TCX FCode driver blob +[IFDEF] CONFIG_DRIVER_SBUS + -1 value tcx-driver-fcode + " QEMU,tcx.bin" $encode-file to tcx-driver-fcode +[THEN] diff --git a/roms/openbios/arch/sparc32/lib.c b/roms/openbios/arch/sparc32/lib.c index 483069cc8..81d30ad9e 100644 --- a/roms/openbios/arch/sparc32/lib.c +++ b/roms/openbios/arch/sparc32/lib.c @@ -269,6 +269,8 @@ char *obp_memalloc(char *va, unsigned int size, unsigned int align) phys_addr_t phys; ucell virt; + DPRINTF("obp_memalloc: virta 0x%x, sz %d, align %d\n", (unsigned int)va, size, align); + /* Claim physical memory */ phys = ofmem_claim_phys(-1, size, align); @@ -283,26 +285,14 @@ char *obp_memalloc(char *va, unsigned int size, unsigned int align) char *obp_dumb_memalloc(char *va, unsigned int size) { - unsigned long align; - int i; + unsigned long align = size; + + DPRINTF("obp_dumb_memalloc: virta 0x%x, sz %d\n", (unsigned int)va, size); + + /* Solaris seems to assume that the returned value is physically aligned to size. + e.g. it is used for setting up page tables. Fortunately this is now handled by + ofmem_claim_phys() above. */ - /* Solaris seems to assume that the returned value is physically aligned to size. For - example, not having this here causes the Solaris 8 kernel to fault because the - IOMMU page table base address is calculated incorrectly. */ - - /* Enforce a minimum alignment of CONFIG_OFMEM_MALLOC_ALIGN, and choose an alignment - which is the next power of 2 higher than the specified size */ - align = size; - if (align <= CONFIG_OFMEM_MALLOC_ALIGN) { - align = CONFIG_OFMEM_MALLOC_ALIGN; - } else { - align--; - for (i = 1; i < sizeof(unsigned long) * 8; i<<=1) { - align |= align >> i; - } - align++; - } - return obp_memalloc(va, size, align); } @@ -401,9 +391,11 @@ init_mmu_swift(void) size = (unsigned long)&_end - (unsigned long)&_start; pa = va2pa(va); ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa)); + ofmem_map_page_range(pa, va, size, ofmem_arch_default_translation_mode(pa)); - // 1:1 mapping for RAM - ofmem_arch_map_pages(0, 0, LOWMEMSZ, ofmem_arch_default_translation_mode(0)); + // 1:1 mapping for RAM (don't map page 0 to allow catching of NULL dereferences) + ofmem_arch_map_pages(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0)); + ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0)); /* * Flush cache diff --git a/roms/openbios/arch/sparc32/ofmem_sparc32.c b/roms/openbios/arch/sparc32/ofmem_sparc32.c index e2f4159c1..2767b7bf3 100644 --- a/roms/openbios/arch/sparc32/ofmem_sparc32.c +++ b/roms/openbios/arch/sparc32/ofmem_sparc32.c @@ -61,7 +61,7 @@ ucell ofmem_arch_get_heap_top(void) ucell ofmem_arch_get_virt_top(void) { - return (ucell)TOP_OF_RAM; + return (ucell)OFMEM_VIRT_TOP; } phys_addr_t ofmem_arch_get_phys_top(void) @@ -238,6 +238,9 @@ void ofmem_init( void ) memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); s_ofmem_data.ofmem.ramsize = qemu_mem_size; + /* Mark the first page as non-free */ + ofmem_claim_virt(0, PAGE_SIZE, 0); + /* Claim reserved physical addresses at top of RAM */ ofmem_claim_phys(ofmem_arch_get_phys_top(), s_ofmem_data.ofmem.ramsize - ofmem_arch_get_phys_top(), 0); diff --git a/roms/openbios/arch/sparc32/openbios.c b/roms/openbios/arch/sparc32/openbios.c index b016be715..40948d1cd 100644 --- a/roms/openbios/arch/sparc32/openbios.c +++ b/roms/openbios/arch/sparc32/openbios.c @@ -22,12 +22,12 @@ #include "boot.h" #include "romvec.h" #include "openprom.h" -#include "packages/video.h" +#include "libopenbios/video.h" #define NO_QEMU_PROTOS #include "arch/common/fw_cfg.h" -#include "libopenbios/ofmem.h" +#include "arch/sparc32/ofmem_sparc32.h" -#define MEMORY_SIZE (512*1024) /* 512K ram for hosted system */ +#define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */ #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" #define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00) @@ -244,9 +244,9 @@ static const struct cpudef sparc_defs[] = { .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ .name = "FMI,MB86904", .psr_impl = 0, - .psr_vers = 5, + .psr_vers = 4, .impl = 0, - .vers = 5, + .vers = 4, .dcache_line_size = 0x10, .dcache_lines = 0x200, .dcache_assoc = 1, @@ -813,7 +813,7 @@ static void init_memory(void) if (!phys) printk("panic: not enough physical memory on host system.\n"); - virt = ofmem_claim_virt(-1, MEMORY_SIZE, PAGE_SIZE); + virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0); if (!virt) printk("panic: not enough virtual memory on host system.\n"); @@ -832,8 +832,7 @@ static void init_memory(void) static void arch_init( void ) { - static char cmdline[128]; - int size = 0; + char *cmdline; const char *kernel_cmdline; uint32_t temp; uint16_t machine_id; @@ -876,7 +875,7 @@ arch_init( void ) #endif #ifdef CONFIG_DRIVER_SBUS #ifdef CONFIG_DEBUG_CONSOLE_VIDEO - init_video((unsigned long)vmem, 1024, 768, 8, 1024); + setup_video(hwdef->tcx_base + 0x00800000ULL, (unsigned long)vmem); #endif ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type); #endif @@ -894,11 +893,11 @@ arch_init( void ) kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); if (kernel_cmdline) { - size = strlen(kernel_cmdline); - memcpy(cmdline, kernel_cmdline, size); + cmdline = strdup(kernel_cmdline); obp_arg.argv[1] = cmdline; - } - cmdline[size] = '\0'; + } else { + cmdline = strdup(""); + } qemu_cmdline = (uint32_t)cmdline; /* Setup nvram variables */ @@ -972,8 +971,6 @@ int openbios(void) tcx_init(hwdef->tcx_base); kbd_init(hwdef->ms_kb_base); #endif - /* Clear the screen. */ - cls(); #endif collect_sys_info(&sys_info); diff --git a/roms/openbios/arch/sparc32/tree.fs b/roms/openbios/arch/sparc32/tree.fs index f9a04064d..0f31f4ff1 100644 --- a/roms/openbios/arch/sparc32/tree.fs +++ b/roms/openbios/arch/sparc32/tree.fs @@ -1,3 +1,4 @@ +include config.fs " /" find-device 2 encode-int " #address-cells" property diff --git a/roms/openbios/arch/sparc32/wuf.S b/roms/openbios/arch/sparc32/wuf.S index a477a3eae..853fc7322 100644 --- a/roms/openbios/arch/sparc32/wuf.S +++ b/roms/openbios/arch/sparc32/wuf.S @@ -131,6 +131,7 @@ fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1 /* LOCATION: Window 'O' */ restore %g0, %g0, %g0 + WRITE_PAUSE /* LOCATION: Window 'W' */ diff --git a/roms/openbios/arch/sparc64/build.xml b/roms/openbios/arch/sparc64/build.xml index 54807c580..3a1cd346a 100644 --- a/roms/openbios/arch/sparc64/build.xml +++ b/roms/openbios/arch/sparc64/build.xml @@ -3,6 +3,7 @@ + diff --git a/roms/openbios/arch/sparc64/console.c b/roms/openbios/arch/sparc64/console.c index b4b4b767c..ec7571c17 100644 --- a/roms/openbios/arch/sparc64/console.c +++ b/roms/openbios/arch/sparc64/console.c @@ -58,16 +58,4 @@ int getchar(void) return 0; } -void cls(void) -{ -#ifdef CONFIG_DEBUG_CONSOLE_SERIAL - serial_putchar(27); - serial_putchar('['); - serial_putchar('H'); - serial_putchar(27); - serial_putchar('['); - serial_putchar('J'); -#endif -} - #endif // CONFIG_DEBUG_CONSOLE diff --git a/roms/openbios/arch/sparc64/init.fs b/roms/openbios/arch/sparc64/init.fs index a1cadc1e9..eb6c9da52 100644 --- a/roms/openbios/arch/sparc64/init.fs +++ b/roms/openbios/arch/sparc64/init.fs @@ -53,3 +53,9 @@ device-end : rmap@ ( virt -- rmentry ) drop 0 ; + +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/roms/openbios/arch/sparc64/openbios.c b/roms/openbios/arch/sparc64/openbios.c index 3b372b9d1..b1e5f476b 100644 --- a/roms/openbios/arch/sparc64/openbios.c +++ b/roms/openbios/arch/sparc64/openbios.c @@ -42,9 +42,6 @@ #define NVRAM_OB_START (0) #define NVRAM_OB_SIZE ((0x1fd0 - NVRAM_OB_START) & ~15) -#define OBIO_CMDLINE_MAX 256 -static char obio_cmdline[OBIO_CMDLINE_MAX]; - static uint8_t idprom[NVRAM_IDPROM_SIZE]; struct hwdef { @@ -370,6 +367,7 @@ static uint8_t qemu_uuid[16]; void arch_nvram_get(char *data) { + char *obio_cmdline; uint32_t size = 0; const struct cpudef *cpu; char buf[256]; @@ -401,12 +399,13 @@ void arch_nvram_get(char *data) kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR); size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); - if (size > OBIO_CMDLINE_MAX - 1) - size = OBIO_CMDLINE_MAX - 1; if (size) { + obio_cmdline = (char *)malloc(size + 1); fw_cfg_read(FW_CFG_CMDLINE_DATA, obio_cmdline, size); + obio_cmdline[size] = '\0'; + } else { + obio_cmdline = strdup(""); } - obio_cmdline[size] = '\0'; qemu_cmdline = (uint64_t)obio_cmdline; cmdline_size = size; boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); @@ -548,6 +547,9 @@ void setup_timers(void) void udelay(unsigned int usecs) { + volatile int i; + + for (i = 0; i < usecs * 100; i++); } static void init_memory(void) @@ -617,8 +619,6 @@ int openbios(void) #ifdef CONFIG_DEBUG_CONSOLE_SERIAL uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED); #endif - /* Clear the screen. */ - cls(); printk("OpenBIOS for Sparc64\n"); #endif diff --git a/roms/openbios/arch/sparc64/tree.fs b/roms/openbios/arch/sparc64/tree.fs index e15c0b597..e034b5931 100644 --- a/roms/openbios/arch/sparc64/tree.fs +++ b/roms/openbios/arch/sparc64/tree.fs @@ -1,3 +1,5 @@ +include config.fs + \ ------------------------------------------------------------------------- \ UPA encode/decode unit \ ------------------------------------------------------------------------- diff --git a/roms/openbios/arch/unix/unix.c b/roms/openbios/arch/unix/unix.c index e5c4590fd..65e67bc36 100644 --- a/roms/openbios/arch/unix/unix.c +++ b/roms/openbios/arch/unix/unix.c @@ -82,6 +82,26 @@ void flush_icache_range(char *start, char *stop) } #endif +#ifdef CONFIG_PPC +/* Expose system level is_machine helpers to make generic code easier */ + +#include "drivers/drivers.h" +int is_apple(void) +{ + return 0; +} + +int is_oldworld(void) +{ + return 0; +} + +int is_newworld(void) +{ + return 0; +} +#endif + #if 0 static void write_dictionary(char *filename) { diff --git a/roms/openbios/arch/x86/build.xml b/roms/openbios/arch/x86/build.xml index 02cecce43..260a33258 100644 --- a/roms/openbios/arch/x86/build.xml +++ b/roms/openbios/arch/x86/build.xml @@ -2,6 +2,7 @@ + diff --git a/roms/openbios/arch/x86/init.fs b/roms/openbios/arch/x86/init.fs index 9607824fd..eef72e9b2 100644 --- a/roms/openbios/arch/x86/init.fs +++ b/roms/openbios/arch/x86/init.fs @@ -1,3 +1,5 @@ +include config.fs + :noname ." Type 'help' for detailed information" cr \ ." boot secondary slave cdrom: " cr @@ -74,3 +76,9 @@ finish-device :noname " keyboard" input ; CONSOLE-IN-initializer + +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/roms/openbios/arch/x86/openbios.c b/roms/openbios/arch/x86/openbios.c index dd444faba..4c1895256 100644 --- a/roms/openbios/arch/x86/openbios.c +++ b/roms/openbios/arch/x86/openbios.c @@ -16,6 +16,7 @@ #include "drivers/drivers.h" #include "drivers/pci.h" #include "libopenbios/sys_info.h" +#include "libopenbios/video.h" #include "openbios.h" #include "relocate.h" #include "boot.h" @@ -61,7 +62,12 @@ arch_init( void ) ob_floppy_init("/isa", "floppy0", 0x3f0, 0); #endif #ifdef CONFIG_XBOX - init_video(phys_to_virt(0x3C00000), 640, 480, 32, 2560); + setup_video(0x3C00000, phys_to_virt(0x3C00000)); + + /* Force video to 32-bit depth */ + VIDEO_DICT_VALUE(video.depth) = 32; + + init_video(); node_methods_init(); #endif device_end(); diff --git a/roms/openbios/config/examples/amd64_config.xml b/roms/openbios/config/examples/amd64_config.xml index 33d4267d1..e8904b78d 100644 --- a/roms/openbios/config/examples/amd64_config.xml +++ b/roms/openbios/config/examples/amd64_config.xml @@ -58,3 +58,4 @@