diff --git a/src/Makefile b/src/Makefile index 4da6b583..c8516a50 100644 --- a/src/Makefile +++ b/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 diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 41c59562..d2b4ee38 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -381,6 +381,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 +412,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 @@ -514,6 +517,136 @@ 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 +# +KEY_LIST := $(BIN)/.private_key.list +ifeq ($(wildcard $(KEY_LIST)),) +KEY_OLD := +else +KEY_OLD := $(shell cat $(KEY_LIST)) +endif +ifneq ($(KEY_OLD),$(KEY)) +$(shell $(ECHO) "$(KEY)" > $(KEY_LIST)) +endif + +$(KEY_LIST) : + +VERYCLEANUP += $(KEY_LIST) + +# Embedded client private key +# +KEY_INC := $(BIN)/.private_key.der + +ifdef KEY +$(KEY_INC) : $(KEY) $(KEY_LIST) + $(Q)$(OPENSSL) rsa -in $< -outform DER -out $@ + +clientcert_DEPS += $(KEY_INC) +endif + +CLEANUP += $(KEY_INC) + +clientcert_DEPS += $(KEY_LIST) + +CFLAGS_clientcert += $(if $(KEY),-DPRIVATE_KEY="\"$(KEY_INC)\"") + +# These files use .incbin inline assembly to include a binary file. +# Unfortunately ccache does not detect this dependency and caches +# builds even when the binary file has changed. +# +$(BIN)/embedded.o : override CC := env CCACHE_DISABLE=1 $(CC) + +$(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC) + # We automatically generate rules for any file mentioned in AUTO_SRCS # using the following set of templates. It would be cleaner to use # $(eval ...), but this function exists only in GNU make >= 3.80. @@ -529,7 +662,7 @@ define deps_template @$(MKDIR) -p $(BIN)/deps/$(dir $(1)) @$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ -Wno-error -M $(1) -MG -MP | \ - sed 's/\.o\s*:/_DEPS =/' > $(BIN)/deps/$(1).d + sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d endef # rules_template : generate rules for a given source file @@ -603,40 +736,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. -# -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)))\" )) - -$(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 @@ -961,13 +1060,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) ############################################################################### @@ -975,23 +1074,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) ############################################################################### @@ -1000,7 +1101,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) ############################################################################### @@ -1009,7 +1110,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/src/arch/i386/Makefile b/src/arch/i386/Makefile index 3261fff3..ca258330 100644 --- a/src/arch/i386/Makefile +++ b/src/arch/i386/Makefile @@ -85,15 +85,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/src/arch/i386/core/aout_loader.c b/src/arch/i386/core/aout_loader.c deleted file mode 100644 index f85620e9..00000000 --- a/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/src/arch/i386/core/freebsd_loader.c b/src/arch/i386/core/freebsd_loader.c deleted file mode 100644 index 464f6d93..00000000 --- a/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/src/arch/i386/core/runtime.c b/src/arch/i386/core/runtime.c index 2053bf21..fcfec060 100644 --- a/src/arch/i386/core/runtime.c +++ b/src/arch/i386/core/runtime.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -189,19 +190,25 @@ static int initrd_init ( void ) { initrd_phys, ( initrd_phys + initrd_len ) ); /* Allocate image */ - image = alloc_image(); + image = alloc_image ( NULL ); if ( ! image ) { DBGC ( colour, "RUNTIME could not allocate image for " "initrd\n" ); + rc = -ENOMEM; goto err_alloc_image; } - image_set_name ( 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 %zd bytes for " + DBGC ( colour, "RUNTIME could not allocate %d bytes for " "initrd\n", initrd_len ); + rc = -ENOMEM; goto err_umalloc; } image->len = initrd_len; @@ -225,6 +232,7 @@ static int initrd_init ( void ) { err_register_image: err_umalloc: + err_set_name: image_put ( image ); err_alloc_image: return rc; diff --git a/src/arch/i386/core/video_subr.c b/src/arch/i386/core/video_subr.c index 6885ad9a..306c6d56 100644 --- a/src/arch/i386/core/video_subr.c +++ b/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/src/arch/i386/core/wince_loader.c b/src/arch/i386/core/wince_loader.c deleted file mode 100644 index f452b659..00000000 --- a/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/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 1a05be9b..f0c9cc46 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -166,6 +167,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 * @@ -175,8 +180,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 @@ -189,15 +200,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 ); diff --git a/src/arch/i386/firmware/pcbios/bios_console.c b/src/arch/i386/firmware/pcbios/bios_console.c index 1ecd07dd..7f9892fc 100644 --- a/src/arch/i386/firmware/pcbios/bios_console.c +++ b/src/arch/i386/firmware/pcbios/bios_console.c @@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #define ATTR_BOLD 0x08 @@ -48,6 +49,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 +170,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 +216,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 +328,5 @@ struct console_driver bios_console __console_driver = { .putchar = bios_putchar, .getchar = bios_getchar, .iskey = bios_iskey, + .usage = CONSOLE_PCBIOS, }; diff --git a/src/arch/i386/image/elfboot.c b/src/arch/i386/image/elfboot.c index 89e70a3b..21504b7a 100644 --- a/src/arch/i386/image/elfboot.c +++ b/src/arch/i386/image/elfboot.c @@ -42,10 +42,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/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index 15e8fd52..004a01b1 100644 --- a/src/arch/i386/image/multiboot.c +++ b/src/arch/i386/image/multiboot.c @@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 ); @@ -139,53 +140,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; +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; - if ( ! cmdline ) - cmdline = ""; + /* 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 */ - 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 ); + /* 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 +203,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 ) ) ); + + /* Copy module */ + memcpy_user ( phys_to_user ( start ), 0, + module_image->data, 0, module_image->len ); + + /* Add module to list */ + module = &modules[mbinfo->mods_count++]; module->mod_start = start; - module->mod_end = end; - module->string = multiboot_add_cmdline ( module_image->name, - module_image->cmdline ); + module->mod_end = ( start + module_image->len ); + module->string = multiboot_add_cmdline ( module_image ); module->reserved = 0; - - /* We promise to page-align modules */ - assert ( ( module->mod_start & 0xfff ) == 0 ); - - count++; + DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n", + image, module_image->name, module->mod_start, + module->mod_end ); + start += 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 ); - } - - return count; + return 0; } /** @@ -305,11 +311,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 +347,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 +359,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 +385,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 +407,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 +416,14 @@ 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 ); 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/src/arch/i386/include/bios.h b/src/arch/i386/include/bios.h index 70bb73da..fadb9f1b 100644 --- a/src/arch/i386/include/bios.h +++ b/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/src/arch/i386/include/bits/byteswap.h b/src/arch/i386/include/bits/byteswap.h index ddbd40ed..f3d30a25 100644 --- a/src/arch/i386/include/bits/byteswap.h +++ b/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 ) ); } -#endif /* ETHERBOOT_BITS_BYTESWAP_H */ +static inline __attribute__ (( always_inline, const )) uint64_t +__bswap_variable_64 ( uint64_t x ) { + uint32_t in_high = ( x >> 32 ); + uint32_t in_low = ( x & 0xffffffffUL ); + uint32_t out_high; + uint32_t out_low; + + __asm__ ( "bswapl %0\n\t" + "bswapl %1\n\t" + "xchgl %0,%1\n\t" + : "=r" ( out_high ), "=r" ( out_low ) + : "0" ( in_high ), "1" ( in_low ) ); + + return ( ( ( ( uint64_t ) out_high ) << 32 ) | + ( ( uint64_t ) out_low ) ); +} + +static inline __attribute__ (( always_inline )) void +__bswap_64s ( uint64_t *x ) { + struct { + uint32_t low; + uint32_t high; + } __attribute__ (( may_alias )) *dwords = ( ( void * ) x ); + uint32_t discard; + + __asm__ ( "movl %0,%2\n\t" + "bswapl %2\n\t" + "xchgl %2,%1\n\t" + "bswapl %2\n\t" + "movl %2,%0\n\t" + : "+m" ( dwords->low ), "+m" ( dwords->high ), + "=r" ( discard ) ); +} + +#endif /* _BITS_BYTESWAP_H */ diff --git a/src/arch/i386/include/bits/entropy.h b/src/arch/i386/include/bits/entropy.h new file mode 100644 index 00000000..6dcceec6 --- /dev/null +++ b/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/src/arch/i386/include/bits/errfile.h b/src/arch/i386/include/bits/errfile.h index 93f34f8d..ccf00b86 100644 --- a/src/arch/i386/include/bits/errfile.h +++ b/src/arch/i386/include/bits/errfile.h @@ -16,6 +16,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 ) diff --git a/src/arch/i386/include/bits/time.h b/src/arch/i386/include/bits/time.h new file mode 100644 index 00000000..24dd020e --- /dev/null +++ b/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/src/arch/i386/include/int13.h b/src/arch/i386/include/int13.h index 0244acaf..5d36b637 100644 --- a/src/arch/i386/include/int13.h +++ b/src/arch/i386/include/int13.h @@ -71,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 */ @@ -394,4 +407,43 @@ enum eltorito_media_type { ELTORITO_NO_EMULATION = 0, }; +/** A floppy disk geometry */ +struct int13_fdd_geometry { + /** Number of tracks */ + uint8_t tracks; + /** Number of heads and sectors per track */ + uint8_t heads_spt; +}; + +/** Define a floppy disk geometry */ +#define INT13_FDD_GEOMETRY( cylinders, heads, sectors ) \ + { \ + .tracks = (cylinders), \ + .heads_spt = ( ( (heads) << 6 ) | (sectors) ), \ + } + +/** Get floppy disk number of cylinders */ +#define INT13_FDD_CYLINDERS( geometry ) ( (geometry)->tracks ) + +/** Get floppy disk number of heads */ +#define INT13_FDD_HEADS( geometry ) ( (geometry)->heads_spt >> 6 ) + +/** Get floppy disk number of sectors per track */ +#define INT13_FDD_SECTORS( geometry ) ( (geometry)->heads_spt & 0x3f ) + +/** A floppy drive parameter table */ +struct int13_fdd_parameters { + uint8_t step_rate__head_unload; + uint8_t head_load__ndma; + uint8_t motor_off_delay; + uint8_t bytes_per_sector; + uint8_t sectors_per_track; + uint8_t gap_length; + uint8_t data_length; + uint8_t format_gap_length; + uint8_t format_filler; + uint8_t head_settle_time; + uint8_t motor_start_time; +} __attribute__ (( packed )); + #endif /* INT13_H */ diff --git a/src/arch/i386/include/ipxe/guestrpc.h b/src/arch/i386/include/ipxe/guestrpc.h new file mode 100644 index 00000000..72a0f714 --- /dev/null +++ b/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/src/arch/i386/include/ipxe/rtc_entropy.h b/src/arch/i386/include/ipxe/rtc_entropy.h new file mode 100644 index 00000000..6c3cf210 --- /dev/null +++ b/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/src/arch/i386/include/ipxe/rtc_time.h b/src/arch/i386/include/ipxe/rtc_time.h new file mode 100644 index 00000000..c0dfe3f8 --- /dev/null +++ b/src/arch/i386/include/ipxe/rtc_time.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_RTC_TIME_H +#define _IPXE_RTC_TIME_H + +/** @file + * + * RTC-based time source + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef TIME_RTC +#define TIME_PREFIX_rtc +#else +#define TIME_PREFIX_rtc __rtc_ +#endif + +#endif /* _IPXE_RTC_TIME_H */ diff --git a/src/arch/i386/include/ipxe/vmware.h b/src/arch/i386/include/ipxe/vmware.h new file mode 100644 index 00000000..2ac65f43 --- /dev/null +++ b/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/src/arch/i386/include/pic8259.h b/src/arch/i386/include/pic8259.h index f8e20c4c..a07e97d3 100644 --- a/src/arch/i386/include/pic8259.h +++ b/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/src/arch/i386/include/rtc.h b/src/arch/i386/include/rtc.h new file mode 100644 index 00000000..2a6abbae --- /dev/null +++ b/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/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c index 8ce77ada..0a1e7748 100644 --- a/src/arch/i386/interface/pcbios/int13.c +++ b/src/arch/i386/interface/pcbios/int13.c @@ -75,9 +75,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 @@ -142,17 +142,44 @@ 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 * - * 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. + * This is a cached copy of the BIOS Data Area equipment word at + * 40:10. */ -static uint8_t num_drives; +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 @@ -160,7 +187,7 @@ static uint8_t num_drives; * @v int13 Emulated drive * @ret blksize Sector size */ -static inline unsigned int int13_blksize ( struct int13_drive *int13 ) { +static inline size_t int13_blksize ( struct int13_drive *int13 ) { return ( int13->capacity.blksize << int13->blksize_shift ); } @@ -185,6 +212,16 @@ static inline uint32_t int13_capacity32 ( struct int13_drive *int13 ) { return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff ); } +/** + * Test if INT 13 drive is a floppy disk drive + * + * @v int13 Emulated drive + * @ret is_fdd Emulated drive is a floppy disk + */ +static inline int int13_is_fdd ( struct int13_drive *int13 ) { + return ( ! ( int13->drive & 0x80 ) ); +} + /** An INT 13 command */ struct int13_command { /** Status */ @@ -499,33 +536,33 @@ static int int13_parse_iso9660 ( struct int13_drive *int13, void *scratch ) { } /** - * Guess INT 13 drive geometry + * 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, void *scratch ) { +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 int blocks; - unsigned int blocks_per_cyl; unsigned int i; int rc; - /* Don't even try when the blksize is invalid for C/H/S access */ - if ( int13_blksize ( int13 ) != 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 ), 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; } @@ -534,25 +571,126 @@ static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) { DBGC ( int13, "INT13 drive %02x has signature %08x\n", int13->drive, mbr->signature ); - /* Scan through partition table and modify guesses for heads - * and sectors_per_track if we find any used partitions. + /* Scan through partition table and modify guesses for + * heads and sectors_per_track if we find any used + * partitions. */ for ( i = 0 ; i < 4 ; i++ ) { partition = &mbr->partitions[i]; if ( ! partition->type ) continue; - 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_blksize ( int13 ); + const struct int13_fdd_geometry *geometry; + unsigned int cylinders; + unsigned int i; + + /* Look for a match against a known geometry */ + for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) / + sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) { + geometry = &int13_fdd_geometries[i]; + cylinders = INT13_FDD_CYLINDERS ( geometry ); + *heads = INT13_FDD_HEADS ( geometry ); + *sectors = INT13_FDD_SECTORS ( geometry ); + if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) { + DBGC ( int13, "INT13 drive %02x guessing C/H/S " + "%d/%d/%d based on size %dK\n", int13->drive, + cylinders, *heads, *sectors, ( blocks / 2 ) ); + return 0; + } + } + + /* Otherwise, assume a partial disk image in the most common + * format (1440K, 80/2/18). + */ + *heads = 2; + *sectors = 18; + DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based on size " + "%dK\n", int13->drive, *heads, *sectors, ( blocks / 2 ) ); + return 0; +} + +/** + * Guess INT 13 drive geometry + * + * @v int13 Emulated drive + * @v scratch Scratch area for single-sector reads + * @ret rc Return status code + */ +static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) { + unsigned int guessed_heads; + unsigned int guessed_sectors; + unsigned int blocks; + unsigned int blocks_per_cyl; + int rc; + + /* Don't even try when the blksize is invalid for C/H/S access */ + if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) + return 0; + + /* Guess geometry according to drive type */ + if ( int13_is_fdd ( int13 ) ) { + if ( ( rc = int13_guess_geometry_fdd ( int13, &guessed_heads, + &guessed_sectors )) != 0) + return rc; + } else { + if ( ( rc = int13_guess_geometry_hdd ( int13, scratch, + &guessed_heads, + &guessed_sectors )) != 0) + return rc; } /* Apply guesses if no geometry already specified */ if ( ! int13->heads ) int13->heads = guessed_heads; if ( ! int13->sectors_per_track ) - int13->sectors_per_track = guessed_sectors_per_track; + int13->sectors_per_track = guessed_sectors; if ( ! int13->cylinders ) { /* Avoid attempting a 64-bit divide on a 32-bit system */ blocks = int13_capacity32 ( int13 ); @@ -569,19 +707,40 @@ static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) { /** * 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 ); } @@ -589,13 +748,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(); } } @@ -669,14 +829,19 @@ static int int13_rw_sectors ( struct int13_drive *int13, 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; @@ -761,10 +926,19 @@ static int int13_get_parameters ( struct int13_drive *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; } @@ -781,10 +955,15 @@ static int int13_get_disk_type ( struct int13_drive *int13, uint32_t blocks; DBGC2 ( int13, "Get disk type\n" ); - blocks = int13_capacity32 ( int13 ); - 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; + } } /** @@ -833,6 +1012,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 ) ) ); @@ -1300,26 +1486,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 ); @@ -1404,14 +1592,13 @@ static void int13_free ( struct refcnt *refcnt ) { */ 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 natural drive number */ - get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES ); - natural_drive = ( num_drives | 0x80 ); + 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 ) { @@ -1468,7 +1655,7 @@ 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(); free ( scratch ); return 0; diff --git a/src/arch/i386/interface/pcbios/memtop_umalloc.c b/src/arch/i386/interface/pcbios/memtop_umalloc.c index 16736e19..dba4a23a 100644 --- a/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ b/src/arch/i386/interface/pcbios/memtop_umalloc.c @@ -52,6 +52,9 @@ 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 * @@ -59,12 +62,12 @@ static userptr_t bottom = UNULL; */ 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 ); + heap_size = 0; for ( i = 0 ; i < memmap.count ; i++ ) { struct memory_region *region = &memmap.regions[i]; unsigned long r_start, r_end; @@ -99,8 +102,8 @@ static int init_eheap ( void ) { return -ENOMEM; } - DBG ( "External heap grows downwards from %lx\n", - user_to_phys ( top, 0 ) ); + DBG ( "External heap grows downwards from %lx (size %zx)\n", + user_to_phys ( top, 0 ), heap_size ); return 0; } @@ -110,6 +113,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 +123,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; } } @@ -153,7 +158,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 +173,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 +188,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 +208,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/src/arch/i386/interface/pcbios/rtc_entropy.c b/src/arch/i386/interface/pcbios/rtc_entropy.c new file mode 100644 index 00000000..3f2a7c78 --- /dev/null +++ b/src/arch/i386/interface/pcbios/rtc_entropy.c @@ -0,0 +1,198 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/arch/i386/interface/pcbios/rtc_time.c b/src/arch/i386/interface/pcbios/rtc_time.c new file mode 100644 index 00000000..b5b46ff4 --- /dev/null +++ b/src/arch/i386/interface/pcbios/rtc_time.c @@ -0,0 +1,137 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/i386/interface/syslinux/comboot_call.c index 818cae84..7ee5f61b 100644 --- a/src/arch/i386/interface/syslinux/comboot_call.c +++ b/src/arch/i386/interface/syslinux/comboot_call.c @@ -166,6 +166,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 +186,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, - NULL ) ) != 0 ) { + if ( ( rc = imgdownload_string ( initrd_file, &initrd ) ) != 0){ DBG ( "COMBOOT: could not fetch initrd: %s\n", strerror ( rc ) ); return rc; @@ -198,14 +199,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, - image_replace ) ) != 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; } diff --git a/src/arch/i386/interface/vmware/guestinfo.c b/src/arch/i386/interface/vmware/guestinfo.c new file mode 100644 index 00000000..5f73e949 --- /dev/null +++ b/src/arch/i386/interface/vmware/guestinfo.c @@ -0,0 +1,281 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 %zd bytes\n", + settings, info_len ); + ret = -ENOMEM; + goto err_alloc; + } + info[info_len] = '\0'; + + /* Fetch GuestInfo value */ + check_len = guestrpc_command ( guestinfo_channel, command, + info, info_len ); + if ( check_len < 0 ) { + ret = check_len; + goto err_get_info; + } + if ( check_len != info_len ) { + DBGC ( settings, "GuestInfo %p length mismatch (expected %d, " + "got %d)\n", settings, info_len, check_len ); + ret = -EIO; + goto err_get_info; + } + DBGC2 ( settings, "GuestInfo %p found %s = \"%s\"\n", + settings, &command[9] /* Skip "info-get " */, info ); + + /* Parse GuestInfo value according to type */ + ret = type->parse ( info, data, len ); + if ( ret < 0 ) { + DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: " + "%s\n", settings, info, type->name, strerror ( ret ) ); + goto err_parse; + } + + err_parse: + err_get_info: + free ( info ); + err_alloc: + err_get_info_len: + return ret; +} + +/** + * Fetch value of GuestInfo setting + * + * @v settings Settings block + * @v setting Setting to fetch + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int guestinfo_fetch ( struct settings *settings, + struct setting *setting, + void *data, size_t len ) { + struct setting_type *type; + int found = 0; + int ret; + + /* Try default type first */ + ret = guestinfo_fetch_type ( settings, setting, NULL, + data, len, &found ); + if ( found ) + return ret; + + /* Otherwise, try all possible types */ + for_each_table_entry ( type, SETTING_TYPES ) { + ret = guestinfo_fetch_type ( settings, setting, type, + data, len, &found ); + if ( found ) + return ret; + } + + /* Not found */ + return -ENOENT; +} + +/** GuestInfo settings operations */ +static struct settings_operations guestinfo_settings_operations = { + .fetch = guestinfo_fetch, +}; + +/** GuestInfo settings */ +static struct settings guestinfo_settings = { + .refcnt = NULL, + .siblings = LIST_HEAD_INIT ( guestinfo_settings.siblings ), + .children = LIST_HEAD_INIT ( guestinfo_settings.children ), + .op = &guestinfo_settings_operations, +}; + +/** Initialise GuestInfo settings */ +static void guestinfo_init ( void ) { + int rc; + + /* Open GuestRPC channel */ + guestinfo_channel = guestrpc_open(); + if ( guestinfo_channel < 0 ) { + rc = guestinfo_channel; + DBG ( "GuestInfo could not open channel: %s\n", + strerror ( rc ) ); + return; + } + + /* Register root GuestInfo settings */ + if ( ( rc = register_settings ( &guestinfo_settings, NULL, + "vmware" ) ) != 0 ) { + DBG ( "GuestInfo could not register settings: %s\n", + strerror ( rc ) ); + return; + } +} + +/** GuestInfo settings initialiser */ +struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = guestinfo_init, +}; + +/** + * Create per-netdevice GuestInfo settings + * + * @v netdev Network device + * @ret rc Return status code + */ +static int guestinfo_net_probe ( struct net_device *netdev ) { + struct settings *settings; + int rc; + + /* Do nothing unless we have a GuestInfo channel available */ + if ( guestinfo_channel < 0 ) + return 0; + + /* Allocate and initialise settings block */ + settings = zalloc ( sizeof ( *settings ) ); + if ( ! settings ) { + rc = -ENOMEM; + goto err_alloc; + } + settings_init ( settings, &guestinfo_settings_operations, NULL, 0 ); + + /* Register settings */ + if ( ( rc = register_settings ( settings, netdev_settings ( netdev ), + "vmware" ) ) != 0 ) { + DBGC ( settings, "GuestInfo %p could not register for %s: %s\n", + settings, netdev->name, strerror ( rc ) ); + goto err_register; + } + DBGC ( settings, "GuestInfo %p registered for %s\n", + settings, netdev->name ); + + return 0; + + err_register: + free ( settings ); + err_alloc: + return rc; +} + +/** + * Handle network device or link state change + * + * @v netdev Network device + */ +static void guestinfo_net_notify ( struct net_device *netdev __unused ) { + /* Nothing to do */ +} + +/** + * Remove per-netdevice GuestInfo settings + * + * @v netdev Network device + */ +static void guestinfo_net_remove ( struct net_device *netdev ) { + struct settings *parent = netdev_settings ( netdev ); + struct settings *settings; + + list_for_each_entry ( settings, &parent->children, siblings ) { + if ( settings->op == &guestinfo_settings_operations ) { + DBGC ( settings, "GuestInfo %p unregistered for %s\n", + settings, netdev->name ); + unregister_settings ( settings ); + free ( settings ); + return; + } + } +} + +/** GuestInfo per-netdevice driver */ +struct net_driver guestinfo_net_driver __net_driver = { + .name = "GuestInfo", + .probe = guestinfo_net_probe, + .notify = guestinfo_net_notify, + .remove = guestinfo_net_remove, +}; diff --git a/src/arch/i386/interface/vmware/guestrpc.c b/src/arch/i386/interface/vmware/guestrpc.c new file mode 100644 index 00000000..a19e5bff --- /dev/null +++ b/src/arch/i386/interface/vmware/guestrpc.c @@ -0,0 +1,327 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/arch/i386/interface/vmware/vmconsole.c b/src/arch/i386/interface/vmware/vmconsole.c new file mode 100644 index 00000000..7f02c50e --- /dev/null +++ b/src/arch/i386/interface/vmware/vmconsole.c @@ -0,0 +1,133 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/arch/i386/interface/vmware/vmware.c b/src/arch/i386/interface/vmware/vmware.c new file mode 100644 index 00000000..8cc26c94 --- /dev/null +++ b/src/arch/i386/interface/vmware/vmware.c @@ -0,0 +1,57 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * VMware backdoor mechanism + * + * Based on the unofficial documentation at + * + * http://sites.google.com/site/chitchatvmback/backdoor + * + */ + +#include +#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/src/arch/x86/core/x86_bigint.c b/src/arch/x86/core/x86_bigint.c new file mode 100644 index 00000000..cb6c67b1 --- /dev/null +++ b/src/arch/x86/core/x86_bigint.c @@ -0,0 +1,90 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/arch/x86/include/bits/bigint.h b/src/arch/x86/include/bits/bigint.h new file mode 100644 index 00000000..d3449af5 --- /dev/null +++ b/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/src/arch/x86_64/core/linux/linuxprefix.S b/src/arch/x86_64/core/linux/linuxprefix.S index 713b9e38..ec8a9dec 100644 --- a/src/arch/x86_64/core/linux/linuxprefix.S +++ b/src/arch/x86_64/core/linux/linuxprefix.S @@ -22,4 +22,4 @@ _linux_start: movq $__NR_exit, %rax syscall - .size _start, . - _start + .size _linux_start, . - _linux_start diff --git a/src/arch/x86_64/include/bits/byteswap.h b/src/arch/x86_64/include/bits/byteswap.h index 9ed85e8f..2e472d98 100644 --- a/src/arch/x86_64/include/bits/byteswap.h +++ b/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/src/arch/x86_64/include/bits/entropy.h b/src/arch/x86_64/include/bits/entropy.h new file mode 100644 index 00000000..9c64c833 --- /dev/null +++ b/src/arch/x86_64/include/bits/entropy.h @@ -0,0 +1,12 @@ +#ifndef _BITS_ENTROPY_H +#define _BITS_ENTROPY_H + +/** @file + * + * x86_64-specific entropy API implementations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#endif /* _BITS_ENTROPY_H */ diff --git a/src/arch/x86_64/include/bits/time.h b/src/arch/x86_64/include/bits/time.h new file mode 100644 index 00000000..59b35535 --- /dev/null +++ b/src/arch/x86_64/include/bits/time.h @@ -0,0 +1,12 @@ +#ifndef _BITS_TIME_H +#define _BITS_TIME_H + +/** @file + * + * x86_64-specific time API implementations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#endif /* _BITS_TIME_H */ diff --git a/src/config/config.c b/src/config/config.c index 2c3555ea..9c1df1f3 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -71,21 +71,24 @@ 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 /* * Drag in all requested network protocols @@ -122,9 +125,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 +155,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 @@ -214,12 +205,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 @@ -274,13 +271,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/src/config/console.h b/src/config/console.h index afc89569..95c32803 100644 --- a/src/config/console.h +++ b/src/config/console.h @@ -17,12 +17,15 @@ 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 KEYBOARD_MAP us +#define LOG_LEVEL LOG_NONE + #include #endif /* CONFIG_CONSOLE_H */ diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index 693f55ad..16a44dd5 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -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/src/config/defaults/linux.h b/src/config/defaults/linux.h index 647dc0a5..50897560 100644 --- a/src/config/defaults/linux.h +++ b/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/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index 59adbf78..b68186f1 100644 --- a/src/config/defaults/pcbios.h +++ b/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 */ diff --git a/src/config/entropy.h b/src/config/entropy.h new file mode 100644 index 00000000..7de2f673 --- /dev/null +++ b/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/src/config/general.h b/src/config/general.h index 339d78a6..845a91e1 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -58,7 +58,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */ #define 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,10 +94,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #undef IMAGE_NBI /* NBI image support */ //#define IMAGE_ELF /* ELF image support */ -#undef IMAGE_FREEBSD /* FreeBSD kernel image support */ #undef IMAGE_MULTIBOOT /* MultiBoot image support */ -#undef IMAGE_AOUT /* a.out image support */ -#undef 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 */ @@ -119,6 +115,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define IMAGE_CMD /* Image management commands */ #undef DHCP_CMD /* DHCP management commands */ #define SANBOOT_CMD /* SAN boot commands */ +#undef MENU_CMD /* Menu commands */ #undef LOGIN_CMD /* Login command */ #undef TIME_CMD /* Time commands */ #undef DIGEST_CMD /* Image crypto digest commands */ @@ -126,6 +123,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #undef VLAN_CMD /* VLAN commands */ #undef PXE_CMD /* PXE commands */ #undef REBOOT_CMD /* Reboot command */ +#define IMAGE_TRUST_CMD /* Image trust management commands */ /* * ROM-specific options diff --git a/src/config/sideband.h b/src/config/sideband.h index 5385dd72..a16c2e37 100644 --- a/src/config/sideband.h +++ b/src/config/sideband.h @@ -10,5 +10,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */ +//#define VMWARE_SETTINGS /* VMware GuestInfo settings */ #endif /* CONFIG_SIDEBAND_H */ diff --git a/src/config/time.h b/src/config/time.h new file mode 100644 index 00000000..0576211f --- /dev/null +++ b/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/src/core/btext.c b/src/core/btext.c deleted file mode 100644 index 4fb7378d..00000000 --- a/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/src/core/console.c b/src/core/console.c index f27edf46..a26a3ef6 100644 --- a/src/core/console.c +++ b/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/src/core/debug.c b/src/core/debug.c index 73e74d9c..fc90c64a 100644 --- a/src/core/debug.c +++ b/src/core/debug.c @@ -21,17 +21,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 +60,9 @@ void dbg_pause ( void ) { * */ void dbg_more ( void ) { - printf ( "---more---" ); + dbg_printf ( "---more---" ); getchar(); - printf ( "\r \r" ); + dbg_printf ( "\r \r" ); } /** @@ -58,27 +79,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 +179,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 +188,5 @@ void dbg_autocolourise ( unsigned long stream ) { * */ void dbg_decolourise ( void ) { - printf ( "\033[0m" ); + dbg_printf ( "\033[0m" ); } diff --git a/src/core/downloader.c b/src/core/downloader.c index 4dc0aa02..b4c5a5a7 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -73,6 +74,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 +111,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 +183,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/src/core/image.c b/src/core/image.c index b1eba4ad..bf9bb7fa 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -36,12 +37,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 +67,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 +160,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 @@ -228,6 +270,12 @@ int image_exec ( struct image *image ) { if ( ( rc = image_select ( image ) ) != 0 ) return rc; + /* Check that image is trusted (if applicable) */ + if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) { + DBGC ( image, "IMAGE %s is not trusted\n", image->name ); + return -EACCES_UNTRUSTED; + } + /* Switch current working directory to be that of the image itself */ old_cwuri = uri_get ( cwuri ); churi ( image->uri ); @@ -241,6 +289,9 @@ int image_exec ( struct image *image ) { */ current_image = image_get ( image ); + /* Record boot attempt */ + syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name ); + /* Try executing the image */ if ( ( rc = image->type->exec ( image ) ) != 0 ) { DBGC ( image, "IMAGE %s could not execute: %s\n", @@ -248,6 +299,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 @@ -269,8 +329,8 @@ int image_exec ( struct image *image ) { /* Tail-recurse into replacement image, if one exists */ if ( replacement ) { - DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n", - image->name, replacement->name ); + DBGC ( image, "IMAGE replacing self with IMAGE %s\n", + replacement->name ); if ( ( rc = image_exec ( replacement ) ) != 0 ) return rc; } @@ -355,3 +415,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/src/core/lineconsole.c b/src/core/lineconsole.c new file mode 100644 index 00000000..71bc1f8b --- /dev/null +++ b/src/core/lineconsole.c @@ -0,0 +1,66 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/core/log.c b/src/core/log.c new file mode 100644 index 00000000..c0c3656c --- /dev/null +++ b/src/core/log.c @@ -0,0 +1,62 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/core/malloc.c b/src/core/malloc.c index d694f555..6633887b 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -105,11 +105,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 +144,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 ) { - 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 ) ); + if ( RUNNING_ON_VALGRIND <= 0 ) + return; + + /* Traverse free block list, marking each block structure as + * inaccessible. Some contortions are necessary to avoid + * errors from list_check(). + */ + + /* Mark each block in list as inaccessible */ + list_for_each_entry ( block, &free_blocks, list ) { + + /* Mark previous block (if any) as inaccessible. (Current + * block will be accessed by list_check().) + */ + if ( prev ) + VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) ); + prev = block; + + /* At the end of the list, list_check() will end up + * accessing the first list item. Temporarily mark + * this area as defined. + */ + VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->prev, + sizeof ( free_blocks.next->prev ) ); } + /* Mark last block (if any) as inaccessible */ + if ( prev ) + VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) ); + + /* Mark as inaccessible the area that was temporarily marked + * as defined to avoid errors from list_check(). + */ + VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks.next->prev, + sizeof ( free_blocks.next->prev ) ); + + /* Mark block list itself as inaccessible */ + VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) ); } /** @@ -144,6 +200,18 @@ static unsigned int discard_cache ( void ) { return discarded; } +/** + * Discard all cached data + * + */ +static void discard_all_cache ( void ) { + unsigned int discarded; + + do { + discarded = discard_cache(); + } while ( discarded ); +} + /** * Allocate a memory block * @@ -458,6 +526,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/src/core/menu.c b/src/core/menu.c new file mode 100644 index 00000000..1d1678f3 --- /dev/null +++ b/src/core/menu.c @@ -0,0 +1,177 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/core/misc.c b/src/core/misc.c index 8f56e1fb..11342481 100644 --- a/src/core/misc.c +++ b/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/src/core/null_time.c b/src/core/null_time.c new file mode 100644 index 00000000..f9c48a95 --- /dev/null +++ b/src/core/null_time.c @@ -0,0 +1,29 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Nonexistent time source + * + */ + +#include + +PROVIDE_TIME_INLINE ( null, time_now ); diff --git a/src/core/parseopt.c b/src/core/parseopt.c index f953b421..432e856d 100644 --- a/src/core/parseopt.c +++ b/src/core/parseopt.c @@ -26,7 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include +#include #include /** @file @@ -115,21 +115,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; } @@ -151,6 +152,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 * diff --git a/src/core/pcmcia.c b/src/core/pcmcia.c index 2d8ceb6f..5fd21f4a 100644 --- a/src/core/pcmcia.c +++ b/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/src/core/serial_console.c b/src/core/serial_console.c index b05a06b1..bbddd6b2 100644 --- a/src/core/serial_console.c +++ b/src/core/serial_console.c @@ -1,6 +1,7 @@ #include #include #include +#include /** @file * @@ -8,6 +9,12 @@ * */ +/* 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 ) { @@ -21,6 +28,7 @@ struct console_driver serial_console __console_driver = { .getchar = serial_getc, .iskey = serial_ischar, .disabled = 1, + .usage = CONSOLE_SERIAL, }; /** diff --git a/src/core/settings.c b/src/core/settings.c index 0a8c5f68..c84e1bc2 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -676,6 +676,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 +816,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 +861,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 +887,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 +992,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. - */ + /* NULL value implies deletion */ if ( ! value ) 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 * @@ -1176,302 +1295,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; - len = uri_decode ( value, buf, sizeof ( buf ) ); - return store_setting ( settings, setting, buf, len ); + /* Decode to temporary buffer (including NUL) */ + raw_len = uri_decode ( value, tmp, sizeof ( tmp ) ); + + /* Copy to output buffer (excluding NUL) */ + if ( len > raw_len ) + len = raw_len; + memcpy ( buf, tmp, len ); + + return raw_len; } /** - * 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; + /* Copy to temporary buffer and terminate */ + memcpy ( tmp, raw, raw_len ); + tmp[raw_len] = '\0'; - { - 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 ); - } + /* 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 +1634,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; + unsigned 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; + 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; - if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0) - return raw_len; - return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) ); + /* Range check */ + if ( raw_len != sizeof ( *uuid ) ) + return -ERANGE; + + /* Format value */ + return snprintf ( buf, len, "%s", uuid_ntoa ( uuid ) ); } /** UUID setting type */ struct setting_type setting_type_uuid __setting_type = { .name = "uuid", - .storef = storef_uuid, - .fetchf = fetchf_uuid, + .parse = parse_uuid_setting, + .format = format_uuid_setting, }; /****************************************************************************** @@ -1703,6 +1838,14 @@ struct setting hostname_setting __setting ( SETTING_HOST ) = { .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", diff --git a/src/core/strtoull.c b/src/core/strtoull.c index b1ceeb45..00986eef 100644 --- a/src/core/strtoull.c +++ b/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/src/core/time.c b/src/core/time.c new file mode 100644 index 00000000..52ae3ee9 --- /dev/null +++ b/src/core/time.c @@ -0,0 +1,137 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/core/uuid.c b/src/core/uuid.c index d98553f0..cc41afda 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -35,7 +35,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/src/core/vsprintf.c b/src/core/vsprintf.c index b838b89e..b721b024 100644 --- a/src/core/vsprintf.c +++ b/src/core/vsprintf.c @@ -21,7 +21,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include #include diff --git a/src/core/xfer.c b/src/core/xfer.c index 4d7d6b43..037c089a 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -297,17 +298,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/src/core/xferbuf.c b/src/core/xferbuf.c new file mode 100644 index 00000000..a0457fee --- /dev/null +++ b/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/src/crypto/aes_wrap.c b/src/crypto/aes_wrap.c index 46ef016f..f59fbf91 100644 --- a/src/crypto/aes_wrap.c +++ b/src/crypto/aes_wrap.c @@ -48,7 +48,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/src/crypto/asn1.c b/src/crypto/asn1.c index 40b87533..2eab3422 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -20,7 +20,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include +#include #include /** @file @@ -42,12 +44,32 @@ FILE_LICENCE ( GPL2_OR_LATER ); __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" ) + +/** + * 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 @@ -67,7 +89,7 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) { } /* 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 ) ); return -ENXIO; @@ -110,7 +132,7 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) { * 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 @@ -137,7 +159,7 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { * 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 @@ -168,7 +190,7 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) { * Skip 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 next ASN.1 @@ -178,10 +200,203 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) { int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) { int rc; - if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) { + 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 asn1_boolean *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; +} + +/** + * 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, or NULL + */ +struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { + struct asn1_cursor contents; + struct asn1_algorithm *algorithm; + 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 NULL; + } + + /* 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 NULL; + } + + return algorithm; +} diff --git a/src/crypto/axtls/aes.c b/src/crypto/axtls/aes.c index 87faaa1d..bd99a709 100644 --- a/src/crypto/axtls/aes.c +++ b/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; + int i; + uint32_t tin[4], tout[4], iv[4]; - n2l(iv, tout0); - n2l(iv, tout1); - n2l(iv, tout2); - n2l(iv, tout3); - iv -= 4; + memcpy(iv, ctx->iv, AES_IV_SIZE); + for (i = 0; i < 4; i++) + tout[i] = ntohl(iv[i]); - for (length -= 16; length >= 0; length -= 16) + 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; + int i; + uint32_t tin[4], xor[4], tout[4], data[4], iv[4]; - n2l(iv ,xor0); - n2l(iv, xor1); - n2l(iv, xor2); - n2l(iv, xor3); - 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) + 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; + for (i = 0; i < 4; i++) + { + tout[i] = data[i]^xor[i]; + xor[i] = tin[i]; + out_32[i] = htonl(tout[i]); + } - xor0 = tin0; - xor1 = tin1; - xor2 = tin2; - xor3 = tin3; - - 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/src/crypto/axtls/bigint.c b/src/crypto/axtls/bigint.c deleted file mode 100644 index 49cad971..00000000 --- a/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/src/crypto/axtls/bigint.h b/src/crypto/axtls/bigint.h index f5f33531..1f38c53d 100644 --- a/src/crypto/axtls/bigint.h +++ b/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 "crypto.h" -#include "os_port.h" -#include "bigint_impl.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/src/crypto/axtls/bigint_impl.h b/src/crypto/axtls/bigint_impl.h index 762a7ccb..09d8550e 100644 --- a/src/crypto/axtls/bigint_impl.h +++ b/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/src/crypto/axtls/config.h b/src/crypto/axtls/config.h new file mode 100644 index 00000000..32fa3bf0 --- /dev/null +++ b/src/crypto/axtls/config.h @@ -0,0 +1,13 @@ +#ifndef AXTLS_CONFIG_H +#define AXTLS_CONFIG_H + +/** + * @file config.h + * + * Trick the axtls code into building within our build environment. + */ + +#define CONFIG_SSL_ENABLE_CLIENT 1 +#define CONFIG_BIGINT_CLASSICAL 1 + +#endif diff --git a/src/crypto/axtls/crypto.h b/src/crypto/axtls/crypto.h index a9893cf3..2c4cda4d 100644 --- a/src/crypto/axtls/crypto.h +++ b/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 + * RNG 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 - **************************************************************************/ - -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/src/crypto/axtls/os_port.h b/src/crypto/axtls/os_port.h index babdbfad..76313e20 100644 --- a/src/crypto/axtls/os_port.h +++ b/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; +/* Expose AES_encrypt() and AES_decrypt() in aes.o */ +#define aes 1 +#if OBJECT -static inline FILE * fopen ( const char *filename __unused, - const char *mode __unused ) { - return NULL; +struct aes_key_st; + +static void AES_encrypt ( const struct aes_key_st *ctx, uint32_t *data ); +static void AES_decrypt ( const struct aes_key_st *ctx, uint32_t *data ); + +void axtls_aes_encrypt ( void *ctx, uint32_t *data ) { + AES_encrypt ( ctx, data ); } -static inline int fseek ( FILE *stream __unused, long offset __unused, - int whence __unused ) { - return -1; +void axtls_aes_decrypt ( void *ctx, uint32_t *data ) { + AES_decrypt ( ctx, data ); } -static inline long ftell ( FILE *stream __unused ) { - return -1; -} - -static inline size_t fread ( void *ptr __unused, size_t size __unused, - size_t nmemb __unused, FILE *stream __unused ) { - return -1; -} - -static inline int fclose ( FILE *stream __unused ) { - return -1; -} - -#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/src/crypto/axtls/rsa.c b/src/crypto/axtls/rsa.c deleted file mode 100644 index 389eda57..00000000 --- a/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/src/crypto/axtls/sha1.c b/src/crypto/axtls/sha1.c deleted file mode 100644 index 9a42801f..00000000 --- a/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/src/crypto/axtls_aes.c b/src/crypto/axtls_aes.c index b73a5725..3f1d668a 100644 --- a/src/crypto/axtls_aes.c +++ b/src/crypto/axtls_aes.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -119,7 +120,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 +140,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/src/crypto/axtls_sha1.c b/src/crypto/axtls_sha1.c deleted file mode 100644 index 3eb8912d..00000000 --- a/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/src/crypto/bigint.c b/src/crypto/bigint.c new file mode 100644 index 00000000..b13b0ac6 --- /dev/null +++ b/src/crypto/bigint.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., 675 Mass Ave, Cambridge, MA 02139, 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/src/crypto/clientcert.c b/src/crypto/clientcert.c new file mode 100644 index 00000000..159a3f4e --- /dev/null +++ b/src/crypto/clientcert.c @@ -0,0 +1,182 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 key_setting __setting ( SETTING_CRYPTO ) = { + .name = "key", + .description = "Client private key", + .tag = DHCP_EB_KEY, + .type = &setting_type_hex, +}; + +/** + * Apply client certificate store configuration settings + * + * @ret rc Return status code + */ +static int clientcert_apply_settings ( void ) { + static void *cert = NULL; + static void *key = NULL; + int len; + int rc; + + /* Allow client certificate to be overridden only if + * not explicitly specified at build time. + */ + if ( ALLOW_CERT_OVERRIDE ) { + + /* Restore default client certificate */ + client_certificate.data = client_certificate_data; + client_certificate.len = ( ( size_t ) client_certificate_len ); + + /* Fetch new client certificate, if any */ + free ( cert ); + len = fetch_setting_copy ( NULL, &cert_setting, &cert ); + if ( len < 0 ) { + rc = len; + DBGC ( &client_certificate, "CLIENTCERT cannot fetch " + "client certificate: %s\n", strerror ( rc ) ); + return rc; + } + if ( cert ) { + client_certificate.data = cert; + client_certificate.len = len; + } + + /* Restore default client private key */ + client_private_key.data = client_private_key_data; + client_private_key.len = ( ( size_t ) client_private_key_len ); + + /* Fetch new client private key, if any */ + free ( key ); + len = fetch_setting_copy ( NULL, &key_setting, &key ); + if ( len < 0 ) { + rc = len; + DBGC ( &client_certificate, "CLIENTCERT cannot fetch " + "client private key: %s\n", strerror ( rc ) ); + return rc; + } + if ( key ) { + client_private_key.data = key; + client_private_key.len = len; + } + } + + /* Debug */ + if ( have_client_certificate() ) { + DBGC ( &client_certificate, "CLIENTCERT using %s " + "certificate:\n", ( cert ? "external" : "built-in" ) ); + DBGC_HDA ( &client_certificate, 0, client_certificate.data, + client_certificate.len ); + DBGC ( &client_certificate, "CLIENTCERT using %s private " + "key:\n", ( key ? "external" : "built-in" ) ); + DBGC_HDA ( &client_certificate, 0, client_private_key.data, + client_private_key.len ); + } else { + DBGC ( &client_certificate, "CLIENTCERT has no certificate\n" ); + } + + return 0; +} + +/** Client certificate store settings applicator */ +struct settings_applicator clientcert_applicator __settings_applicator = { + .apply = clientcert_apply_settings, +}; diff --git a/src/crypto/cms.c b/src/crypto/cms.c new file mode 100644 index 00000000..18e59bfb --- /dev/null +++ b/src/crypto/cms.c @@ -0,0 +1,727 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Cryptographic Message Syntax (PKCS #7) + * + * The format of CMS messages is defined in RFC 5652. + * + */ + +#include +#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" ) +#define ENOTSUP_DIGEST \ + __einfo_error ( EINFO_ENOTSUP_DIGEST ) +#define EINFO_ENOTSUP_DIGEST \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported digest algorithm" ) +#define ENOTSUP_PUBKEY \ + __einfo_error ( EINFO_ENOTSUP_PUBKEY ) +#define EINFO_ENOTSUP_PUBKEY \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \ + "Unsupported public-key algorithm" ) + +/** "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; + + /* Identify algorithm */ + algorithm = asn1_algorithm ( raw ); + if ( ! algorithm ) { + DBGC ( sig, "CMS %p/%p could not identify digest algorithm:\n", + sig, info ); + DBGC_HDA ( sig, 0, raw->data, raw->len ); + return -ENOTSUP_DIGEST; + } + + /* Check algorithm is a digest algorithm */ + if ( ! algorithm->digest ) { + DBGC ( sig, "CMS %p/%p algorithm %s is not a digest " + "algorithm\n", sig, info, algorithm->name ); + return -EINVAL_DIGEST; + } + + /* 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; + + /* Identify algorithm */ + algorithm = asn1_algorithm ( raw ); + if ( ! algorithm ) { + DBGC ( sig, "CMS %p/%p could not identify public-key " + "algorithm:\n", sig, info ); + DBGC_HDA ( sig, 0, raw->data, raw->len ); + return -ENOTSUP_PUBKEY; + } + + /* Check algorithm is a signature algorithm */ + if ( ! algorithm->pubkey ) { + DBGC ( sig, "CMS %p/%p algorithm %s is not a public-key " + "algorithm\n", sig, info, algorithm->name ); + return -EINVAL_PUBKEY; + } + + /* Record signature algorithm */ + info->pubkey = algorithm->pubkey; + DBGC ( sig, "CMS %p/%p public-key algorithm is %s\n", + sig, info, algorithm->name ); + + return 0; +} + +/** + * Parse CMS signature value + * + * @v sig CMS signature + * @v info Signer information to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int cms_parse_signature_value ( struct cms_signature *sig, + struct cms_signer_info *info, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int rc; + + /* Enter signature */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not locate signature:\n", + sig, info ); + DBGC_HDA ( sig, 0, raw->data, raw->len ); + return rc; + } + + /* Record signature */ + info->signature_len = cursor.len; + info->signature = malloc ( info->signature_len ); + if ( ! info->signature ) + return -ENOMEM; + memcpy ( info->signature, cursor.data, info->signature_len ); + DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info ); + DBGC_HDA ( sig, 0, info->signature, info->signature_len ); + + return 0; +} + +/** + * Parse CMS signature signer information + * + * @v sig CMS signature + * @v info Signer information to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int cms_parse_signer_info ( struct cms_signature *sig, + struct cms_signer_info *info, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int rc; + + /* Enter signerInfo */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Skip version */ + asn1_skip ( &cursor, ASN1_INTEGER ); + + /* Parse sid */ + if ( ( rc = cms_parse_signer_identifier ( sig, info, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse digestAlgorithm */ + if ( ( rc = cms_parse_digest_algorithm ( sig, info, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Skip signedAttrs, if present */ + asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + + /* Parse signatureAlgorithm */ + if ( ( rc = cms_parse_signature_algorithm ( sig, info, &cursor ) ) != 0) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse signature */ + if ( ( rc = cms_parse_signature_value ( sig, info, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Parse CMS signature from ASN.1 data + * + * @v sig CMS signature + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int cms_parse ( struct cms_signature *sig, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + struct cms_signer_info *info; + int rc; + + /* Enter contentInfo */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse contentType */ + + if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Enter content */ + asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + + /* Enter signedData */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Skip version */ + asn1_skip ( &cursor, ASN1_INTEGER ); + + /* Skip digestAlgorithms */ + asn1_skip ( &cursor, ASN1_SET ); + + /* Skip encapContentInfo */ + asn1_skip ( &cursor, ASN1_SEQUENCE ); + + /* Parse certificates */ + if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Skip crls, if present */ + asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) ); + + /* Enter signerInfos */ + asn1_enter ( &cursor, ASN1_SET ); + + /* Add each signerInfo. Errors are handled by ensuring that + * cms_put() will always be able to free any allocated memory. + */ + while ( cursor.len ) { + + /* Allocate signer information block */ + info = zalloc ( sizeof ( *info ) ); + if ( ! info ) + return -ENOMEM; + list_add ( &info->list, &sig->info ); + + /* Allocate certificate chain */ + info->chain = x509_alloc_chain(); + if ( ! info->chain ) + return -ENOMEM; + + /* Parse signerInfo */ + if ( ( rc = cms_parse_signer_info ( sig, info, + &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + } + + return 0; +} + +/** + * Free CMS signature + * + * @v refcnt Reference count + */ +static void cms_free ( struct refcnt *refcnt ) { + struct cms_signature *sig = + container_of ( refcnt, struct cms_signature, refcnt ); + struct cms_signer_info *info; + struct cms_signer_info *tmp; + + list_for_each_entry_safe ( info, tmp, &sig->info, list ) { + list_del ( &info->list ); + x509_chain_put ( info->chain ); + free ( info->signature ); + free ( info ); + } + x509_chain_put ( sig->certificates ); + free ( sig ); +} + +/** + * Create CMS signature + * + * @v data Raw signature data + * @v len Length of raw data + * @ret sig CMS signature + * @ret rc Return status code + * + * On success, the caller holds a reference to the CMS signature, and + * is responsible for ultimately calling cms_put(). + */ +int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) { + struct asn1_cursor cursor; + int rc; + + /* Allocate and initialise signature */ + *sig = zalloc ( sizeof ( **sig ) ); + if ( ! *sig ) { + rc = -ENOMEM; + goto err_alloc; + } + ref_init ( &(*sig)->refcnt, cms_free ); + INIT_LIST_HEAD ( &(*sig)->info ); + + /* Allocate certificate list */ + (*sig)->certificates = x509_alloc_chain(); + if ( ! (*sig)->certificates ) { + rc = -ENOMEM; + goto err_alloc_chain; + } + + /* Initialise cursor */ + cursor.data = data; + cursor.len = len; + asn1_shrink_any ( &cursor ); + + /* Parse signature */ + if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 ) + goto err_parse; + + return 0; + + err_parse: + err_alloc_chain: + cms_put ( *sig ); + err_alloc: + return rc; +} + +/** + * Calculate digest of CMS-signed data + * + * @v sig CMS signature + * @v info Signer information + * @v data Signed data + * @v len Length of signed data + * @v out Digest output + */ +static void cms_digest ( struct cms_signature *sig, + struct cms_signer_info *info, + userptr_t data, size_t len, void *out ) { + struct digest_algorithm *digest = info->digest; + uint8_t ctx[ digest->ctxsize ]; + uint8_t block[ digest->blocksize ]; + size_t offset = 0; + size_t frag_len; + + /* Initialise digest */ + digest_init ( digest, ctx ); + + /* Process data one block at a time */ + while ( len ) { + frag_len = len; + if ( frag_len > sizeof ( block ) ) + frag_len = sizeof ( block ); + copy_from_user ( block, data, offset, frag_len ); + digest_update ( digest, ctx, block, frag_len ); + offset += frag_len; + len -= frag_len; + } + + /* Finalise digest */ + digest_final ( digest, ctx, out ); + + DBGC ( sig, "CMS %p/%p digest value:\n", sig, info ); + DBGC_HDA ( sig, 0, out, digest->digestsize ); +} + +/** + * Verify digest of CMS-signed data + * + * @v sig CMS signature + * @v info Signer information + * @v cert Corresponding certificate + * @v data Signed data + * @v len Length of signed data + * @ret rc Return status code + */ +static int cms_verify_digest ( struct cms_signature *sig, + struct cms_signer_info *info, + struct x509_certificate *cert, + userptr_t data, size_t len ) { + struct digest_algorithm *digest = info->digest; + struct pubkey_algorithm *pubkey = info->pubkey; + struct x509_public_key *public_key = &cert->subject.public_key; + uint8_t digest_out[ digest->digestsize ]; + uint8_t ctx[ pubkey->ctxsize ]; + int rc; + + /* Generate digest */ + cms_digest ( sig, info, data, len, digest_out ); + + /* Initialise public-key algorithm */ + if ( ( rc = pubkey_init ( pubkey, ctx, public_key->raw.data, + public_key->raw.len ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not initialise public key: %s\n", + sig, info, strerror ( rc ) ); + goto err_init; + } + + /* Verify digest */ + if ( ( rc = pubkey_verify ( pubkey, ctx, digest, digest_out, + info->signature, + info->signature_len ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p signature verification failed: %s\n", + sig, info, strerror ( rc ) ); + goto err_verify; + } + + err_verify: + pubkey_final ( pubkey, ctx ); + err_init: + return rc; +} + +/** + * Verify CMS signature signer information + * + * @v sig CMS signature + * @v info Signer information + * @v data Signed data + * @v len Length of signed data + * @v time Time at which to validate certificates + * @v root Root certificate store, or NULL to use default + * @ret rc Return status code + */ +static int cms_verify_signer_info ( struct cms_signature *sig, + struct cms_signer_info *info, + userptr_t data, size_t len, + time_t time, struct x509_root *root ) { + struct x509_certificate *cert; + int rc; + + /* Validate certificate chain */ + if ( ( rc = x509_validate_chain ( info->chain, time, root ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not validate chain: %s\n", + sig, info, strerror ( rc ) ); + return rc; + } + + /* Extract code-signing certificate */ + cert = x509_first ( info->chain ); + assert ( cert != NULL ); + + /* Check that certificate can create digital signatures */ + if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) { + DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n", + sig, info ); + return -EACCES_NON_SIGNING; + } + + /* Check that certificate can sign code */ + if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) { + DBGC ( sig, "CMS %p/%p certificate is not code-signing\n", + sig, info ); + return -EACCES_NON_CODE_SIGNING; + } + + /* Verify digest */ + if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Verify CMS signature + * + * @v sig CMS signature + * @v data Signed data + * @v len Length of signed data + * @v name Required common name, or NULL to check all signatures + * @v time Time at which to validate certificates + * @v root Root certificate store, or NULL to use default + * @ret rc Return status code + */ +int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len, + const char *name, time_t time, struct x509_root *root ) { + struct cms_signer_info *info; + struct x509_certificate *cert; + int count = 0; + int rc; + + /* Verify using all signerInfos */ + list_for_each_entry ( info, &sig->info, list ) { + cert = x509_first ( info->chain ); + if ( name && ( ( cert->subject.name == NULL ) || + ( strcmp ( cert->subject.name, name ) != 0 ) ) ) + continue; + if ( ( rc = cms_verify_signer_info ( sig, info, data, len, + time, root ) ) != 0 ) + return rc; + count++; + } + + /* Check that we have verified at least one signature */ + if ( count == 0 ) { + if ( name ) { + DBGC ( sig, "CMS %p had no signatures matching name " + "%s\n", sig, name ); + return -EACCES_WRONG_NAME; + } else { + DBGC ( sig, "CMS %p had no signatures\n", sig ); + return -EACCES_NO_SIGNATURES; + } + } + + return 0; +} diff --git a/src/crypto/crandom.c b/src/crypto/crandom.c deleted file mode 100644 index 1886f9b7..00000000 --- a/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/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index c9c32ae9..590ac560 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -81,7 +81,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/src/crypto/drbg.c b/src/crypto/drbg.c index 68aa7857..809de372 100644 --- a/src/crypto/drbg.c +++ b/src/crypto/drbg.c @@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include #include #include #include @@ -62,7 +63,7 @@ int drbg_instantiate ( struct drbg_state *state, const void *personal, 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[ entropy_bufsize ( entropy_bits, min_len, max_len ) ]; + uint8_t data[max_len]; int len; int rc; @@ -127,8 +128,8 @@ int drbg_instantiate ( struct drbg_state *state, const void *personal, state, strerror ( rc ) ); return rc; } - assert ( len >= min_len ); - assert ( len <= sizeof ( data ) ); + assert ( len >= ( int ) min_len ); + assert ( len <= ( int ) sizeof ( data ) ); /* 9. initial_working_state = Instantiate_algorithm ( * entropy_input, nonce, personalization_string ). @@ -150,6 +151,7 @@ int drbg_instantiate ( struct drbg_state *state, const void *personal, * in-situ.) */ state->reseed_required = 0; + state->valid = 1; /* 12. Return SUCCESS and state_handle. */ return 0; @@ -173,7 +175,7 @@ int drbg_reseed ( struct drbg_state *state, const void *additional, 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[ entropy_bufsize ( entropy_bits, min_len, max_len ) ]; + uint8_t data[max_len]; int len; int rc; @@ -186,9 +188,13 @@ int drbg_reseed ( struct drbg_state *state, const void *additional, * If state_handle indicates an invalid or empty internal * state, return an ERROR_FLAG. * - * (Nothing to do since the memory holding the internal state - * was passed in by the caller.) + * (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 @@ -272,9 +278,13 @@ int drbg_generate ( struct drbg_state *state, const void *additional, * for the instantiation. If state_handle indicates an * invalid or empty internal state, then return an ERROR_FLAG. * - * (Nothing to do since the memory holding the internal state - * was passed in by the caller.) + * (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 diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c index 86fa8978..03e7290a 100644 --- a/src/crypto/entropy.c +++ b/src/crypto/entropy.c @@ -22,27 +22,457 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * 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" ) + /** - * Obtain entropy input + * Calculate cutoff value for the repetition count test * - * @v 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 + * @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. */ -int get_entropy_input ( unsigned int entropy_bits, void *data, size_t min_len, - size_t max_len ) { +static inline __attribute__ (( always_inline )) unsigned int +repetition_count_cutoff ( void ) { + double max_repetitions; + unsigned int cutoff; - /* Placeholder to allow remainder of RBG code to be tested */ - ( void ) entropy_bits; - ( void ) min_len; - memset ( data, 0x01, max_len ); + /* 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() ) ); - return max_len; + /* Round up to a whole number of repetitions. We don't have + * the ceil() function available, so do the rounding by hand. + */ + cutoff = max_repetitions; + if ( cutoff < max_repetitions ) + cutoff++; + linker_assert ( ( cutoff >= max_repetitions ), rounding_error ); + + /* Floating-point operations are not allowed in iPXE since we + * never set up a suitable environment. Abort the build + * unless the calculated number of repetitions is a + * compile-time constant. + */ + linker_assert ( __builtin_constant_p ( cutoff ), + repetition_count_cutoff_not_constant ); + + return cutoff; +} + +/** + * Perform repetition count test + * + * @v sample Noise sample + * @ret rc Return status code + * + * This is the Repetition Count Test defined in ANS X9.82 Part 2 + * (October 2011 Draft) Section 8.5.2.1.2. + */ +static int repetition_count_test ( noise_sample_t sample ) { + static noise_sample_t most_recent_sample; + static unsigned int repetition_count = 0; + + /* A = the most recently seen sample value + * B = the number of times that value A has been seen in a row + * C = the cutoff value above which the repetition test should fail + */ + + /* 1. For each new sample processed: + * + * (Note that the test for "repetition_count > 0" ensures that + * the initial value of most_recent_sample is treated as being + * undefined.) + */ + if ( ( sample == most_recent_sample ) && ( repetition_count > 0 ) ) { + + /* a) If the new sample = A, then B is incremented by one. */ + repetition_count++; + + /* i. If B >= C, then an error condition is raised + * due to a failure of the test + */ + if ( repetition_count >= repetition_count_cutoff() ) + return -EPIPE_REPETITION_COUNT_TEST; + + } else { + + /* b) Else: + * i. A = new sample + */ + most_recent_sample = sample; + + /* ii. B = 1 */ + repetition_count = 1; + } + + return 0; +} + +/** + * Window size for the adaptive proportion test + * + * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows + * five possible window sizes: 16, 64, 256, 4096 and 65536. + * + * We expect to generate relatively few (<256) entropy samples during + * a typical iPXE run; the use of a large window size would mean that + * the test would never complete a single cycle. We use a window size + * of 64, which is the smallest window size that permits values of + * H_min down to one bit per sample. + */ +#define ADAPTIVE_PROPORTION_WINDOW_SIZE 64 + +/** + * Combine adaptive proportion test window size and min-entropy + * + * @v n N (window size) + * @v h H (min-entropy) + * @ret n_h (N,H) combined value + */ +#define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) ) + +/** + * Define a row of the adaptive proportion cutoff table + * + * @v h H (min-entropy) + * @v c16 Cutoff for N=16 + * @v c64 Cutoff for N=64 + * @v c256 Cutoff for N=256 + * @v c4096 Cutoff for N=4096 + * @v c65536 Cutoff for N=65536 + */ +#define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \ + case APC_N_H ( 16, h ) : return c16; \ + case APC_N_H ( 64, h ) : return c64; \ + case APC_N_H ( 256, h ) : return c256; \ + case APC_N_H ( 4096, h ) : return c4096; \ + case APC_N_H ( 65536, h ) : return c65536; + +/** Value used to represent "N/A" in adaptive proportion cutoff table */ +#define APC_NA 0 + +/** + * Look up value in adaptive proportion test cutoff table + * + * @v n N (window size) + * @v h H (min-entropy) + * @ret cutoff Cutoff + * + * This is the table of cutoff values defined in ANS X9.82 Part 2 + * (October 2011 Draft) Section 8.5.2.1.3.1.2. + */ +static inline __attribute__ (( always_inline )) unsigned int +adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) { + switch ( APC_N_H ( n, h ) ) { + APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 ); + APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 ); + APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 ); + APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 ); + APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 ); + APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 ); + APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 ); + APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 ); + APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 ); + APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 ); + APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 ); + APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 ); + APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 ); + APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 ); + APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 ); + APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 ); + APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 ); + APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 ); + APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 ); + APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 ); + default: + return APC_NA; + } +} + +/** + * Calculate cutoff value for the adaptive proportion test + * + * @ret cutoff Cutoff value + * + * This is the cutoff value for the Adaptive Proportion Test defined + * in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2. + */ +static inline __attribute__ (( always_inline )) unsigned int +adaptive_proportion_cutoff ( void ) { + unsigned int h; + unsigned int n; + unsigned int cutoff; + + /* Look up cutoff value in cutoff table */ + n = ADAPTIVE_PROPORTION_WINDOW_SIZE; + h = min_entropy_per_sample(); + cutoff = adaptive_proportion_cutoff_lookup ( n, h ); + + /* Fail unless cutoff value is a build-time constant */ + linker_assert ( __builtin_constant_p ( cutoff ), + adaptive_proportion_cutoff_not_constant ); + + /* Fail if cutoff value is N/A */ + linker_assert ( ( cutoff != APC_NA ), + adaptive_proportion_cutoff_not_applicable ); + + return cutoff; +} + +/** + * Perform adaptive proportion test + * + * @v sample Noise sample + * @ret rc Return status code + * + * This is the Adaptive Proportion Test for the Most Common Value + * defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3. + */ +static int adaptive_proportion_test ( noise_sample_t sample ) { + static noise_sample_t current_counted_sample; + static unsigned int sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE; + static unsigned int repetition_count; + + /* A = the sample value currently being counted + * B = the number of samples examined in this run of the test so far + * N = the total number of samples that must be observed in + * one run of the test, also known as the "window size" of + * the test + * B = the current number of times that S (sic) has been seen + * in the W (sic) samples examined so far + * C = the cutoff value above which the repetition test should fail + * W = the probability of a false positive: 2^-30 + */ + + /* 1. The entropy source draws the current sample from the + * noise source. + * + * (Nothing to do; we already have the current sample.) + */ + + /* 2. If S = N, then a new run of the test begins: */ + if ( sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) { + + /* a. A = the current sample */ + current_counted_sample = sample; + + /* b. S = 0 */ + sample_count = 0; + + /* c. B = 0 */ + repetition_count = 0; + + } else { + + /* Else: (the test is already running) + * a. S = S + 1 + */ + sample_count++; + + /* b. If A = the current sample, then: */ + if ( sample == current_counted_sample ) { + + /* i. B = B + 1 */ + repetition_count++; + + /* ii. If S (sic) > C then raise an error + * condition, because the test has + * detected a failure + */ + if ( repetition_count > adaptive_proportion_cutoff() ) + return -EPIPE_ADAPTIVE_PROPORTION_TEST; + + } + } + + return 0; +} + +/** + * Get entropy sample + * + * @ret entropy Entropy sample + * @ret rc Return status code + * + * This is the GetEntropy function defined in ANS X9.82 Part 2 + * (October 2011 Draft) Section 6.5.1. + */ +static int get_entropy ( entropy_sample_t *entropy ) { + static int rc = 0; + noise_sample_t noise; + + /* Any failure is permanent */ + if ( rc != 0 ) + return rc; + + /* Get noise sample */ + if ( ( rc = get_noise ( &noise ) ) != 0 ) + return rc; + + /* Perform Repetition Count Test and Adaptive Proportion Test + * as mandated by ANS X9.82 Part 2 (October 2011 Draft) + * Section 8.5.2.1.1. + */ + if ( ( rc = repetition_count_test ( noise ) ) != 0 ) + return rc; + if ( ( rc = adaptive_proportion_test ( noise ) ) != 0 ) + return rc; + + /* We do not use any optional conditioning component */ + *entropy = noise; + + return 0; +} + +/** + * Calculate number of samples required for startup tests + * + * @ret num_samples Number of samples required + * + * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires + * that at least one full cycle of the continuous tests must be + * performed at start-up. + */ +static inline __attribute__ (( always_inline )) unsigned int +startup_test_count ( void ) { + unsigned int num_samples; + + /* At least max(N,C) samples shall be generated by the noise + * source for start-up testing. + */ + num_samples = repetition_count_cutoff(); + if ( num_samples < adaptive_proportion_cutoff() ) + num_samples = adaptive_proportion_cutoff(); + linker_assert ( __builtin_constant_p ( num_samples ), + startup_test_count_not_constant ); + + return num_samples; +} + +/** + * Create next nonce value + * + * @ret nonce Nonce + * + * This is the MakeNextNonce function defined in ANS X9.82 Part 4 + * (April 2011 Draft) Section 13.3.4.2. + */ +static uint32_t make_next_nonce ( void ) { + static uint32_t nonce; + + /* The simplest implementation of a nonce uses a large counter */ + nonce++; + + return nonce; +} + +/** + * Obtain entropy input temporary buffer + * + * @v num_samples Number of entropy samples + * @v tmp Temporary buffer + * @v tmp_len Length of temporary buffer + * @ret rc Return status code + * + * This is (part of) the implementation of the Get_entropy_input + * function (using an entropy source as the source of entropy input + * and condensing each entropy source output after each GetEntropy + * call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section + * 13.3.4.2. + * + * To minimise code size, the number of samples required is calculated + * at compilation time. + */ +int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp, + size_t tmp_len ) { + static unsigned int startup_tested = 0; + struct { + uint32_t nonce; + entropy_sample_t sample; + } __attribute__ (( packed )) data;; + uint8_t df_buf[tmp_len]; + unsigned int i; + int rc; + + /* Enable entropy gathering */ + if ( ( rc = entropy_enable() ) != 0 ) + return rc; + + /* Perform mandatory startup tests, if not yet performed */ + for ( ; startup_tested < startup_test_count() ; startup_tested++ ) { + if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) + goto err_get_entropy; + } + + /* 3. entropy_total = 0 + * + * (Nothing to do; the number of entropy samples required has + * already been precalculated.) + */ + + /* 4. tmp = a fixed n-bit value, such as 0^n */ + memset ( tmp, 0, tmp_len ); + + /* 5. While ( entropy_total < min_entropy ) */ + while ( num_samples-- ) { + /* 5.1. ( status, entropy_bitstring, assessed_entropy ) + * = GetEntropy() + * 5.2. If status indicates an error, return ( status, Null ) + */ + if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) + goto err_get_entropy; + + /* 5.3. nonce = MakeNextNonce() */ + data.nonce = make_next_nonce(); + + /* 5.4. tmp = tmp XOR + * df ( ( nonce || entropy_bitstring ), n ) + */ + hash_df ( &entropy_hash_df_algorithm, &data, sizeof ( data ), + df_buf, sizeof ( df_buf ) ); + for ( i = 0 ; i < tmp_len ; i++ ) + tmp[i] ^= df_buf[i]; + + /* 5.5. entropy_total = entropy_total + assessed_entropy + * + * (Nothing to do; the number of entropy samples + * required has already been precalculated.) + */ + } + + /* Disable entropy gathering */ + entropy_disable(); + + return 0; + + err_get_entropy: + entropy_disable(); + return rc; } diff --git a/src/crypto/hash_df.c b/src/crypto/hash_df.c new file mode 100644 index 00000000..250c2ffc --- /dev/null +++ b/src/crypto/hash_df.c @@ -0,0 +1,137 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Hash-based derivation function (Hash_df) + * + * This algorithm is designed to comply with ANS X9.82 Part 3-2007 + * Section 10.5.2. This standard is not freely available, but most of + * the text appears to be shared with NIST SP 800-90, which can be + * downloaded from + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + * + * Where possible, references are given to both documents. In the + * case of any disagreement, ANS X9.82 takes priority over NIST SP + * 800-90. (In particular, note that some algorithms that are + * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) + */ + +#include +#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/src/crypto/hmac_drbg.c b/src/crypto/hmac_drbg.c index 64613d01..3f56e1b7 100644 --- a/src/crypto/hmac_drbg.c +++ b/src/crypto/hmac_drbg.c @@ -36,7 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include #include +#include #include #include #include @@ -44,6 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * 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 @@ -55,40 +58,40 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * as used by hmac_drbg_update() */ -static void hmac_drbg_update_key ( struct hmac_drbg_state *state, +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[HMAC_DRBG_CTX_SIZE]; - size_t key_len = sizeof ( state->key ); + uint8_t context[ hash->ctxsize ]; + size_t out_len = hash->digestsize; - DBGC ( state, "HMAC_DRBG %p provided data :\n", state ); + 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 ( &hmac_drbg_algorithm, context, state->key, &key_len ); - assert ( key_len == sizeof ( state->key ) ); - hmac_update ( &hmac_drbg_algorithm, context, - state->value, sizeof ( state->value ) ); - hmac_update ( &hmac_drbg_algorithm, context, - &single, sizeof ( single ) ); - hmac_update ( &hmac_drbg_algorithm, context, data, len ); - hmac_final ( &hmac_drbg_algorithm, context, state->key, &key_len, - state->key ); - assert ( key_len == sizeof ( state->key ) ); + 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 %p K = HMAC ( K, V || %#02x || " - "provided_data ) :\n", state, single ); - DBGC_HDA ( state, 0, state->key, sizeof ( state->key ) ); + 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 @@ -100,29 +103,31 @@ static void hmac_drbg_update_key ( struct hmac_drbg_state *state, * * as used by hmac_drbg_update() and hmac_drbg_generate() */ -static void hmac_drbg_update_value ( struct hmac_drbg_state *state ) { - uint8_t context[HMAC_DRBG_CTX_SIZE]; - size_t key_len = sizeof ( state->key ); +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 ( &hmac_drbg_algorithm, context, state->key, &key_len ); - assert ( key_len == sizeof ( state->key ) ); - hmac_update ( &hmac_drbg_algorithm, context, - state->value, sizeof ( state->value ) ); - hmac_final ( &hmac_drbg_algorithm, context, state->key, &key_len, - state->value ); - assert ( key_len == sizeof ( state->key ) ); + 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 %p V = HMAC ( K, V ) :\n", state ); - DBGC_HDA ( state, 0, state->value, sizeof ( state->value ) ); + 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 @@ -133,30 +138,32 @@ static void hmac_drbg_update_value ( struct hmac_drbg_state *state ) { * The key and value are updated in-place within the HMAC_DRBG * internal state. */ -static void hmac_drbg_update ( struct hmac_drbg_state *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 %p update\n", state ); + 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 ( state, data, len, 0x00 ); + hmac_drbg_update_key ( hash, state, data, len, 0x00 ); /* 2. V = HMAC ( K, V ) */ - hmac_drbg_update_value ( state ); + 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 ( state, data, len, 0x01 ); + hmac_drbg_update_key ( hash, state, data, len, 0x01 ); /* 5. V = HMAC ( K, V ) */ - hmac_drbg_update_value ( state ); + hmac_drbg_update_value ( hash, state ); /* 6. Return K and V */ } @@ -164,6 +171,7 @@ static void hmac_drbg_update ( struct hmac_drbg_state *state, /** * 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 @@ -182,17 +190,18 @@ static void hmac_drbg_update ( struct hmac_drbg_state *state, * The key, value and reseed counter are updated in-place within the * HMAC_DRBG internal state. */ -void hmac_drbg_instantiate ( struct hmac_drbg_state *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 %p instantiate\n", state ); + DBGC ( state, "HMAC_DRBG_%s %p instantiate\n", hash->name, state ); /* Sanity checks */ + assert ( hash != NULL ); assert ( state != NULL ); assert ( entropy != NULL ); - assert ( ( 8 * entropy_len ) >= - ( 3 * HMAC_DRBG_SECURITY_STRENGTH / 2 ) ); assert ( ( personal != NULL ) || ( personal_len == 0 ) ); /* 1. seed_material = entropy_input || nonce || @@ -200,23 +209,24 @@ void hmac_drbg_instantiate ( struct hmac_drbg_state *state, */ /* 2. Key = 0x00 00..00 */ - memset ( state->key, 0x00, sizeof ( state->key ) ); + memset ( state->key, 0x00, out_len ); /* 3. V = 0x01 01...01 */ - memset ( state->value, 0x01, sizeof ( state->value ) ); + 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 ( state, entropy, entropy_len, + 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 @@ -229,27 +239,29 @@ void hmac_drbg_instantiate ( struct hmac_drbg_state *state, * The key, value and reseed counter are updated in-place within the * HMAC_DRBG internal state. */ -void hmac_drbg_reseed ( struct hmac_drbg_state *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 %p (re)seed\n", state ); + DBGC ( state, "HMAC_DRBG_%s %p (re)seed\n", hash->name, state ); /* Sanity checks */ + assert ( hash != NULL ); assert ( state != NULL ); assert ( entropy != NULL ); - assert ( ( 8 * entropy_len ) >= HMAC_DRBG_SECURITY_STRENGTH ); 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 %p seed material :\n", state ); + 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 ( state, seed_material, sizeof ( seed_material ) ); + hmac_drbg_update ( hash, state, seed_material, + sizeof ( seed_material ) ); /* 3. reseed_counter = 1 */ state->reseed_counter = 1; @@ -260,6 +272,7 @@ void hmac_drbg_reseed ( struct hmac_drbg_state *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 @@ -277,16 +290,19 @@ void hmac_drbg_reseed ( struct hmac_drbg_state *state, * * Note that the only permitted error is "reseed required". */ -int hmac_drbg_generate ( struct hmac_drbg_state *state, +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 %p generate\n", state ); + 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 ) ); @@ -295,8 +311,8 @@ int hmac_drbg_generate ( struct hmac_drbg_state *state, * indication that a reseed is required */ if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) { - DBGC ( state, "HMAC_DRBG %p reseed interval exceeded\n", - state ); + DBGC ( state, "HMAC_DRBG_%s %p reseed interval exceeded\n", + hash->name, state ); return -ESTALE; } @@ -304,7 +320,7 @@ int hmac_drbg_generate ( struct hmac_drbg_state *state, * ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */ if ( additional_len ) - hmac_drbg_update ( state, additional, additional_len ); + hmac_drbg_update ( hash, state, additional, additional_len ); /* 3. temp = Null * 4. While ( len ( temp ) < requested_number_of_bits ) do: @@ -312,27 +328,27 @@ int hmac_drbg_generate ( struct hmac_drbg_state *state, while ( len ) { /* 4.1 V = HMAC ( Key, V ) */ - hmac_drbg_update_value ( state ); + 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 > sizeof ( state->value ) ) - frag_len = sizeof ( state->value ); + 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 ( state, additional, additional_len ); + hmac_drbg_update ( hash, state, additional, additional_len ); /* 7. reseed_counter = reseed_counter + 1 */ state->reseed_counter++; - DBGC ( state, "HMAC_DRBG %p generated :\n", state ); + 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 diff --git a/src/crypto/md5.c b/src/crypto/md5.c index ef322ad2..b8b7b43d 100644 --- a/src/crypto/md5.c +++ b/src/crypto/md5.c @@ -1,234 +1,297 @@ -/* - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); +/** @file + * + * MD5 algorithm + * + */ + #include #include #include +#include +#include #include +#include #include +/** MD5 variables */ +struct md5_variables { + /* This layout matches that of struct md5_digest_data, + * allowing for efficient endianness-conversion, + */ + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t w[16]; +} __attribute__ (( packed )); + +/** MD5 constants */ +static const uint32_t k[64] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, + 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, + 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, + 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, + 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, + 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +/** MD5 shift amounts */ +static const uint8_t r[64] = { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; + +/** + * f(b,c,d) for steps 0 to 15 + * + * @v v MD5 variables + * @ret f f(b,c,d) + */ +static uint32_t md5_f_0_15 ( struct md5_variables *v ) { + return ( v->d ^ ( v->b & ( v->c ^ v->d ) ) ); +} + +/** + * f(b,c,d) for steps 16 to 31 + * + * @v v MD5 variables + * @ret f f(b,c,d) + */ +static uint32_t md5_f_16_31 ( struct md5_variables *v ) { + return ( v->c ^ ( v->d & ( v->b ^ v->c ) ) ); +} + +/** + * f(b,c,d) for steps 32 to 47 + * + * @v v MD5 variables + * @ret f f(b,c,d) + */ +static uint32_t md5_f_32_47 ( struct md5_variables *v ) { + return ( v->b ^ v->c ^ v->d ); +} + +/** + * f(b,c,d) for steps 48 to 63 + * + * @v v MD5 variables + * @ret f f(b,c,d) + */ +static uint32_t md5_f_48_63 ( struct md5_variables *v ) { + return ( v->c ^ ( v->b | (~v->d) ) ); +} + +/** An MD5 step function */ struct md5_step { - u32 ( * f ) ( u32 b, u32 c, u32 d ); - u8 coefficient; - u8 constant; + /** + * 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 u32 f1(u32 b, u32 c, u32 d) -{ - return ( d ^ ( b & ( c ^ d ) ) ); -} - -static u32 f2(u32 b, u32 c, u32 d) -{ - return ( c ^ ( d & ( b ^ c ) ) ); -} - -static u32 f3(u32 b, u32 c, u32 d) -{ - return ( b ^ c ^ d ); -} - -static u32 f4(u32 b, u32 c, u32 d) -{ - return ( c ^ ( b | ~d ) ); -} - +/** MD5 steps */ 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, - } + /** 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 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 -}; +/** + * Initialise MD5 algorithm + * + * @v ctx MD5 context + */ +static void md5_init ( void *ctx ) { + struct md5_context *context = ctx; -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, -}; + 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; +} -static void md5_transform(u32 *hash, const u32 *in) -{ - u32 a, b, c, d, f, g, temp; - int i; +/** + * 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; - a = hash[0]; - b = hash[1]; - c = hash[2]; - d = hash[3]; + /* Sanity checks */ + assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); + linker_assert ( &u.ddd.dd.digest.h[0] == a, md5_bad_layout ); + linker_assert ( &u.ddd.dd.digest.h[1] == b, md5_bad_layout ); + linker_assert ( &u.ddd.dd.digest.h[2] == c, md5_bad_layout ); + linker_assert ( &u.ddd.dd.digest.h[3] == d, md5_bad_layout ); + linker_assert ( &u.ddd.dd.data.dword[0] == w, md5_bad_layout ); + DBGC ( context, "MD5 digesting:\n" ); + DBGC_HDA ( context, 0, &context->ddd.dd.digest, + sizeof ( context->ddd.dd.digest ) ); + DBGC_HDA ( context, context->len, &context->ddd.dd.data, + sizeof ( context->ddd.dd.data ) ); + + /* Convert h[0..3] to host-endian, and initialise a, b, c, d, + * and w[0..15] + */ + for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) / + sizeof ( u.ddd.dword[0] ) ) ; i++ ) { + le32_to_cpus ( &context->ddd.dword[i] ); + u.ddd.dword[i] = context->ddd.dword[i]; + } + + /* Main loop */ for ( i = 0 ; i < 64 ; i++ ) { - step = &md5_steps[i >> 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; + 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 ); } - hash[0] += a; - hash[1] += b; - hash[2] += c; - hash[3] += d; + /* Add chunk to hash and convert back to big-endian */ + for ( i = 0 ; i < 4 ; i++ ) { + context->ddd.dd.digest.h[i] = + cpu_to_le32 ( context->ddd.dd.digest.h[i] + + u.ddd.dd.digest.h[i] ); + } + + DBGC ( context, "MD5 digested:\n" ); + DBGC_HDA ( context, 0, &context->ddd.dd.digest, + sizeof ( context->ddd.dd.digest ) ); } -/* 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++; +/** + * Accumulate data with MD5 algorithm + * + * @v ctx MD5 context + * @v data Data + * @v len Length of data + */ +static void md5_update ( void *ctx, const void *data, size_t len ) { + struct md5_context *context = ctx; + const uint8_t *byte = data; + size_t offset; + + /* Accumulate data a byte at a time, performing the digest + * whenever we fill the data buffer + */ + while ( len-- ) { + offset = ( context->len % sizeof ( context->ddd.dd.data ) ); + context->ddd.dd.data.byte[offset] = *(byte++); + context->len++; + if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ) + md5_digest ( context ); } } -static inline void cpu_to_le32_array(u32 *buf, unsigned int words) -{ - while (words--) { - cpu_to_le32s(buf); - buf++; - } -} - -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; - - mctx->hash[0] = 0x67452301; - mctx->hash[1] = 0xefcdab89; - mctx->hash[2] = 0x98badcfe; - mctx->hash[3] = 0x10325476; - mctx->byte_count = 0; -} - -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; - - if (avail > len) { - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, len); - return; - } - - memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), - data, avail); - - md5_transform_helper(mctx); - data += avail; - len -= avail; - - while (len >= sizeof(mctx->block)) { - memcpy(mctx->block, data, sizeof(mctx->block)); - md5_transform_helper(mctx); - data += sizeof(mctx->block); - len -= sizeof(mctx->block); - } - - 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; - } - - 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)); +/** + * Generate MD5 digest + * + * @v ctx MD5 context + * @v out Output buffer + */ +static void md5_final ( void *ctx, void *out ) { + struct md5_context *context = ctx; + uint64_t len_bits; + uint8_t pad; + + /* Record length before pre-processing */ + len_bits = cpu_to_le64 ( ( ( uint64_t ) context->len ) * 8 ); + + /* Pad with a single "1" bit followed by as many "0" bits as required */ + pad = 0x80; + do { + md5_update ( ctx, &pad, sizeof ( pad ) ); + pad = 0x00; + } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) != + offsetof ( typeof ( context->ddd.dd.data ), final.len ) ); + + /* Append length (in bits) */ + md5_update ( ctx, &len_bits, sizeof ( len_bits ) ); + assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); + + /* Copy out final digest */ + memcpy ( out, &context->ddd.dd.digest, + sizeof ( context->ddd.dd.digest ) ); } +/** MD5 algorithm */ struct digest_algorithm md5_algorithm = { .name = "md5", - .ctxsize = 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/src/crypto/null_entropy.c b/src/crypto/null_entropy.c new file mode 100644 index 00000000..be2acae3 --- /dev/null +++ b/src/crypto/null_entropy.c @@ -0,0 +1,35 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Nonexistent entropy source + * + * + * This source provides no entropy and must NOT be used in a + * security-sensitive environment. + */ + +#include + +PROVIDE_ENTROPY_INLINE ( null, min_entropy_per_sample ); +PROVIDE_ENTROPY_INLINE ( null, entropy_enable ); +PROVIDE_ENTROPY_INLINE ( null, entropy_disable ); +PROVIDE_ENTROPY_INLINE ( null, get_noise ); diff --git a/src/crypto/random_nz.c b/src/crypto/random_nz.c new file mode 100644 index 00000000..7b54aad7 --- /dev/null +++ b/src/crypto/random_nz.c @@ -0,0 +1,75 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Random non-zero bytes + * + * The RSA algorithm requires the generation of random non-zero bytes, + * i.e. bytes in the range [0x01,0xff]. + * + * This algorithm is designed to comply with ANS X9.82 Part 1-2006 + * Section 9.2.1. This standard is not freely available, but most of + * the text appears to be shared with NIST SP 800-90, which can be + * downloaded from + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + * + * Where possible, references are given to both documents. In the + * case of any disagreement, ANS X9.82 takes priority over NIST SP + * 800-90. (In particular, note that some algorithms that are + * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) + */ + +#include +#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/src/crypto/rbg.c b/src/crypto/rbg.c new file mode 100644 index 00000000..da0ad5df --- /dev/null +++ b/src/crypto/rbg.c @@ -0,0 +1,114 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * RBG mechanism + * + * This mechanism is designed to comply with ANS X9.82 Part 4 (April + * 2011 Draft) Section 10. This standard is unfortunately not freely + * available. + * + * The chosen RBG design is that of a DRBG with a live entropy source + * with no conditioning function. Only a single security strength is + * supported. No seedfile is used since there may be no non-volatile + * storage available. The system UUID is used as the personalisation + * string. + */ + +#include +#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/src/crypto/rootcert.c b/src/crypto/rootcert.c new file mode 100644 index 00000000..ee2a3454 --- /dev/null +++ b/src/crypto/rootcert.c @@ -0,0 +1,132 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/crypto/rsa.c b/src/crypto/rsa.c new file mode 100644 index 00000000..be2696ba --- /dev/null +++ b/src/crypto/rsa.c @@ -0,0 +1,648 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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; + const struct asn1_bit_string *bit_string; + 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 */ + asn1_enter ( &cursor, ASN1_BIT_STRING ); + + /* Check and skip unused-bits byte of bit string */ + bit_string = cursor.data; + if ( ( cursor.len < sizeof ( *bit_string ) ) || + ( bit_string->unused != 0 ) ) { + rc = -EINVAL; + goto err_parse; + } + cursor.data = &bit_string->data; + cursor.len -= offsetof ( typeof ( *bit_string ), data ); + + /* Enter RSAPublicKey */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); + } + + /* Extract modulus */ + if ( ( rc = rsa_parse_integer ( context, &modulus, &cursor ) ) != 0 ) + goto err_parse; + asn1_skip_any ( &cursor ); + + /* Skip public exponent, if applicable */ + if ( is_private ) + asn1_skip ( &cursor, ASN1_INTEGER ); + + /* Extract publicExponent/privateExponent */ + if ( ( rc = rsa_parse_integer ( context, &exponent, &cursor ) ) != 0 ) + goto err_parse; + + DBGC ( context, "RSA %p modulus:\n", context ); + DBGC_HDA ( context, 0, modulus.data, modulus.len ); + DBGC ( context, "RSA %p exponent:\n", context ); + DBGC_HDA ( context, 0, exponent.data, exponent.len ); + + /* Allocate dynamic storage */ + if ( ( rc = rsa_alloc ( context, modulus.len, exponent.len ) ) != 0 ) + goto err_alloc; + + /* Construct big integers */ + bigint_init ( ( ( bigint_t ( context->size ) * ) context->modulus0 ), + modulus.data, modulus.len ); + bigint_init ( ( ( bigint_t ( context->exponent_size ) * ) + context->exponent0 ), exponent.data, exponent.len ); + + return 0; + + rsa_free ( context ); + err_alloc: + err_parse: + return rc; +} + +/** + * Calculate RSA maximum output length + * + * @v ctx RSA context + * @ret max_len Maximum output length + */ +static size_t rsa_max_len ( void *ctx ) { + struct rsa_context *context = ctx; + + return context->max_len; +} + +/** + * Perform RSA cipher operation + * + * @v context RSA context + * @v in Input buffer + * @v out Output buffer + */ +static void rsa_cipher ( struct rsa_context *context, + const void *in, void *out ) { + bigint_t ( context->size ) *input = ( ( void * ) context->input0 ); + bigint_t ( context->size ) *output = ( ( void * ) context->output0 ); + bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 ); + bigint_t ( context->exponent_size ) *exponent = + ( ( void * ) context->exponent0 ); + + /* Initialise big integer */ + bigint_init ( input, in, context->max_len ); + + /* Perform modular exponentiation */ + bigint_mod_exp ( input, modulus, exponent, output, context->tmp ); + + /* Copy out result */ + bigint_done ( output, out, context->max_len ); +} + +/** + * Encrypt using RSA + * + * @v ctx RSA context + * @v plaintext Plaintext + * @v plaintext_len Length of plaintext + * @v ciphertext Ciphertext + * @ret ciphertext_len Length of ciphertext, or negative error + */ +static int rsa_encrypt ( void *ctx, const void *plaintext, + size_t plaintext_len, void *ciphertext ) { + struct rsa_context *context = ctx; + void *temp; + uint8_t *encoded; + size_t max_len = ( context->max_len - 11 ); + size_t random_nz_len = ( max_len - plaintext_len + 8 ); + int rc; + + /* Sanity check */ + if ( plaintext_len > max_len ) { + DBGC ( context, "RSA %p plaintext too long (%zd bytes, max " + "%zd)\n", context, plaintext_len, max_len ); + return -ERANGE; + } + DBGC ( context, "RSA %p encrypting:\n", context ); + DBGC_HDA ( context, 0, plaintext, plaintext_len ); + + /* Construct encoded message (using the big integer output + * buffer as temporary storage) + */ + temp = context->output0; + encoded = temp; + encoded[0] = 0x00; + encoded[1] = 0x02; + if ( ( rc = get_random_nz ( &encoded[2], random_nz_len ) ) != 0 ) { + DBGC ( context, "RSA %p could not generate random data: %s\n", + context, strerror ( rc ) ); + return rc; + } + encoded[ 2 + random_nz_len ] = 0x00; + memcpy ( &encoded[ context->max_len - plaintext_len ], + plaintext, plaintext_len ); + + /* Encipher the encoded message */ + rsa_cipher ( context, encoded, ciphertext ); + DBGC ( context, "RSA %p encrypted:\n", context ); + DBGC_HDA ( context, 0, ciphertext, context->max_len ); + + return context->max_len; +} + +/** + * Decrypt using RSA + * + * @v ctx RSA context + * @v ciphertext Ciphertext + * @v ciphertext_len Ciphertext length + * @v plaintext Plaintext + * @ret plaintext_len Plaintext length, or negative error + */ +static int rsa_decrypt ( void *ctx, const void *ciphertext, + size_t ciphertext_len, void *plaintext ) { + struct rsa_context *context = ctx; + void *temp; + uint8_t *encoded; + uint8_t *end; + uint8_t *zero; + uint8_t *start; + size_t plaintext_len; + + /* Sanity check */ + if ( ciphertext_len != context->max_len ) { + DBGC ( context, "RSA %p ciphertext incorrect length (%zd " + "bytes, should be %zd)\n", + context, ciphertext_len, context->max_len ); + return -ERANGE; + } + DBGC ( context, "RSA %p decrypting:\n", context ); + DBGC_HDA ( context, 0, ciphertext, ciphertext_len ); + + /* Decipher the message (using the big integer input buffer as + * temporary storage) + */ + temp = context->input0; + encoded = temp; + rsa_cipher ( context, ciphertext, encoded ); + + /* Parse the message */ + end = ( encoded + context->max_len ); + if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) ) + goto invalid; + zero = memchr ( &encoded[2], 0, ( end - &encoded[2] ) ); + if ( ! zero ) + goto invalid; + start = ( zero + 1 ); + plaintext_len = ( end - start ); + + /* Copy out message */ + memcpy ( plaintext, start, plaintext_len ); + DBGC ( context, "RSA %p decrypted:\n", context ); + DBGC_HDA ( context, 0, plaintext, plaintext_len ); + + return plaintext_len; + + invalid: + DBGC ( context, "RSA %p invalid decrypted message:\n", context ); + DBGC_HDA ( context, 0, encoded, context->max_len ); + return -EINVAL; +} + +/** + * Encode RSA digest + * + * @v context RSA context + * @v digest Digest algorithm + * @v value Digest value + * @v encoded Encoded digest + * @ret rc Return status code + */ +static int rsa_encode_digest ( struct rsa_context *context, + struct digest_algorithm *digest, + const void *value, void *encoded ) { + struct rsa_digestinfo_prefix *prefix; + size_t digest_len = digest->digestsize; + uint8_t *temp = encoded; + size_t digestinfo_len; + size_t max_len; + size_t pad_len; + + /* Identify prefix */ + prefix = rsa_find_prefix ( digest ); + if ( ! prefix ) { + DBGC ( context, "RSA %p has no prefix for %s\n", + context, digest->name ); + return -ENOTSUP; + } + digestinfo_len = ( prefix->len + digest_len ); + + /* Sanity check */ + max_len = ( context->max_len - 11 ); + if ( digestinfo_len > max_len ) { + DBGC ( context, "RSA %p %s digestInfo too long (%zd bytes, max" + "%zd)\n", + context, digest->name, digestinfo_len, max_len ); + return -ERANGE; + } + DBGC ( context, "RSA %p encoding %s digest:\n", + context, digest->name ); + DBGC_HDA ( context, 0, value, digest_len ); + + /* Construct encoded message */ + *(temp++) = 0x00; + *(temp++) = 0x01; + pad_len = ( max_len - digestinfo_len + 8 ); + memset ( temp, 0xff, pad_len ); + temp += pad_len; + *(temp++) = 0x00; + memcpy ( temp, prefix->data, prefix->len ); + temp += prefix->len; + memcpy ( temp, value, digest_len ); + temp += digest_len; + assert ( temp == ( encoded + context->max_len ) ); + DBGC ( context, "RSA %p encoded %s digest:\n", context, digest->name ); + DBGC_HDA ( context, 0, encoded, context->max_len ); + + return 0; +} + +/** + * Sign digest value using RSA + * + * @v ctx RSA context + * @v digest Digest algorithm + * @v value Digest value + * @v signature Signature + * @ret signature_len Signature length, or negative error + */ +static int rsa_sign ( void *ctx, struct digest_algorithm *digest, + const void *value, void *signature ) { + struct rsa_context *context = ctx; + void *temp; + int rc; + + DBGC ( context, "RSA %p signing %s digest:\n", context, digest->name ); + DBGC_HDA ( context, 0, value, digest->digestsize ); + + /* Encode digest (using the big integer output buffer as + * temporary storage) + */ + temp = context->output0; + if ( ( rc = rsa_encode_digest ( context, digest, value, temp ) ) != 0 ) + return rc; + + /* Encipher the encoded digest */ + rsa_cipher ( context, temp, signature ); + DBGC ( context, "RSA %p signed %s digest:\n", context, digest->name ); + DBGC_HDA ( context, 0, signature, context->max_len ); + + return context->max_len; +} + +/** + * Verify signed digest value using RSA + * + * @v ctx RSA context + * @v digest Digest algorithm + * @v value Digest value + * @v signature Signature + * @v signature_len Signature length + * @ret rc Return status code + */ +static int rsa_verify ( void *ctx, struct digest_algorithm *digest, + const void *value, const void *signature, + size_t signature_len ) { + struct rsa_context *context = ctx; + void *temp; + void *expected; + void *actual; + int rc; + + /* Sanity check */ + if ( signature_len != context->max_len ) { + DBGC ( context, "RSA %p signature incorrect length (%zd " + "bytes, should be %zd)\n", + context, signature_len, context->max_len ); + return -ERANGE; + } + DBGC ( context, "RSA %p verifying %s digest:\n", + context, digest->name ); + DBGC_HDA ( context, 0, value, digest->digestsize ); + DBGC_HDA ( context, 0, signature, signature_len ); + + /* Decipher the signature (using the big integer input buffer + * as temporary storage) + */ + temp = context->input0; + expected = temp; + rsa_cipher ( context, signature, expected ); + DBGC ( context, "RSA %p deciphered signature:\n", context ); + DBGC_HDA ( context, 0, expected, context->max_len ); + + /* Encode digest (using the big integer output buffer as + * temporary storage) + */ + temp = context->output0; + actual = temp; + if ( ( rc = rsa_encode_digest ( context, digest, value, actual ) ) !=0 ) + return rc; + + /* Verify the signature */ + if ( memcmp ( actual, expected, context->max_len ) != 0 ) { + DBGC ( context, "RSA %p signature verification failed\n", + context ); + return -EACCES_VERIFY; + } + + DBGC ( context, "RSA %p signature verified successfully\n", context ); + return 0; +} + +/** + * Finalise RSA cipher + * + * @v ctx RSA context + */ +static void rsa_final ( void *ctx ) { + struct rsa_context *context = ctx; + + rsa_free ( context ); +} + +/** RSA public-key algorithm */ +struct pubkey_algorithm rsa_algorithm = { + .name = "rsa", + .ctxsize = sizeof ( struct rsa_context ), + .init = rsa_init, + .max_len = rsa_max_len, + .encrypt = rsa_encrypt, + .decrypt = rsa_decrypt, + .sign = rsa_sign, + .verify = rsa_verify, + .final = rsa_final, +}; diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c new file mode 100644 index 00000000..7f287d3c --- /dev/null +++ b/src/crypto/sha1.c @@ -0,0 +1,271 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/crypto/sha1extra.c b/src/crypto/sha1extra.c index 74445e9d..01d5f89c 100644 --- a/src/crypto/sha1extra.c +++ b/src/crypto/sha1extra.c @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include #include #include #include @@ -46,7 +47,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 +68,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 +98,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 +148,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/src/crypto/sha256.c b/src/crypto/sha256.c new file mode 100644 index 00000000..e85d2006 --- /dev/null +++ b/src/crypto/sha256.c @@ -0,0 +1,255 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/crypto/x509.c b/src/crypto/x509.c index 28d28fc1..6e3cfead 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -20,164 +20,1780 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#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_BIT_STRING \ + __einfo_error ( EINFO_EINVAL_BIT_STRING ) +#define EINFO_EINVAL_BIT_STRING \ + __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" ) +#define EINVAL_TIME \ + __einfo_error ( EINFO_EINVAL_TIME ) +#define EINFO_EINVAL_TIME \ + __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid time" ) +#define EINVAL_ALGORITHM_MISMATCH \ + __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH ) +#define EINFO_EINVAL_ALGORITHM_MISMATCH \ + __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" ) +#define EINVAL_PATH_LEN \ + __einfo_error ( EINFO_EINVAL_PATH_LEN ) +#define EINFO_EINVAL_PATH_LEN \ + __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" ) +#define EINVAL_VERSION \ + __einfo_error ( EINFO_EINVAL_VERSION ) +#define EINFO_EINVAL_VERSION \ + __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" ) +#define EACCES_WRONG_ISSUER \ + __einfo_error ( EINFO_EACCES_WRONG_ISSUER ) +#define EINFO_EACCES_WRONG_ISSUER \ + __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" ) +#define EACCES_NOT_CA \ + __einfo_error ( EINFO_EACCES_NOT_CA ) +#define EINFO_EACCES_NOT_CA \ + __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" ) +#define EACCES_KEY_USAGE \ + __einfo_error ( EINFO_EACCES_KEY_USAGE ) +#define EINFO_EACCES_KEY_USAGE \ + __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" ) +#define EACCES_EXPIRED \ + __einfo_error ( EINFO_EACCES_EXPIRED ) +#define EINFO_EACCES_EXPIRED \ + __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" ) +#define EACCES_PATH_LEN \ + __einfo_error ( EINFO_EACCES_PATH_LEN ) +#define EINFO_EACCES_PATH_LEN \ + __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" ) +#define EACCES_UNTRUSTED \ + __einfo_error ( EINFO_EACCES_UNTRUSTED ) +#define EINFO_EACCES_UNTRUSTED \ + __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" ) +#define EACCES_OUT_OF_ORDER \ + __einfo_error ( EINFO_EACCES_OUT_OF_ORDER ) +#define EINFO_EACCES_OUT_OF_ORDER \ + __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" ) +#define EACCES_EMPTY \ + __einfo_error ( EINFO_EACCES_EMPTY ) +#define EINFO_EACCES_EMPTY \ + __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" ) + +/** Certificate cache */ +static LIST_HEAD ( x509_cache ); /** - * Identify X.509 certificate public key + * Free X.509 certificate * - * @v certificate Certificate - * @v algorithm Public key algorithm to fill in - * @v pubkey Public key value to fill in + * @v refcnt Reference count + */ +static void x509_free ( struct refcnt *refcnt ) { + struct x509_certificate *cert = + container_of ( refcnt, struct x509_certificate, refcnt ); + + DBGC2 ( cert, "X509 %p freed\n", cert ); + free ( cert->subject.name ); + free ( cert->extensions.auth_info.ocsp.uri ); + free ( cert ); +} + +/** + * Discard a cached certificate + * + * @ret discarded Number of cached items discarded + */ +static unsigned int x509_discard ( void ) { + struct x509_certificate *cert; + + /* Discard the least recently used certificate for which the + * only reference is held by the cache itself. + */ + list_for_each_entry_reverse ( cert, &x509_cache, list ) { + if ( cert->refcnt.count == 0 ) { + list_del ( &cert->list ); + x509_put ( cert ); + return 1; + } + } + return 0; +} + +/** X.509 cache discarder */ +struct cache_discarder x509_cache_discarder __cache_discarder = { + .discard = x509_discard, +}; + +/** "commonName" object identifier */ +static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME }; + +/** "commonName" object identifier cursor */ +static struct asn1_cursor oid_common_name_cursor = + ASN1_OID_CURSOR ( oid_common_name ); + +/** + * Parse X.509 certificate algorithm + * + * @v cert X.509 certificate + * @v algorithm Algorithm to fill in + * @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_pubkey_algorithm ( struct x509_certificate *cert, + struct asn1_algorithm **algorithm, + const struct asn1_cursor *raw ) { + + /* Parse algorithm */ + *algorithm = asn1_algorithm ( raw ); + if ( ! (*algorithm) ) { + DBGC ( cert, "X509 %p unrecognised algorithm:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -ENOTSUP_ALGORITHM; + } + + /* Check algorithm has a public key */ + if ( ! (*algorithm)->pubkey ) { + DBGC ( cert, "X509 %p algorithm %s is not a public-key " + "algorithm:\n", cert, (*algorithm)->name ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_ALGORITHM; + } + + return 0; +} + +/** + * Parse X.509 certificate signature algorithm + * + * @v cert X.509 certificate + * @v algorithm Algorithm to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_signature_algorithm ( struct x509_certificate *cert, + struct asn1_algorithm **algorithm, + const struct asn1_cursor *raw ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, + raw ) ) != 0 ) + return rc; + + /* Check algorithm is a signature algorithm */ + if ( ! (*algorithm)->digest ) { + DBGC ( cert, "X509 %p algorithm %s is not a signature " + "algorithm:\n", cert, (*algorithm)->name ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_ALGORITHM; + } + + return 0; +} + +/** + * Parse X.509 certificate bit string + * + * @v cert X.509 certificate + * @v bits Bit string to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_bit_string ( struct x509_certificate *cert, + struct x509_bit_string *bits, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + const struct asn1_bit_string *bit_string; + size_t len; + unsigned int unused; + uint8_t unused_mask; + const uint8_t *last; + int rc; + + /* Enter bit string */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + if ( ( rc = asn1_enter ( &cursor, ASN1_BIT_STRING ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot locate bit string:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + /* Validity checks */ + if ( cursor.len < sizeof ( *bit_string ) ) { + DBGC ( cert, "X509 %p invalid bit string:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_BIT_STRING; + } + bit_string = cursor.data; + len = ( cursor.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 ( cert, "X509 %p invalid bit string:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_BIT_STRING; + } + + /* Populate bit string */ + bits->data = &bit_string->data; + bits->len = len; + bits->unused = unused; + + return 0; +} + +/** + * Parse X.509 certificate bit string that must be an integral number of bytes + * + * @v cert X.509 certificate + * @v bits Bit string to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_integral_bit_string ( struct x509_certificate *cert, + struct x509_bit_string *bits, + const struct asn1_cursor *raw ) { + int rc; + + /* Parse bit string */ + if ( ( rc = x509_parse_bit_string ( cert, bits, raw ) ) != 0 ) + return rc; + + /* Check that there are no unused bits at end of string */ + if ( bits->unused ) { + DBGC ( cert, "X509 %p invalid integral bit string:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_BIT_STRING; + } + + return 0; +} + +/** + * Parse X.509 certificate time + * + * @v cert X.509 certificate + * @v time Time to fill in + * @v raw ASN.1 cursor + * @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. + */ +static int x509_parse_time ( struct x509_certificate *cert, + struct x509_time *time, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + 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 ( &cursor, raw, sizeof ( cursor ) ); + type = asn1_type ( &cursor ); + switch ( type ) { + case ASN1_UTC_TIME: + have_century = 0; + break; + case ASN1_GENERALIZED_TIME: + have_century = 1; + break; + default: + DBGC ( cert, "X509 %p invalid time type %02x\n", cert, type ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_TIME; + } + + /* Enter utcTime/generalizedTime */ + if ( ( rc = asn1_enter ( &cursor, type ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot locate %s time:\n", cert, + ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + /* Parse digit string a pair at a time */ + data = cursor.data; + remaining = cursor.len; + for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { + if ( remaining < 2 ) { + DBGC ( cert, "X509 %p invalid time:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_TIME; + } + tens = data[0]; + units = data[1]; + if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) { + DBGC ( cert, "X509 %p invalid time:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_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 ( cert, "X509 %p invalid time:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_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->time = mktime ( &tm ); + + return 0; +} + +/** + * Parse X.509 certificate version + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_version ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int version; + int rc; + + /* Enter version */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + + /* Parse integer */ + if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot parse version: %s\n", + cert, strerror ( rc ) ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + /* Sanity check */ + if ( version < 0 ) { + DBGC ( cert, "X509 %p invalid version %d\n", cert, version ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL_VERSION; + } + + /* Record version */ + cert->version = version; + DBGC2 ( cert, "X509 %p is a version %d certificate\n", + cert, ( cert->version + 1 ) ); + + return 0; +} + +/** + * Parse X.509 certificate serial number + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_serial ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_serial *serial = &cert->serial; + int rc; + + /* Record raw serial number */ + memcpy ( &serial->raw, raw, sizeof ( serial->raw ) ); + if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n", + cert, strerror ( rc ) ); + return rc; + } + DBGC2 ( cert, "X509 %p issuer is:\n", cert ); + DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len ); + + return 0; +} + +/** + * Parse X.509 certificate issuer + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_issuer ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_issuer *issuer = &cert->issuer; + int rc; + + /* Record raw issuer */ + memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) ); + if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot shrink issuer: %s\n", + cert, strerror ( rc ) ); + return rc; + } + DBGC2 ( cert, "X509 %p issuer is:\n", cert ); + DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len ); + + return 0; +} + +/** + * Parse X.509 certificate validity + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_validity ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_validity *validity = &cert->validity; + struct x509_time *not_before = &validity->not_before; + struct x509_time *not_after = &validity->not_after; struct asn1_cursor cursor; int rc; - /* Locate subjectPublicKeyInfo */ - memcpy ( &cursor, certificate, sizeof ( cursor ) ); - rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */ - asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */ - asn1_skip_if_exists ( &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 validity */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse notBefore */ + if ( ( rc = x509_parse_time ( cert, not_before, &cursor ) ) != 0 ) return rc; + DBGC2 ( cert, "X509 %p valid from time %lld\n", + cert, not_before->time ); + asn1_skip_any ( &cursor ); + + /* Parse notAfter */ + if ( ( rc = x509_parse_time ( cert, not_after, &cursor ) ) != 0 ) + return rc; + DBGC2 ( cert, "X509 %p valid until time %lld\n", + cert, not_after->time ); + + return 0; +} + +/** + * Parse X.509 certificate common name + * + * @v cert X.509 certificate + * @v name Common name to fill in + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_common_name ( struct x509_certificate *cert, char **name, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + struct asn1_cursor oid_cursor; + struct asn1_cursor name_cursor; + int rc; + + /* Enter name */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Scan through name list */ + for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) { + + /* Check for "commonName" OID */ + memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) ); + asn1_enter ( &oid_cursor, ASN1_SET ); + asn1_enter ( &oid_cursor, ASN1_SEQUENCE ); + memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) ); + asn1_enter ( &oid_cursor, ASN1_OID ); + if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0) + continue; + asn1_skip_any ( &name_cursor ); + if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot locate name:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + /* Allocate and copy name */ + *name = zalloc ( name_cursor.len + 1 /* NUL */ ); + if ( ! *name ) + return -ENOMEM; + memcpy ( *name, name_cursor.data, name_cursor.len ); + + /* Check that name contains no NULs */ + if ( strlen ( *name ) != name_cursor.len ) { + DBGC ( cert, "X509 %p contains malicious commonName:\n", + cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + return 0; } - /* 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 ); - return rc; - } + /* Certificates may not have a commonName */ + DBGC2 ( cert, "X509 %p no commonName found:\n", cert ); + return 0; +} - /* 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 ); +/** + * Parse X.509 certificate subject + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_subject ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_subject *subject = &cert->subject; + char **name = &subject->name; + int rc; + + /* Record raw subject */ + memcpy ( &subject->raw, raw, sizeof ( subject->raw ) ); + asn1_shrink_any ( &subject->raw ); + DBGC2 ( cert, "X509 %p subject is:\n", cert ); + DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len ); + + /* Parse common name */ + if ( ( rc = x509_parse_common_name ( cert, name, raw ) ) != 0 ) return rc; + DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert, *name ); + + return 0; +} + +/** + * Parse X.509 certificate public key information + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_public_key ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_public_key *public_key = &cert->subject.public_key; + struct asn1_algorithm **algorithm = &public_key->algorithm; + struct asn1_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 ) ); + + /* Enter subjectPublicKeyInfo */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse algorithm */ + if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, + &cursor ) ) != 0 ) + return rc; + DBGC2 ( cert, "X509 %p public key algorithm is %s\n", + cert, (*algorithm)->name ); + DBGC2 ( cert, "X509 %p public key is:\n", cert ); + DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len ); + + 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; } /** - * Identify X.509 certificate RSA modulus and public exponent + * Parse X.509 certificate key usage * - * @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 - * - * The caller is responsible for eventually calling - * x509_free_rsa_public_key() to free the storage allocated to hold - * the RSA modulus and exponent. */ -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_key_usage ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_key_usage *usage = &cert->extensions.usage; + struct x509_bit_string bit_string; + const uint8_t *bytes; + size_t len; + unsigned int i; int rc; - /* First, extract the public key algorithm and key data */ - if ( ( rc = x509_public_key ( certificate, &algorithm, - &pubkey ) ) != 0 ) + /* Mark extension as present */ + usage->present = 1; + + /* Parse bit string */ + if ( ( rc = x509_parse_bit_string ( cert, &bit_string, raw ) ) != 0 ) return rc; - /* 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; + /* 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 ) ); } - 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; - } - - /* Check that public key is a byte string, i.e. that the - * "unused bits" byte contains zero. - */ - 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 ) - 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; - - 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 ); + 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 }; + +/** Supported key purposes */ +static struct x509_key_purpose x509_key_purposes[] = { + { + .name = "codeSigning", + .bits = X509_CODE_SIGNING, + .oid = ASN1_OID_CURSOR ( oid_code_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 ); + } + + /* Parse serialNumber */ + if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse signature */ + if ( ( rc = x509_parse_signature_algorithm ( cert, algorithm, + &cursor ) ) != 0 ) + return rc; + DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n", + cert, (*algorithm)->name ); + asn1_skip_any ( &cursor ); + + /* Parse issuer */ + if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse validity */ + if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse subject */ + if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse subjectPublicKeyInfo */ + if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse extensions, if present */ + if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Parse X.509 certificate from ASN.1 data + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_signature *signature = &cert->signature; + struct asn1_algorithm **signature_algorithm = &signature->algorithm; + struct x509_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 = x509_parse_signature_algorithm ( cert, signature_algorithm, + &cursor ) ) != 0 ) + return rc; + DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n", + cert, (*signature_algorithm)->name ); + asn1_skip_any ( &cursor ); + + /* Parse signatureValue */ + if ( ( rc = x509_parse_integral_bit_string ( cert, signature_value, + &cursor ) ) != 0 ) + return rc; + DBGC2 ( cert, "X509 %p signatureValue is:\n", cert ); + DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len ); + + /* Check that algorithm in tbsCertificate matches algorithm in + * signature + */ + if ( signature->algorithm != (*signature_algorithm) ) { + DBGC ( cert, "X509 %p signature algorithm %s does not match " + "signatureAlgorithm %s\n", + cert, signature->algorithm->name, + (*signature_algorithm)->name ); + return -EINVAL_ALGORITHM_MISMATCH; + } + + return 0; +} + +/** + * Create X.509 certificate + * + * @v data Raw certificate data + * @v len Length of raw data + * @ret cert X.509 certificate + * @ret rc Return status code + * + * On success, the caller holds a reference to the X.509 certificate, + * and is responsible for ultimately calling x509_put(). + */ +int x509_certificate ( const void *data, size_t len, + struct x509_certificate **cert ) { + struct asn1_cursor cursor; + void *raw; + int rc; + + /* Initialise cursor */ + cursor.data = data; + cursor.len = len; + asn1_shrink_any ( &cursor ); + + /* Search for certificate within cache */ + list_for_each_entry ( (*cert), &x509_cache, list ) { + if ( asn1_compare ( &cursor, &(*cert)->raw ) == 0 ) { + + DBGC2 ( *cert, "X509 %p \"%s\" cache hit\n", + *cert, (*cert)->subject.name ); + + /* Mark as most recently used */ + list_del ( &(*cert)->list ); + list_add ( &(*cert)->list, &x509_cache ); + + /* Add caller's reference */ + x509_get ( *cert ); + + return 0; + } + } + + /* Allocate and initialise certificate */ + *cert = zalloc ( sizeof ( **cert ) + cursor.len ); + if ( ! *cert ) + return -ENOMEM; + ref_init ( &(*cert)->refcnt, x509_free ); + INIT_LIST_HEAD ( &(*cert)->list ); + raw = ( *cert + 1 ); + + /* Copy raw data */ + memcpy ( raw, cursor.data, cursor.len ); + cursor.data = raw; + + /* Parse certificate */ + if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) { + x509_put ( *cert ); + return rc; + } + + /* Add certificate to cache */ + x509_get ( *cert ); + list_add ( &(*cert)->list, &x509_cache ); + + return 0; +} + +/** + * Check X.509 certificate signature + * + * @v cert X.509 certificate + * @v public_key X.509 public key + * @ret rc Return status code + */ +static int x509_check_signature ( struct x509_certificate *cert, + struct x509_public_key *public_key ) { + struct x509_signature *signature = &cert->signature; + struct asn1_algorithm *algorithm = signature->algorithm; + struct digest_algorithm *digest = algorithm->digest; + struct pubkey_algorithm *pubkey = algorithm->pubkey; + uint8_t digest_ctx[ digest->ctxsize ]; + uint8_t digest_out[ digest->digestsize ]; + uint8_t pubkey_ctx[ pubkey->ctxsize ]; + int rc; + + /* Sanity check */ + assert ( cert->signature_algorithm == cert->signature.algorithm ); + + /* Calculate certificate digest */ + digest_init ( digest, digest_ctx ); + digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len ); + digest_final ( digest, digest_ctx, digest_out ); + DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, cert->subject.name ); + DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) ); + + /* Check that signature public key algorithm matches signer */ + if ( public_key->algorithm->pubkey != pubkey ) { + DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not " + "match signer's algorithm %s\n", + cert, cert->subject.name, algorithm->name, + public_key->algorithm->name ); + rc = -EINVAL_ALGORITHM_MISMATCH; + goto err_mismatch; + } + + /* Verify signature using signer's public key */ + if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data, + public_key->raw.len ) ) != 0 ) { + DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: " + "%s\n", cert, cert->subject.name, strerror ( rc ) ); + goto err_pubkey_init; + } + if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out, + signature->value.data, + signature->value.len ) ) != 0 ) { + DBGC ( cert, "X509 %p \"%s\" signature verification failed: " + "%s\n", cert, cert->subject.name, strerror ( rc ) ); + goto err_pubkey_verify; + } + + /* Success */ + rc = 0; + + err_pubkey_verify: + pubkey_final ( pubkey, pubkey_ctx ); + err_pubkey_init: + err_mismatch: + return rc; +} + +/** + * Check X.509 certificate against issuer certificate + * + * @v cert X.509 certificate + * @v issuer X.509 issuer certificate + * @ret rc Return status code + */ +int x509_check_issuer ( struct x509_certificate *cert, + struct x509_certificate *issuer ) { + struct x509_public_key *public_key = &issuer->subject.public_key; + int rc; + + /* Check issuer. In theory, this should be a full X.500 DN + * comparison, which would require support for a plethora of + * abominations such as TeletexString (which allows the + * character set to be changed mid-string using escape codes). + * In practice, we assume that anyone who deliberately changes + * the encoding of the issuer DN is probably a masochist who + * will rather enjoy the process of figuring out exactly why + * their certificate doesn't work. + * + * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt + * for some enjoyable ranting on this subject. + */ + if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) { + DBGC ( cert, "X509 %p \"%s\" issuer does not match X509 %p " + "\"%s\" subject\n", cert, cert->subject.name, + issuer, issuer->subject.name ); + DBGC_HDA ( cert, 0, cert->issuer.raw.data, + cert->issuer.raw.len ); + DBGC_HDA ( issuer, 0, issuer->subject.raw.data, + issuer->subject.raw.len ); + return -EACCES_WRONG_ISSUER; + } + + /* Check that issuer is allowed to sign certificates */ + if ( ! issuer->extensions.basic.ca ) { + DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": " + "not a CA certificate\n", issuer, issuer->subject.name, + cert, cert->subject.name ); + return -EACCES_NOT_CA; + } + if ( issuer->extensions.usage.present && + ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) { + DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": " + "no keyCertSign usage\n", issuer, issuer->subject.name, + cert, cert->subject.name ); + return -EACCES_KEY_USAGE; + } + + /* Check signature */ + if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Calculate X.509 certificate fingerprint + * + * @v cert X.509 certificate + * @v digest Digest algorithm + * @v fingerprint Fingerprint buffer + */ +void x509_fingerprint ( struct x509_certificate *cert, + struct digest_algorithm *digest, + void *fingerprint ) { + uint8_t ctx[ digest->ctxsize ]; + + /* Calculate fingerprint */ + digest_init ( digest, ctx ); + digest_update ( digest, ctx, cert->raw.data, cert->raw.len ); + digest_final ( digest, ctx, fingerprint ); +} + +/** + * Check X.509 root certificate + * + * @v cert X.509 certificate + * @v root X.509 root certificate store + * @ret rc Return status code + */ +int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) { + struct digest_algorithm *digest = root->digest; + uint8_t fingerprint[ digest->digestsize ]; + const uint8_t *root_fingerprint = root->fingerprints; + unsigned int i; + + /* Calculate certificate fingerprint */ + x509_fingerprint ( cert, digest, fingerprint ); + + /* Check fingerprint against all root certificates */ + for ( i = 0 ; i < root->count ; i++ ) { + if ( memcmp ( fingerprint, root_fingerprint, + sizeof ( fingerprint ) ) == 0 ) { + DBGC ( cert, "X509 %p \"%s\" is a root certificate\n", + cert, cert->subject.name ); + return 0; + } + root_fingerprint += sizeof ( fingerprint ); + } + + DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n", + cert, cert->subject.name ); + return -ENOENT; +} + +/** + * Check X.509 certificate validity period + * + * @v cert X.509 certificate + * @v time Time at which to check certificate + * @ret rc Return status code + */ +int x509_check_time ( struct x509_certificate *cert, time_t time ) { + struct x509_validity *validity = &cert->validity; + + /* Check validity period */ + if ( time < validity->not_before.time ) { + DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n", + cert, cert->subject.name, time ); + return -EACCES_EXPIRED; + } + if ( time > validity->not_after.time ) { + DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n", + cert, cert->subject.name, time ); + return -EACCES_EXPIRED; + } + + DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n", + cert, cert->subject.name, time ); + return 0; +} + +/** + * Validate X.509 certificate + * + * @v cert X.509 certificate + * @v issuer Issuing X.509 certificate (or NULL) + * @v time Time at which to validate certificate + * @v root Root certificate store, or NULL to use default + * @ret rc Return status code + * + * The issuing certificate must have already been validated. + * + * Validation results are cached: if a certificate has already been + * successfully validated then @c issuer, @c time, and @c root will be + * ignored. + */ +static int x509_validate ( struct x509_certificate *cert, + struct x509_certificate *issuer, + time_t time, struct x509_root *root ) { + unsigned int max_path_remaining; + int rc; + + /* Use default root certificate store if none specified */ + if ( ! root ) + root = &root_certificates; + + /* Return success if certificate has already been validated */ + if ( cert->valid ) + return 0; + + /* Fail if certificate is invalid at specified time */ + if ( ( rc = x509_check_time ( cert, time ) ) != 0 ) + return rc; + + /* Succeed if certificate is a trusted root certificate */ + if ( x509_check_root ( cert, root ) == 0 ) { + cert->valid = 1; + cert->path_remaining = ( cert->extensions.basic.path_len + 1 ); + return 0; + } + + /* Fail unless we have an issuer */ + if ( ! issuer ) { + DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n", + cert, cert->subject.name ); + return -EACCES_UNTRUSTED; + } + + /* Fail unless issuer has already been validated */ + if ( ! issuer->valid ) { + DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" has not yet " + "been validated\n", cert, cert->subject.name, + issuer, issuer->subject.name ); + return -EACCES_OUT_OF_ORDER; + } + + /* Fail if issuing certificate cannot validate this certificate */ + if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 ) + return rc; + + /* Fail if path length constraint is violated */ + if ( issuer->path_remaining == 0 ) { + DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" path length " + "exceeded\n", cert, cert->subject.name, + issuer, issuer->subject.name ); + return -EACCES_PATH_LEN; + } + + /* Calculate effective path length */ + cert->path_remaining = ( issuer->path_remaining - 1 ); + max_path_remaining = ( cert->extensions.basic.path_len + 1 ); + if ( cert->path_remaining > max_path_remaining ) + cert->path_remaining = max_path_remaining; + + /* Mark certificate as valid */ + cert->valid = 1; + + DBGC ( cert, "X509 %p \"%s\" successfully validated using issuer %p " + "\"%s\"\n", cert, cert->subject.name, + issuer, issuer->subject.name ); + return 0; +} + +/** + * Free X.509 certificate chain + * + * @v refcnt Reference count + */ +static void x509_free_chain ( struct refcnt *refcnt ) { + struct x509_chain *chain = + container_of ( refcnt, struct x509_chain, refcnt ); + struct x509_link *link; + struct x509_link *tmp; + + DBGC2 ( chain, "X509 chain %p freed\n", chain ); + + /* Free each link in the chain */ + list_for_each_entry_safe ( link, tmp, &chain->links, list ) { + x509_put ( link->cert ); + list_del ( &link->list ); + free ( link ); + } + + /* Free chain */ + free ( chain ); +} + +/** + * Allocate X.509 certificate chain + * + * @ret chain X.509 certificate chain, or NULL + */ +struct x509_chain * x509_alloc_chain ( void ) { + struct x509_chain *chain; + + /* Allocate chain */ + chain = zalloc ( sizeof ( *chain ) ); + if ( ! chain ) + return NULL; + + /* Initialise chain */ + ref_init ( &chain->refcnt, x509_free_chain ); + INIT_LIST_HEAD ( &chain->links ); + + DBGC2 ( chain, "X509 chain %p allocated\n", chain ); + return chain; +} + +/** + * Append X.509 certificate to X.509 certificate chain + * + * @v chain X.509 certificate chain + * @v cert X.509 certificate + * @ret rc Return status code + */ +int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) { + struct x509_link *link; + + /* Allocate link */ + link = zalloc ( sizeof ( *link ) ); + if ( ! link ) + return -ENOMEM; + + /* Add link to chain */ + link->cert = x509_get ( cert ); + list_add_tail ( &link->list, &chain->links ); + DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n", + chain, cert, cert->subject.name ); + + return 0; +} + +/** + * Append X.509 certificate to X.509 certificate chain + * + * @v chain X.509 certificate chain + * @v data Raw certificate data + * @v len Length of raw data + * @ret rc Return status code + */ +int x509_append_raw ( struct x509_chain *chain, const void *data, + size_t len ) { + struct x509_certificate *cert; + int rc; + + /* Parse certificate */ + if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 ) + goto err_parse; + + /* Append certificate to chain */ + if ( ( rc = x509_append ( chain, cert ) ) != 0 ) + goto err_append; + + /* Drop reference to certificate */ + x509_put ( cert ); + + return 0; + + err_append: + x509_put ( cert ); + err_parse: + return rc; +} + +/** + * Identify X.509 certificate by subject + * + * @v certs X.509 certificate list + * @v subject Subject + * @ret cert X.509 certificate, or NULL if not found + */ +static struct x509_certificate * +x509_find_subject ( struct x509_chain *certs, + const struct asn1_cursor *subject ) { + struct x509_link *link; + struct x509_certificate *cert; + + /* Scan through certificate list */ + list_for_each_entry ( link, &certs->links, list ) { + + /* Check subject */ + cert = link->cert; + if ( asn1_compare ( subject, &cert->subject.raw ) == 0 ) + return cert; + } + + return NULL; +} + +/** + * Append X.509 certificates to X.509 certificate chain + * + * @v chain X.509 certificate chain + * @v certs X.509 certificate list + * @ret rc Return status code + * + * Certificates will be automatically appended to the chain based upon + * the subject and issuer names. + */ +int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) { + struct x509_certificate *cert; + struct x509_certificate *previous; + int rc; + + /* Get current certificate */ + cert = x509_last ( chain ); + if ( ! cert ) { + DBGC ( chain, "X509 chain %p has no certificates\n", chain ); + return -EINVAL; + } + + /* Append certificates, in order */ + while ( 1 ) { + + /* Find issuing certificate */ + previous = cert; + cert = x509_find_subject ( certs, &cert->issuer.raw ); + if ( ! cert ) + break; + if ( cert == previous ) + break; + + /* Append certificate to chain */ + if ( ( rc = x509_append ( chain, cert ) ) != 0 ) + return rc; + } + + return 0; +} + +/** + * Validate X.509 certificate chain + * + * @v chain X.509 certificate chain + * @v time Time at which to validate certificates + * @v root Root certificate store, or NULL to use default + * @ret rc Return status code + */ +int x509_validate_chain ( struct x509_chain *chain, time_t time, + struct x509_root *root ) { + struct x509_certificate *issuer = NULL; + struct x509_link *link; + int rc; + + /* Sanity check */ + if ( list_empty ( &chain->links ) ) { + DBGC ( chain, "X509 chain %p is empty\n", chain ); + return -EACCES_EMPTY; + } + + /* Find first certificate that can be validated as a + * standalone (i.e. is already valid, or can be validated as + * a trusted root certificate). + */ + list_for_each_entry ( link, &chain->links, list ) { + + /* Try validating this certificate as a standalone */ + if ( ( rc = x509_validate ( link->cert, NULL, time, + root ) ) != 0 ) + continue; + + /* Work back up to start of chain, performing pairwise + * validation. + */ + issuer = link->cert; + list_for_each_entry_continue_reverse ( link, &chain->links, + list ) { + + /* Validate this certificate against its issuer */ + if ( ( rc = x509_validate ( link->cert, issuer, time, + root ) ) != 0 ) + return rc; + issuer = link->cert; + } + + return 0; + } + + DBGC ( chain, "X509 chain %p found no valid certificates\n", chain ); + return -EACCES_UNTRUSTED; +} diff --git a/src/drivers/net/3c509-eisa.c b/src/drivers/net/3c509-eisa.c index 195a844a..81c60ee9 100644 --- a/src/drivers/net/3c509-eisa.c +++ b/src/drivers/net/3c509-eisa.c @@ -6,7 +6,6 @@ #include #include -#include #include "3c509.h" /* diff --git a/src/drivers/net/ath/ath9k/ath9k_mac.c b/src/drivers/net/ath/ath9k/ath9k_mac.c index fbb3c334..c2f6d630 100644 --- a/src/drivers/net/ath/ath9k/ath9k_mac.c +++ b/src/drivers/net/ath/ath9k/ath9k_mac.c @@ -638,7 +638,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); } -void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) +void ath9k_hw_set_interrupts(struct ath_hw *ah, unsigned int ints) { enum ath9k_int omask = ah->imask; u32 mask, mask2; diff --git a/src/drivers/net/ath/ath9k/mac.h b/src/drivers/net/ath/ath9k/mac.h index c11fe4a5..5899230e 100644 --- a/src/drivers/net/ath/ath9k/mac.h +++ b/src/drivers/net/ath/ath9k/mac.h @@ -668,7 +668,6 @@ enum ath9k_key_type { struct ath_hw; struct ath9k_channel; -enum ath9k_int; u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); @@ -699,7 +698,7 @@ 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, enum ath9k_int ints); +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); diff --git a/src/drivers/net/cs89x0.c b/src/drivers/net/cs89x0.c index ee34d0c5..876b8785 100644 --- a/src/drivers/net/cs89x0.c +++ b/src/drivers/net/cs89x0.c @@ -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/src/drivers/net/depca.c b/src/drivers/net/depca.c index 735a52df..016f28bb 100644 --- a/src/drivers/net/depca.c +++ b/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/src/drivers/net/e1000/e1000.c b/src/drivers/net/e1000/e1000.c deleted file mode 100644 index a32a4d7c..00000000 --- a/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/src/drivers/net/e1000/e1000.h b/src/drivers/net/e1000/e1000.h deleted file mode 100644 index 31dbb859..00000000 --- a/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/src/drivers/net/e1000/e1000_82540.c b/src/drivers/net/e1000/e1000_82540.c deleted file mode 100644 index 41f3f979..00000000 --- a/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/src/drivers/net/e1000/e1000_82541.c b/src/drivers/net/e1000/e1000_82541.c deleted file mode 100644 index 2d1aecc7..00000000 --- a/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/src/drivers/net/e1000/e1000_82541.h b/src/drivers/net/e1000/e1000_82541.h deleted file mode 100644 index f86a1482..00000000 --- a/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/src/drivers/net/e1000/e1000_82542.c b/src/drivers/net/e1000/e1000_82542.c deleted file mode 100644 index b6d5202c..00000000 --- a/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/src/drivers/net/e1000/e1000_82543.c b/src/drivers/net/e1000/e1000_82543.c deleted file mode 100644 index 848c99e7..00000000 --- a/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/src/drivers/net/e1000/e1000_82543.h b/src/drivers/net/e1000/e1000_82543.h deleted file mode 100644 index 30073e8b..00000000 --- a/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/src/drivers/net/e1000/e1000_api.c b/src/drivers/net/e1000/e1000_api.c deleted file mode 100644 index 72aac4c4..00000000 --- a/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/src/drivers/net/e1000/e1000_api.h b/src/drivers/net/e1000/e1000_api.h deleted file mode 100644 index fc1e533d..00000000 --- a/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/src/drivers/net/e1000/e1000_defines.h b/src/drivers/net/e1000/e1000_defines.h deleted file mode 100644 index c585f09b..00000000 --- a/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/src/drivers/net/e1000/e1000_hw.h b/src/drivers/net/e1000/e1000_hw.h deleted file mode 100644 index 753f75e7..00000000 --- a/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/src/drivers/net/e1000/e1000_mac.c b/src/drivers/net/e1000/e1000_mac.c deleted file mode 100644 index 23513879..00000000 --- a/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/src/drivers/net/e1000/e1000_mac.h b/src/drivers/net/e1000/e1000_mac.h deleted file mode 100644 index 51acae08..00000000 --- a/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/src/drivers/net/e1000/e1000_main.c b/src/drivers/net/e1000/e1000_main.c deleted file mode 100644 index bc2aa968..00000000 --- a/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_RS | 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/src/drivers/net/e1000/e1000_manage.c b/src/drivers/net/e1000/e1000_manage.c deleted file mode 100644 index 3362942e..00000000 --- a/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/src/drivers/net/e1000/e1000_manage.h b/src/drivers/net/e1000/e1000_manage.h deleted file mode 100644 index 14467aa6..00000000 --- a/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/src/drivers/net/e1000/e1000_nvm.c b/src/drivers/net/e1000/e1000_nvm.c deleted file mode 100644 index 488252f4..00000000 --- a/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/src/drivers/net/e1000/e1000_nvm.h b/src/drivers/net/e1000/e1000_nvm.h deleted file mode 100644 index 1585417c..00000000 --- a/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/src/drivers/net/e1000/e1000_osdep.h b/src/drivers/net/e1000/e1000_osdep.h deleted file mode 100644 index 5cd8e391..00000000 --- a/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/src/drivers/net/e1000/e1000_phy.c b/src/drivers/net/e1000/e1000_phy.c deleted file mode 100644 index b3cad480..00000000 --- a/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/src/drivers/net/e1000/e1000_phy.h b/src/drivers/net/e1000/e1000_phy.h deleted file mode 100644 index 93bd7a1b..00000000 --- a/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/src/drivers/net/e1000/e1000_regs.h b/src/drivers/net/e1000/e1000_regs.h deleted file mode 100644 index 579c0707..00000000 --- a/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/src/drivers/net/e1000e/e1000e.c b/src/drivers/net/e1000e/e1000e.c deleted file mode 100644 index b7318b7d..00000000 --- a/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/src/drivers/net/e1000e/e1000e.h b/src/drivers/net/e1000e/e1000e.h deleted file mode 100644 index bc8e7b08..00000000 --- a/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/src/drivers/net/e1000e/e1000e_80003es2lan.c b/src/drivers/net/e1000e/e1000e_80003es2lan.c deleted file mode 100644 index a3eed9b7..00000000 --- a/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/src/drivers/net/e1000e/e1000e_80003es2lan.h b/src/drivers/net/e1000e/e1000e_80003es2lan.h deleted file mode 100644 index 93430a16..00000000 --- a/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/src/drivers/net/e1000e/e1000e_82571.c b/src/drivers/net/e1000e/e1000e_82571.c deleted file mode 100644 index a061d6d4..00000000 --- a/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/src/drivers/net/e1000e/e1000e_82571.h b/src/drivers/net/e1000e/e1000e_82571.h deleted file mode 100644 index c645e25a..00000000 --- a/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/src/drivers/net/e1000e/e1000e_defines.h b/src/drivers/net/e1000e/e1000e_defines.h deleted file mode 100644 index da135d91..00000000 --- a/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/src/drivers/net/e1000e/e1000e_hw.h b/src/drivers/net/e1000e/e1000e_hw.h deleted file mode 100644 index 03ed35c9..00000000 --- a/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/src/drivers/net/e1000e/e1000e_ich8lan.c b/src/drivers/net/e1000e/e1000e_ich8lan.c deleted file mode 100644 index 7b9a49b9..00000000 --- a/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/src/drivers/net/e1000e/e1000e_ich8lan.h b/src/drivers/net/e1000e/e1000e_ich8lan.h deleted file mode 100644 index af344782..00000000 --- a/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/src/drivers/net/e1000e/e1000e_mac.c b/src/drivers/net/e1000e/e1000e_mac.c deleted file mode 100644 index d96b279f..00000000 --- a/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/src/drivers/net/e1000e/e1000e_mac.h b/src/drivers/net/e1000e/e1000e_mac.h deleted file mode 100644 index 5b8a4251..00000000 --- a/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/src/drivers/net/e1000e/e1000e_main.c b/src/drivers/net/e1000e/e1000e_main.c deleted file mode 100644 index 352e3c45..00000000 --- a/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_RCTL_SECRC; - 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/src/drivers/net/e1000e/e1000e_manage.c b/src/drivers/net/e1000e/e1000e_manage.c deleted file mode 100644 index e0935362..00000000 --- a/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/src/drivers/net/e1000e/e1000e_manage.h b/src/drivers/net/e1000e/e1000e_manage.h deleted file mode 100644 index f136aee8..00000000 --- a/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/src/drivers/net/e1000e/e1000e_nvm.c b/src/drivers/net/e1000e/e1000e_nvm.c deleted file mode 100644 index f49d421f..00000000 --- a/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/src/drivers/net/e1000e/e1000e_nvm.h b/src/drivers/net/e1000e/e1000e_nvm.h deleted file mode 100644 index 1a8e0f3f..00000000 --- a/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/src/drivers/net/e1000e/e1000e_phy.c b/src/drivers/net/e1000e/e1000e_phy.c deleted file mode 100644 index 337be737..00000000 --- a/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/src/drivers/net/e1000e/e1000e_phy.h b/src/drivers/net/e1000e/e1000e_phy.h deleted file mode 100644 index 9081050f..00000000 --- a/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/src/drivers/net/e1000e/e1000e_regs.h b/src/drivers/net/e1000e/e1000e_regs.h deleted file mode 100644 index 064d92c9..00000000 --- a/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/src/drivers/net/eepro100.c b/src/drivers/net/eepro100.c index 85840cdf..99dfb180 100644 --- a/src/drivers/net/eepro100.c +++ b/src/drivers/net/eepro100.c @@ -1141,6 +1141,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/src/drivers/net/epic100.c b/src/drivers/net/epic100.c index 5211317f..b478fab5 100644 --- a/src/drivers/net/epic100.c +++ b/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 */ diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index 15e7d4c1..a0a009cb 100644 --- a/src/drivers/net/etherfabric.c +++ b/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 | \ diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c index 5d0137e1..34c59223 100644 --- a/src/drivers/net/forcedeth.c +++ b/src/drivers/net/forcedeth.c @@ -740,8 +740,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 ); diff --git a/src/drivers/net/igb/igb.c b/src/drivers/net/igb/igb.c deleted file mode 100644 index cd5db1ff..00000000 --- a/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/src/drivers/net/igb/igb.h b/src/drivers/net/igb/igb.h deleted file mode 100644 index c8e8205d..00000000 --- a/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/src/drivers/net/igb/igb_82575.c b/src/drivers/net/igb/igb_82575.c deleted file mode 100644 index b5b615ad..00000000 --- a/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/src/drivers/net/igb/igb_82575.h b/src/drivers/net/igb/igb_82575.h deleted file mode 100644 index 12c9a249..00000000 --- a/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/src/drivers/net/igb/igb_api.c b/src/drivers/net/igb/igb_api.c deleted file mode 100644 index eda6bc01..00000000 --- a/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/src/drivers/net/igb/igb_api.h b/src/drivers/net/igb/igb_api.h deleted file mode 100644 index 2d97fecc..00000000 --- a/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/src/drivers/net/igb/igb_defines.h b/src/drivers/net/igb/igb_defines.h deleted file mode 100644 index 4f58ba83..00000000 --- a/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/src/drivers/net/igb/igb_hw.h b/src/drivers/net/igb/igb_hw.h deleted file mode 100644 index 65a04f20..00000000 --- a/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/src/drivers/net/igb/igb_mac.c b/src/drivers/net/igb/igb_mac.c deleted file mode 100644 index 237c6c75..00000000 --- a/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/src/drivers/net/igb/igb_mac.h b/src/drivers/net/igb/igb_mac.h deleted file mode 100644 index 7639e24e..00000000 --- a/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/src/drivers/net/igb/igb_main.c b/src/drivers/net/igb/igb_main.c deleted file mode 100644 index 9295c2c8..00000000 --- a/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/src/drivers/net/igb/igb_manage.c b/src/drivers/net/igb/igb_manage.c deleted file mode 100644 index b29d4c4a..00000000 --- a/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/src/drivers/net/igb/igb_manage.h b/src/drivers/net/igb/igb_manage.h deleted file mode 100644 index ff70d8c9..00000000 --- a/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/src/drivers/net/igb/igb_nvm.c b/src/drivers/net/igb/igb_nvm.c deleted file mode 100644 index 1bad567c..00000000 --- a/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/src/drivers/net/igb/igb_nvm.h b/src/drivers/net/igb/igb_nvm.h deleted file mode 100644 index 6b54d44c..00000000 --- a/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/src/drivers/net/igb/igb_osdep.h b/src/drivers/net/igb/igb_osdep.h deleted file mode 100644 index 84f490f5..00000000 --- a/src/drivers/net/igb/igb_osdep.h +++ /dev/null @@ -1,124 +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 - -#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/src/drivers/net/igb/igb_phy.c b/src/drivers/net/igb/igb_phy.c deleted file mode 100644 index 16664fd1..00000000 --- a/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/src/drivers/net/igb/igb_phy.h b/src/drivers/net/igb/igb_phy.h deleted file mode 100644 index 8e6bc991..00000000 --- a/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/src/drivers/net/igb/igb_regs.h b/src/drivers/net/igb/igb_regs.h deleted file mode 100644 index e549675b..00000000 --- a/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/src/drivers/net/igbvf/igbvf_main.c b/src/drivers/net/igbvf/igbvf_main.c index 1f7e1dfd..cd189ecb 100644 --- a/src/drivers/net/igbvf/igbvf_main.c +++ b/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/src/drivers/net/igbvf/igbvf_vf.h b/src/drivers/net/igbvf/igbvf_vf.h index ce8ad796..8d8963fe 100644 --- a/src/drivers/net/igbvf/igbvf_vf.h +++ b/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/src/drivers/net/intel.c b/src/drivers/net/intel.c new file mode 100644 index 00000000..3eb1a377 --- /dev/null +++ b/src/drivers/net/intel.c @@ -0,0 +1,946 @@ +/* + * 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; + + /* Allocate descriptor ring. Align ring on its own size to + * prevent any possible page-crossing errors due to hardware + * errata. + */ + ring->desc = malloc_dma ( ring->len, ring->len ); + if ( ! ring->desc ) + return -ENOMEM; + + /* Initialise descriptor ring */ + memset ( ring->desc, 0, ring->len ); + + /* Program ring address */ + address = virt_to_bus ( ring->desc ); + writel ( ( address & 0xffffffffUL ), + ( intel->regs + ring->reg + INTEL_xDBAL ) ); + if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { + writel ( ( ( ( uint64_t ) address ) >> 32 ), + ( intel->regs + ring->reg + INTEL_xDBAH ) ); + } else { + writel ( 0, intel->regs + ring->reg + INTEL_xDBAH ); + } + + /* Program ring length */ + writel ( ring->len, ( intel->regs + ring->reg + INTEL_xDLEN ) ); + + /* Reset head and tail pointers */ + writel ( 0, ( intel->regs + ring->reg + INTEL_xDH ) ); + writel ( 0, ( intel->regs + ring->reg + INTEL_xDT ) ); + + DBGC ( intel, "INTEL %p ring %05x is at [%08llx,%08llx)\n", + intel, ring->reg, ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + ring->len ) ); + + return 0; +} + +/** + * Destroy descriptor ring + * + * @v intel Intel device + * @v ring Descriptor ring + */ +static void intel_destroy_ring ( struct intel_nic *intel, + struct intel_ring *ring ) { + + /* Clear ring length */ + writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) ); + + /* Clear ring address */ + writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAL ) ); + writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAH ) ); + + /* Free descriptor ring */ + free_dma ( ring->desc, ring->len ); + ring->desc = NULL; + ring->prod = 0; + ring->cons = 0; +} + +/** + * Refill receive descriptor ring + * + * @v intel Intel device + */ +static void intel_refill_rx ( struct intel_nic *intel ) { + struct intel_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + unsigned int rx_tail; + physaddr_t address; + + while ( ( intel->rx.prod - intel->rx.cons ) < INTEL_RX_FILL ) { + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( INTEL_RX_MAX_LEN ); + if ( ! iobuf ) { + /* Wait for next refill */ + return; + } + + /* Get next receive descriptor */ + rx_idx = ( intel->rx.prod++ % INTEL_NUM_RX_DESC ); + rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC ); + rx = &intel->rx.desc[rx_idx]; + + /* Populate receive descriptor */ + address = virt_to_bus ( iobuf->data ); + rx->address = cpu_to_le64 ( address ); + rx->length = 0; + rx->status = 0; + rx->errors = 0; + wmb(); + + /* Record I/O buffer */ + assert ( intel->rx_iobuf[rx_idx] == NULL ); + intel->rx_iobuf[rx_idx] = iobuf; + + /* Push descriptor to card */ + writel ( rx_tail, intel->regs + INTEL_RDT ); + + DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx, + ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + INTEL_RX_MAX_LEN ) ); + } +} + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int intel_open ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + union intel_receive_address mac; + uint32_t tctl; + uint32_t rctl; + int rc; + + /* Create transmit descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) + goto err_create_tx; + + /* Create receive descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) + goto err_create_rx; + + /* Fill receive ring */ + intel_refill_rx ( intel ); + + /* Program MAC address */ + memset ( &mac, 0, sizeof ( mac ) ); + memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) ); + writel ( le32_to_cpu ( mac.reg.low ), intel->regs + INTEL_RAL0 ); + writel ( ( le32_to_cpu ( mac.reg.high ) | INTEL_RAH0_AV ), + intel->regs + INTEL_RAH0 ); + + /* Enable transmitter */ + tctl = readl ( intel->regs + INTEL_TCTL ); + tctl &= ~( INTEL_TCTL_CT_MASK | INTEL_TCTL_COLD_MASK ); + tctl |= ( INTEL_TCTL_EN | INTEL_TCTL_PSP | INTEL_TCTL_CT_DEFAULT | + INTEL_TCTL_COLD_DEFAULT ); + writel ( tctl, intel->regs + INTEL_TCTL ); + + /* Enable receiver */ + rctl = readl ( intel->regs + INTEL_RCTL ); + rctl &= ~( INTEL_RCTL_BSIZE_BSEX_MASK ); + rctl |= ( INTEL_RCTL_EN | INTEL_RCTL_UPE | INTEL_RCTL_MPE | + INTEL_RCTL_BAM | INTEL_RCTL_BSIZE_2048 | INTEL_RCTL_SECRC ); + writel ( rctl, intel->regs + INTEL_RCTL ); + + /* Update link state */ + intel_check_link ( netdev ); + + return 0; + + intel_destroy_ring ( intel, &intel->rx ); + err_create_rx: + intel_destroy_ring ( intel, &intel->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void intel_close ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + unsigned int i; + + /* Disable receiver */ + writel ( 0, intel->regs + INTEL_RCTL ); + + /* Disable transmitter */ + writel ( 0, intel->regs + INTEL_TCTL ); + + /* Destroy receive descriptor ring */ + intel_destroy_ring ( intel, &intel->rx ); + + /* Discard any unused receive buffers */ + for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) { + if ( intel->rx_iobuf[i] ) + free_iob ( intel->rx_iobuf[i] ); + intel->rx_iobuf[i] = NULL; + } + + /* Destroy transmit descriptor ring */ + intel_destroy_ring ( intel, &intel->tx ); + + /* Reset the NIC, to flush the transmit and receive FIFOs */ + intel_reset ( intel ); +} + +/** + * Transmit packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int intel_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct intel_nic *intel = netdev->priv; + struct intel_descriptor *tx; + unsigned int tx_idx; + unsigned int tx_tail; + physaddr_t address; + + /* Get next transmit descriptor */ + if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_NUM_TX_DESC ) { + DBGC ( intel, "INTEL %p out of transmit descriptors\n", intel ); + return -ENOBUFS; + } + tx_idx = ( intel->tx.prod++ % INTEL_NUM_TX_DESC ); + tx_tail = ( intel->tx.prod % INTEL_NUM_TX_DESC ); + tx = &intel->tx.desc[tx_idx]; + + /* Populate transmit descriptor */ + address = virt_to_bus ( iobuf->data ); + tx->address = cpu_to_le64 ( address ); + tx->length = cpu_to_le16 ( iob_len ( iobuf ) ); + tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS | + INTEL_DESC_CMD_EOP ); + tx->status = 0; + wmb(); + + /* Notify card that there are packets ready to transmit */ + writel ( tx_tail, intel->regs + INTEL_TDT ); + + DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx, + ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + iob_len ( iobuf ) ) ); + + return 0; +} + +/** + * Poll for completed packets + * + * @v netdev Network device + */ +static void intel_poll_tx ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + struct intel_descriptor *tx; + unsigned int tx_idx; + + /* Check for completed packets */ + while ( intel->tx.cons != intel->tx.prod ) { + + /* Get next transmit descriptor */ + tx_idx = ( intel->tx.cons % INTEL_NUM_TX_DESC ); + tx = &intel->tx.desc[tx_idx]; + + /* Stop if descriptor is still in use */ + if ( ! ( tx->status & INTEL_DESC_STATUS_DD ) ) + return; + + DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx ); + + /* Complete TX descriptor */ + netdev_tx_complete_next ( netdev ); + intel->tx.cons++; + } +} + +/** + * Poll for received packets + * + * @v netdev Network device + */ +static void intel_poll_rx ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + struct intel_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + size_t len; + + /* Check for received packets */ + while ( intel->rx.cons != intel->rx.prod ) { + + /* Get next receive descriptor */ + rx_idx = ( intel->rx.cons % INTEL_NUM_RX_DESC ); + rx = &intel->rx.desc[rx_idx]; + + /* Stop if descriptor is still in use */ + if ( ! ( rx->status & INTEL_DESC_STATUS_DD ) ) + return; + + /* Populate I/O buffer */ + iobuf = intel->rx_iobuf[rx_idx]; + intel->rx_iobuf[rx_idx] = NULL; + len = le16_to_cpu ( rx->length ); + iob_put ( iobuf, len ); + + /* Hand off to network stack */ + if ( rx->errors ) { + DBGC ( intel, "INTEL %p RX %d error (length %zd, " + "errors %02x)\n", + intel, rx_idx, len, rx->errors ); + netdev_rx_err ( netdev, iobuf, -EIO ); + } else { + DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n", + intel, rx_idx, len ); + netdev_rx ( netdev, iobuf ); + } + intel->rx.cons++; + } +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void intel_poll ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t icr; + + /* Check for and acknowledge interrupts */ + icr = readl ( intel->regs + INTEL_ICR ); + if ( ! icr ) + return; + + /* Poll for TX completions, if applicable */ + if ( icr & INTEL_IRQ_TXDW ) + intel_poll_tx ( netdev ); + + /* Poll for RX completionsm, if applicable */ + if ( icr & INTEL_IRQ_RXT0 ) + intel_poll_rx ( netdev ); + + /* Check link state, if applicable */ + if ( icr & INTEL_IRQ_LSC ) + intel_check_link ( netdev ); + + /* Refill RX ring */ + intel_refill_rx ( intel ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void intel_irq ( struct net_device *netdev, int enable ) { + struct intel_nic *intel = netdev->priv; + uint32_t mask; + + mask = ( INTEL_IRQ_TXDW | INTEL_IRQ_LSC | INTEL_IRQ_RXT0 ); + if ( enable ) { + writel ( mask, intel->regs + INTEL_IMS ); + } else { + writel ( mask, intel->regs + INTEL_IMC ); + } +} + +/** Intel network device operations */ +static struct net_device_operations intel_operations = { + .open = intel_open, + .close = intel_close, + .transmit = intel_transmit, + .poll = intel_poll, + .irq = intel_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int intel_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct intel_nic *intel; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *intel ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &intel_operations ); + intel = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + memset ( intel, 0, sizeof ( *intel ) ); + intel->port = PCI_FUNC ( pci->busdevfn ); + intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD ); + intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE ); + + /* Reset the NIC */ + if ( ( rc = intel_reset ( intel ) ) != 0 ) + goto err_reset; + + /* Fetch MAC address */ + if ( ( rc = intel_fetch_mac ( intel, netdev->hw_addr ) ) != 0 ) + goto err_fetch_mac; + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + /* Set initial link state */ + intel_check_link ( netdev ); + + return 0; + + unregister_netdev ( netdev ); + err_register_netdev: + err_fetch_mac: + intel_reset ( intel ); + err_reset: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void intel_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct intel_nic *intel = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset the NIC */ + intel_reset ( intel ); + + /* Free network device */ + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** Intel PCI device IDs */ +static struct pci_device_id intel_nics[] = { + PCI_ROM ( 0x8086, 0x0438, "dh8900cc", "DH8900CC", 0 ), + PCI_ROM ( 0x8086, 0x043a, "dh8900cc-f", "DH8900CC Fiber", 0 ), + PCI_ROM ( 0x8086, 0x043c, "dh8900cc-b", "DH8900CC Backplane", 0 ), + PCI_ROM ( 0x8086, 0x0440, "dh8900cc-s", "DH8900CC SFP", 0 ), + PCI_ROM ( 0x8086, 0x1000, "82542-f", "82542 (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x1001, "82543gc-f", "82543GC (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x1004, "82543gc", "82543GC (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1008, "82544ei", "82544EI (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1009, "82544ei-f", "82544EI (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x100c, "82544gc", "82544GC (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x100d, "82544gc-l", "82544GC (LOM)", 0 ), + PCI_ROM ( 0x8086, 0x100e, "82540em", "82540EM", 0 ), + PCI_ROM ( 0x8086, 0x100f, "82545em", "82545EM (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1010, "82546eb", "82546EB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1011, "82545em-f", "82545EM (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x1012, "82546eb-f", "82546EB (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x1013, "82541ei", "82541EI", 0 ), + PCI_ROM ( 0x8086, 0x1014, "82541er", "82541ER", 0 ), + PCI_ROM ( 0x8086, 0x1015, "82540em-l", "82540EM (LOM)", 0 ), + PCI_ROM ( 0x8086, 0x1016, "82540ep-m", "82540EP (Mobile)", 0 ), + PCI_ROM ( 0x8086, 0x1017, "82540ep", "82540EP", 0 ), + PCI_ROM ( 0x8086, 0x1018, "82541ei", "82541EI", 0 ), + PCI_ROM ( 0x8086, 0x1019, "82547ei", "82547EI", 0 ), + PCI_ROM ( 0x8086, 0x101a, "82547ei-m", "82547EI (Mobile)", 0 ), + PCI_ROM ( 0x8086, 0x101d, "82546eb", "82546EB", 0 ), + PCI_ROM ( 0x8086, 0x101e, "82540ep-m", "82540EP (Mobile)", 0 ), + PCI_ROM ( 0x8086, 0x1026, "82545gm", "82545GM", 0 ), + PCI_ROM ( 0x8086, 0x1027, "82545gm-1", "82545GM", 0 ), + PCI_ROM ( 0x8086, 0x1028, "82545gm-2", "82545GM", 0 ), + PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", 0 ), + PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", 0 ), + PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", 0 ), + PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V 10/100", 0 ), + PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", 0 ), + PCI_ROM ( 0x8086, 0x105e, "82571eb", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x105f, "82571eb-1", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x1060, "82571eb-2", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x1075, "82547gi", "82547GI", 0 ), + PCI_ROM ( 0x8086, 0x1076, "82541gi", "82541GI", 0 ), + PCI_ROM ( 0x8086, 0x1077, "82541gi-1", "82541GI", 0 ), + PCI_ROM ( 0x8086, 0x1078, "82541er", "82541ER", 0 ), + PCI_ROM ( 0x8086, 0x1079, "82546gb", "82546GB", 0 ), + PCI_ROM ( 0x8086, 0x107a, "82546gb-1", "82546GB", 0 ), + PCI_ROM ( 0x8086, 0x107b, "82546gb-2", "82546GB", 0 ), + PCI_ROM ( 0x8086, 0x107c, "82541pi", "82541PI", 0 ), + PCI_ROM ( 0x8086, 0x107d, "82572ei", "82572EI (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x107e, "82572ei-f", "82572EI (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x107f, "82572ei", "82572EI", 0 ), + PCI_ROM ( 0x8086, 0x108a, "82546gb-3", "82546GB", 0 ), + PCI_ROM ( 0x8086, 0x108b, "82573v", "82573V (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x108c, "82573e", "82573E (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1096, "80003es2lan", "80003ES2LAN (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x1098, "80003es2lan-s", "80003ES2LAN (Serdes)", 0 ), + PCI_ROM ( 0x8086, 0x1099, "82546gb-4", "82546GB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x109a, "82573l", "82573L", 0 ), + PCI_ROM ( 0x8086, 0x10a4, "82571eb", "82571EB", 0 ), + PCI_ROM ( 0x8086, 0x10a5, "82571eb", "82571EB (Fiber)", 0 ), + PCI_ROM ( 0x8086, 0x10a7, "82575eb", "82575EB", 0 ), + PCI_ROM ( 0x8086, 0x10a9, "82575eb", "82575EB Backplane", 0 ), + PCI_ROM ( 0x8086, 0x10b5, "82546gb", "82546GB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x10b9, "82572ei", "82572EI (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x10ba, "80003es2lan", "80003ES2LAN (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x10bb, "80003es2lan", "80003ES2LAN (Serdes)", 0 ), + PCI_ROM ( 0x8086, 0x10bc, "82571eb", "82571EB (Copper)", 0 ), + PCI_ROM ( 0x8086, 0x10bd, "82566dm-2", "82566DM-2", 0 ), + PCI_ROM ( 0x8086, 0x10bf, "82567lf", "82567LF", 0 ), + PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2 10/100", 0 ), + PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2 10/100", 0 ), + PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2 10/100", 0 ), + PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT 10/100", 0 ), + PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G 10/100", 0 ), + PCI_ROM ( 0x8086, 0x10c9, "82576", "82576", 0 ), + PCI_ROM ( 0x8086, 0x10cb, "82567v", "82567V", 0 ), + PCI_ROM ( 0x8086, 0x10cc, "82567lm-2", "82567LM-2", 0 ), + PCI_ROM ( 0x8086, 0x10cd, "82567lf-2", "82567LF-2", 0 ), + PCI_ROM ( 0x8086, 0x10ce, "82567v-2", "82567V-2", 0 ), + PCI_ROM ( 0x8086, 0x10d3, "82574l", "82574L", 0 ), + PCI_ROM ( 0x8086, 0x10d5, "82571pt", "82571PT PT Quad", 0 ), + PCI_ROM ( 0x8086, 0x10d6, "82575gb", "82575GB", 0 ), + PCI_ROM ( 0x8086, 0x10d9, "82571eb-d", "82571EB Dual Mezzanine", 0 ), + PCI_ROM ( 0x8086, 0x10da, "82571eb-q", "82571EB Quad Mezzanine", 0 ), + PCI_ROM ( 0x8086, 0x10de, "82567lm-3", "82567LM-3", 0 ), + PCI_ROM ( 0x8086, 0x10df, "82567lf-3", "82567LF-3", 0 ), + PCI_ROM ( 0x8086, 0x10e5, "82567lm-4", "82567LM-4", 0 ), + PCI_ROM ( 0x8086, 0x10e6, "82576", "82576", 0 ), + PCI_ROM ( 0x8086, 0x10e7, "82576-2", "82576", 0 ), + PCI_ROM ( 0x8086, 0x10e8, "82576-3", "82576", 0 ), + PCI_ROM ( 0x8086, 0x10ea, "82577lm", "82577LM", 0 ), + PCI_ROM ( 0x8086, 0x10eb, "82577lc", "82577LC", 0 ), + PCI_ROM ( 0x8086, 0x10ef, "82578dm", "82578DM", 0 ), + PCI_ROM ( 0x8086, 0x10f0, "82578dc", "82578DC", 0 ), + PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ), + PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ), + PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", 0 ), + PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ), + PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ), + PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ), + PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ), + PCI_ROM ( 0x8086, 0x150d, "82576-4", "82576 Backplane", 0 ), + PCI_ROM ( 0x8086, 0x150e, "82580", "82580", 0 ), + PCI_ROM ( 0x8086, 0x150f, "82580-f", "82580 Fiber", 0 ), + PCI_ROM ( 0x8086, 0x1510, "82580-b", "82580 Backplane", 0 ), + PCI_ROM ( 0x8086, 0x1511, "82580-s", "82580 SFP", 0 ), + PCI_ROM ( 0x8086, 0x1516, "82580-2", "82580", 0 ), + PCI_ROM ( 0x8086, 0x1518, "82576ns", "82576NS SerDes", 0 ), + PCI_ROM ( 0x8086, 0x1521, "i350", "I350", 0 ), + PCI_ROM ( 0x8086, 0x1522, "i350-f", "I350 Fiber", 0 ), + PCI_ROM ( 0x8086, 0x1523, "i350-b", "I350 Backplane", 0 ), + PCI_ROM ( 0x8086, 0x1524, "i350-2", "I350", 0 ), + PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ), + PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ), + PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ), + PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ), + PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ), +}; + +/** Intel PCI driver */ +struct pci_driver intel_driver __pci_driver = { + .ids = intel_nics, + .id_count = ( sizeof ( intel_nics ) / sizeof ( intel_nics[0] ) ), + .probe = intel_probe, + .remove = intel_remove, +}; diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h new file mode 100644 index 00000000..6f941d17 --- /dev/null +++ b/src/drivers/net/intel.h @@ -0,0 +1,252 @@ +#ifndef _INTEL_H +#define _INTEL_H + +/** @file + * + * Intel 10/100/1000 network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#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 */ + +/** Interrupt Mask Set/Read Register */ +#define INTEL_IMS 0x000d0UL + +/** Interrupt Mask Clear Register */ +#define INTEL_IMC 0x000d8UL + +/** Receive Control Register */ +#define INTEL_RCTL 0x00100UL +#define INTEL_RCTL_EN 0x00000002UL /**< Receive enable */ +#define INTEL_RCTL_UPE 0x00000008UL /**< Unicast promiscuous mode */ +#define INTEL_RCTL_MPE 0x00000010UL /**< Multicast promiscuous */ +#define INTEL_RCTL_BAM 0x00008000UL /**< Broadcast accept mode */ +#define INTEL_RCTL_BSIZE_BSEX(bsex,bsize) \ + ( ( (bsize) << 16 ) | ( (bsex) << 25 ) ) /**< Buffer size */ +#define INTEL_RCTL_BSIZE_2048 INTEL_RCTL_BSIZE_BSEX ( 0, 0 ) +#define INTEL_RCTL_BSIZE_BSEX_MASK INTEL_RCTL_BSIZE_BSEX ( 1, 3 ) +#define INTEL_RCTL_SECRC 0x04000000UL /**< Strip CRC */ + +/** Transmit Control Register */ +#define INTEL_TCTL 0x00400UL +#define INTEL_TCTL_EN 0x00000002UL /**< Transmit enable */ +#define INTEL_TCTL_PSP 0x00000008UL /**< Pad short packets */ +#define INTEL_TCTL_CT(x) ( (x) << 4 ) /**< Collision threshold */ +#define INTEL_TCTL_CT_DEFAULT INTEL_TCTL_CT ( 0x0f ) +#define INTEL_TCTL_CT_MASK INTEL_TCTL_CT ( 0xff ) +#define INTEL_TCTL_COLD(x) ( (x) << 12 ) /**< Collision distance */ +#define INTEL_TCTL_COLD_DEFAULT INTEL_TCTL_COLD ( 0x040 ) +#define INTEL_TCTL_COLD_MASK INTEL_TCTL_COLD ( 0x3ff ) + +/** Packet Buffer Allocation */ +#define INTEL_PBA 0x01000UL + +/** Packet Buffer Size */ +#define INTEL_PBS 0x01008UL + +/** Receive Descriptor register block */ +#define INTEL_RD 0x02800UL + +/** Number of receive descriptors + * + * Minimum value is 8, since the descriptor ring length must be a + * multiple of 128. + */ +#define INTEL_NUM_RX_DESC 8 + +/** Receive descriptor ring fill level */ +#define INTEL_RX_FILL 4 + +/** Receive buffer length */ +#define INTEL_RX_MAX_LEN 2048 + +/** Transmit Descriptor register block */ +#define INTEL_TD 0x03800UL + +/** Number of transmit descriptors + * + * Descriptor ring length must be a multiple of 16. ICH8/9/10 + * requires a minimum of 16 TX descriptors. + */ +#define INTEL_NUM_TX_DESC 16 + +/** Receive/Transmit Descriptor Base Address Low (offset) */ +#define INTEL_xDBAL 0x00 + +/** Receive/Transmit Descriptor Base Address High (offset) */ +#define INTEL_xDBAH 0x04 + +/** Receive/Transmit Descriptor Length (offset) */ +#define INTEL_xDLEN 0x08 + +/** Receive/Transmit Descriptor Head (offset) */ +#define INTEL_xDH 0x10 + +/** Receive/Transmit Descriptor Tail (offset) */ +#define INTEL_xDT 0x18 + +/** Receive Descriptor Head */ +#define INTEL_RDH ( INTEL_RD + INTEL_xDH ) + +/** Receive Descriptor Tail */ +#define INTEL_RDT ( INTEL_RD + INTEL_xDT ) + +/** Transmit Descriptor Head */ +#define INTEL_TDH ( INTEL_TD + INTEL_xDH ) + +/** Transmit Descriptor Tail */ +#define INTEL_TDT ( INTEL_TD + INTEL_xDT ) + +/** Receive Address Low */ +#define INTEL_RAL0 0x05400UL + +/** Receive Address High */ +#define INTEL_RAH0 0x05404UL +#define INTEL_RAH0_AV 0x80000000UL /**< Address valid */ + +/** Receive address */ +union intel_receive_address { + struct { + uint32_t low; + uint32_t high; + } __attribute__ (( packed )) reg; + uint8_t raw[ETH_ALEN]; +}; + +/** An Intel descriptor ring */ +struct intel_ring { + /** Descriptors */ + struct intel_descriptor *desc; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; + + /** Register block */ + unsigned int reg; + /** Length (in bytes) */ + size_t len; +}; + +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Descriptor register block + */ +static inline __attribute__ (( always_inline)) void +intel_init_ring ( struct intel_ring *ring, unsigned int count, + unsigned int reg ) { + ring->len = ( count * sizeof ( ring->desc[0] ) ); + ring->reg = reg; +} + +/** An Intel network card */ +struct intel_nic { + /** Registers */ + void *regs; + /** Port number (for multi-port devices) */ + unsigned int port; + + /** EEPROM */ + struct nvs_device eeprom; + /** EEPROM done flag */ + uint32_t eerd_done; + /** EEPROM address shift */ + unsigned int eerd_addr_shift; + + /** Transmit descriptor ring */ + struct intel_ring tx; + /** Receive descriptor ring */ + struct intel_ring rx; + /** Receive I/O buffers */ + struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC]; +}; + +#endif /* _INTEL_H */ diff --git a/src/drivers/net/mii.c b/src/drivers/net/mii.c new file mode 100644 index 00000000..c8e6529d --- /dev/null +++ b/src/drivers/net/mii.c @@ -0,0 +1,85 @@ +/* + * 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 + * + */ + +/** + * Reset MII interface + * + * @v mii MII interface + * @ret rc Return status code + */ +int mii_reset ( struct mii_interface *mii ) { + unsigned int i; + int bmcr; + int rc; + + /* Power-up, enable autonegotiation and initiate reset */ + if ( ( rc = mii_write ( mii, MII_BMCR, + ( BMCR_RESET | BMCR_ANENABLE ) ) ) != 0 ) { + DBGC ( mii, "MII %p could not write BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + /* Wait for reset to complete */ + for ( i = 0 ; i < MII_RESET_MAX_WAIT_MS ; i++ ) { + + /* Check if reset has completed */ + bmcr = mii_read ( mii, MII_BMCR ); + if ( bmcr < 0 ) { + rc = bmcr; + DBGC ( mii, "MII %p could not read BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + /* If reset is not complete, delay 1ms and retry */ + if ( bmcr & BMCR_RESET ) { + mdelay ( 1 ); + continue; + } + + /* Force autonegotation on again, in case it was + * cleared by the reset. + */ + if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){ + DBGC ( mii, "MII %p could not write BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + DBGC ( mii, "MII %p reset after %dms\n", mii, i ); + return 0; + } + + DBGC ( mii, "MII %p timed out waiting for reset\n", mii ); + return -ETIMEDOUT; +} diff --git a/src/drivers/net/mtd80x.c b/src/drivers/net/mtd80x.c deleted file mode 100644 index 170b5c52..00000000 --- a/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/src/drivers/net/myri10ge.c b/src/drivers/net/myri10ge.c index 5bb555d8..2c9bf960 100644 --- a/src/drivers/net/myri10ge.c +++ b/src/drivers/net/myri10ge.c @@ -304,10 +304,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. */ diff --git a/src/drivers/net/myri10ge_mcp.h b/src/drivers/net/myri10ge_mcp.h index 397f8b0d..391dab37 100644 --- a/src/drivers/net/myri10ge_mcp.h +++ b/src/drivers/net/myri10ge_mcp.h @@ -80,7 +80,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/src/drivers/net/myson.c b/src/drivers/net/myson.c new file mode 100644 index 00000000..25f1a270 --- /dev/null +++ b/src/drivers/net/myson.c @@ -0,0 +1,668 @@ +/* + * 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: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void myson_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct myson_nic *myson = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + myson_reset ( myson ); + + /* Free network device */ + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** Myson PCI device IDs */ +static struct pci_device_id myson_nics[] = { + PCI_ROM ( 0x1516, 0x0800, "mtd800", "MTD-8xx", 0 ), + PCI_ROM ( 0x1516, 0x0803, "mtd803", "Surecom EP-320X-S", 0 ), + PCI_ROM ( 0x1516, 0x0891, "mtd891", "MTD-8xx", 0 ), +}; + +/** Myson PCI driver */ +struct pci_driver myson_driver __pci_driver = { + .ids = myson_nics, + .id_count = ( sizeof ( myson_nics ) / sizeof ( myson_nics[0] ) ), + .probe = myson_probe, + .remove = myson_remove, +}; diff --git a/src/drivers/net/myson.h b/src/drivers/net/myson.h new file mode 100644 index 00000000..8d7cc585 --- /dev/null +++ b/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/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c index 17154281..fb1eb822 100644 --- a/src/drivers/net/natsemi.c +++ b/src/drivers/net/natsemi.c @@ -1,604 +1,927 @@ -/* - 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 #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); +/** @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 + * + */ -/** 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, +/****************************************************************************** + * + * 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; + 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; - eereg = inb ( np->ioaddr + EE_REG ); - return ( eereg & mask ); + 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; + 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; - eereg = inb ( np->ioaddr + EE_REG ); - eereg &= ~mask; - eereg |= ( data & mask ); - outb ( eereg, np->ioaddr + EE_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 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 ); + /* 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 ); - /*natsemi DP 83815 only supports at93c46 - */ - init_at93c46 ( &np->eeprom, 16 ); - np->eeprom.bus = &np->spibit.bus; - - /* 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 ); + /* Initialise EEPROM device */ + init_at93c06 ( &natsemi->eeprom, 16 ); + natsemi->eeprom.bus = &natsemi->spibit.bus; } +/** + * Get hardware address from sane EEPROM data + * + * @v natsemi National Semiconductor device + * @v eeprom EEPROM data + * @v hw_addr Hardware address to fill in + */ +static void natsemi_hwaddr_sane ( struct natsemi_nic *natsemi, + const uint16_t *eeprom, uint16_t *hw_addr ) { + int i; + + /* Copy MAC address from EEPROM data */ + for ( i = ( ( ETH_ALEN / 2 ) - 1 ) ; i >= 0 ; i-- ) + *(hw_addr++) = eeprom[ NATSEMI_EEPROM_MAC_SANE + i ]; + + DBGC ( natsemi, "NATSEMI %p has sane EEPROM layout\n", natsemi ); +} + +/** + * Get hardware address from insane EEPROM data + * + * @v natsemi National Semiconductor device + * @v eeprom EEPROM data + * @v hw_addr Hardware address to fill in + */ +static void natsemi_hwaddr_insane ( struct natsemi_nic *natsemi, + const uint16_t *eeprom, + uint16_t *hw_addr ) { + unsigned int i; + unsigned int offset; + uint16_t word; + + /* Copy MAC address from EEPROM data */ + for ( i = 0 ; i < ( ETH_ALEN / 2 ) ; i++ ) { + offset = ( NATSEMI_EEPROM_MAC_INSANE + i ); + word = ( ( le16_to_cpu ( eeprom[ offset ] ) >> 15 ) | + ( le16_to_cpu ( eeprom[ offset + 1 ] << 1 ) ) ); + hw_addr[i] = cpu_to_le16 ( word ); + } + + DBGC ( natsemi, "NATSEMI %p has insane EEPROM layout\n", natsemi ); +} + +/** + * Get hardware address from EEPROM + * + * @v natsemi National Semiconductor device + * @v hw_addr Hardware address to fill in + * @ret rc Return status code + */ +static int natsemi_hwaddr ( struct natsemi_nic *natsemi, void *hw_addr ) { + uint16_t buf[NATSEMI_EEPROM_SIZE]; + void ( * extract ) ( struct natsemi_nic *natsemi, + const uint16_t *eeprom, uint16_t *hw_addr ); + int rc; + + /* Read EEPROM contents */ + if ( ( rc = nvs_read ( &natsemi->eeprom.nvs, 0, buf, + sizeof ( buf ) ) ) != 0 ) { + DBGC ( natsemi, "NATSEMI %p could not read EEPROM: %s\n", + natsemi, strerror ( rc ) ); + return rc; + } + DBGC2 ( natsemi, "NATSEMI %p EEPROM contents:\n", natsemi ); + DBGC2_HDA ( natsemi, 0, buf, sizeof ( buf ) ); + + /* Extract MAC address from EEPROM contents */ + extract = ( ( natsemi->flags & NATSEMI_EEPROM_INSANE ) ? + natsemi_hwaddr_insane : natsemi_hwaddr_sane ); + extract ( natsemi, buf, hw_addr ); + + return 0; +} + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reset controller chip + * + * @v natsemi National Semiconductor device + * @ret rc Return status code + */ +static int natsemi_soft_reset ( struct natsemi_nic *natsemi ) { + unsigned int i; + + /* Initiate reset */ + writel ( NATSEMI_CR_RST, natsemi->regs + NATSEMI_CR ); + + /* Wait for reset to complete */ + for ( i = 0 ; i < NATSEMI_RESET_MAX_WAIT_MS ; i++ ) { + + /* If reset is not complete, delay 1ms and retry */ + if ( readl ( natsemi->regs + NATSEMI_CR ) & NATSEMI_CR_RST ) { + mdelay ( 1 ); + continue; + } + + return 0; + } + + DBGC ( natsemi, "NATSEMI %p timed out waiting for reset\n", natsemi ); + return -ETIMEDOUT; +} + +/** + * Reload configuration from EEPROM + * + * @v natsemi National Semiconductor device + * @ret rc Return status code + */ +static int natsemi_reload_config ( struct natsemi_nic *natsemi ) { + unsigned int i; + + /* Initiate reload */ + writel ( NATSEMI_PTSCR_EELOAD_EN, natsemi->regs + NATSEMI_PTSCR ); + + /* Wait for reload to complete */ + for ( i = 0 ; i < NATSEMI_EELOAD_MAX_WAIT_MS ; i++ ) { + + /* If reload is not complete, delay 1ms and retry */ + if ( readl ( natsemi->regs + NATSEMI_PTSCR ) & + NATSEMI_PTSCR_EELOAD_EN ) { + mdelay ( 1 ); + continue; + } + + return 0; + } + + DBGC ( natsemi, "NATSEMI %p timed out waiting for configuration " + "reload\n", natsemi ); + return -ETIMEDOUT; +} + +/** + * Reset hardware + * + * @v natsemi National Semiconductor device + * @ret rc Return status code + */ +static int natsemi_reset ( struct natsemi_nic *natsemi ) { + uint32_t cfg; + int rc; + + /* Perform soft reset */ + if ( ( rc = natsemi_soft_reset ( natsemi ) ) != 0 ) + return rc; + + /* Reload configuration from EEPROM */ + if ( ( rc = natsemi_reload_config ( natsemi ) ) != 0 ) + return rc; + + /* Configure 64-bit operation, if applicable */ + cfg = readl ( natsemi->regs + NATSEMI_CFG ); + if ( natsemi->flags & NATSEMI_64BIT ) { + cfg |= ( NATSEMI_CFG_M64ADDR | NATSEMI_CFG_EXTSTS_EN ); + if ( ! ( cfg & NATSEMI_CFG_PCI64_DET ) ) + cfg &= ~NATSEMI_CFG_DATA64_EN; + } + writel ( cfg, natsemi->regs + NATSEMI_CFG ); + + /* Invalidate link status cache to force an update */ + natsemi->cfg = ~cfg; + + DBGC ( natsemi, "NATSEMI %p using configuration %08x\n", + natsemi, cfg ); + return 0; +} + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Check link state + * + * @v netdev Network device + */ +static void natsemi_check_link ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + uint32_t cfg; + + /* Read link status */ + cfg = readl ( natsemi->regs + NATSEMI_CFG ); + + /* Do nothing unless link status has changed */ + if ( cfg == natsemi->cfg ) + return; + + /* Set gigabit mode (if applicable) */ + if ( natsemi->flags & NATSEMI_1000 ) { + cfg &= ~NATSEMI_CFG_MODE_1000; + if ( ! ( cfg & NATSEMI_CFG_SPDSTS1 ) ) + cfg |= NATSEMI_CFG_MODE_1000; + writel ( cfg, natsemi->regs + NATSEMI_CFG ); + } + + /* Update link status */ + natsemi->cfg = cfg; + DBGC ( natsemi, "NATSEMI %p link status is %08x\n", natsemi, cfg ); + + /* Update network device */ + if ( cfg & NATSEMI_CFG_LNKSTS ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Set perfect match filter address + * + * @v natsemi National Semiconductor device + * @v mac MAC address + */ +static void natsemi_pmatch ( struct natsemi_nic *natsemi, const void *mac ) { + const uint16_t *pmatch = mac; + uint32_t rfcr; + unsigned int rfaddr; + unsigned int i; + + for ( i = 0 ; i < ETH_ALEN ; i += sizeof ( *pmatch ) ) { + + /* Select receive filter register address */ + rfaddr = ( NATSEMI_RFADDR_PMATCH_BASE + i ); + rfcr = readl ( natsemi->regs + NATSEMI_RFCR ); + rfcr &= ~NATSEMI_RFCR_RFADDR_MASK; + rfcr |= NATSEMI_RFCR_RFADDR ( rfaddr ); + writel ( rfcr, natsemi->regs + NATSEMI_RFCR ); + + /* Write receive filter data */ + writel ( ( le16_to_cpu ( *(pmatch++) ) | NATSEMI_RFDR_BMASK ), + natsemi->regs + NATSEMI_RFDR ); + } +} + +/** + * Create descriptor ring + * + * @v natsemi National Semiconductor device + * @v ring Descriptor ring + * @ret rc Return status code + */ +static int natsemi_create_ring ( struct natsemi_nic *natsemi, + struct natsemi_ring *ring ) { + size_t len = ( ring->count * sizeof ( ring->desc[0] ) ); + union natsemi_descriptor *desc; + union natsemi_descriptor *linked_desc; + physaddr_t address; + physaddr_t link; + size_t offset; + unsigned int i; + int rc; + + /* Calculate descriptor offset */ + offset = ( ( natsemi->flags & NATSEMI_64BIT ) ? 0 : + offsetof ( typeof ( desc[i].d32pad ), d32 ) ); + + /* Allocate descriptor ring. Align ring on its own size to + * ensure that it can't possibly cross the boundary of 32-bit + * address space. + */ + ring->desc = malloc_dma ( len, len ); + if ( ! ring->desc ) { + rc = -ENOMEM; + goto err_alloc; + } + address = ( virt_to_bus ( ring->desc ) + offset ); + + /* Check address is usable by card */ + if ( ! natsemi_address_ok ( natsemi, address ) ) { + DBGC ( natsemi, "NATSEMI %p cannot support 64-bit ring " + "address\n", natsemi ); + rc = -ENOTSUP; + goto err_64bit; + } + + /* Initialise descriptor ring */ + memset ( ring->desc, 0, len ); + for ( i = 0 ; i < ring->count ; i++ ) { + linked_desc = &ring->desc [ ( i + 1 ) % ring->count ]; + link = ( virt_to_bus ( linked_desc ) + offset ); + if ( natsemi->flags & NATSEMI_64BIT ) { + ring->desc[i].d64.link = cpu_to_le64 ( link ); + } else { + ring->desc[i].d32pad.d32.link = cpu_to_le32 ( link ); + } + } + + /* Program ring address */ + writel ( ( address & 0xffffffffUL ), natsemi->regs + ring->reg ); + if ( natsemi->flags & NATSEMI_64BIT ) { + if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { + writel ( ( ( ( uint64_t ) address ) >> 32 ), + natsemi->regs + ring->reg + 4 ); + } else { + writel ( 0, natsemi->regs + ring->reg + 4 ); + } + } + + DBGC ( natsemi, "NATSEMI %p ring %02x is at [%08llx,%08llx)\n", + natsemi, ring->reg, + ( ( unsigned long long ) virt_to_bus ( ring->desc ) ), + ( ( unsigned long long ) virt_to_bus ( ring->desc ) + len ) ); + + return 0; + + err_64bit: + free_dma ( ring->desc, len ); + ring->desc = NULL; + err_alloc: + return rc; +} + +/** + * Destroy descriptor ring + * + * @v natsemi National Semiconductor device + * @v ring Descriptor ring + */ +static void natsemi_destroy_ring ( struct natsemi_nic *natsemi, + struct natsemi_ring *ring ) { + size_t len = ( ring->count * sizeof ( ring->desc[0] ) ); + + /* Clear ring address */ + writel ( 0, natsemi->regs + ring->reg ); + if ( natsemi->flags & NATSEMI_64BIT ) + writel ( 0, natsemi->regs + ring->reg + 4 ); + + /* Free descriptor ring */ + free_dma ( ring->desc, len ); + ring->desc = NULL; + ring->prod = 0; + ring->cons = 0; +} + +/** + * Refill receive descriptor ring + * + * @v netdev Network device + */ +static void natsemi_refill_rx ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + union natsemi_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + physaddr_t address; + + while ( ( natsemi->rx.prod - natsemi->rx.cons ) < NATSEMI_NUM_RX_DESC ){ + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( NATSEMI_RX_MAX_LEN ); + if ( ! iobuf ) { + /* Wait for next refill */ + return; + } + + /* Check address is usable by card */ + address = virt_to_bus ( iobuf->data ); + if ( ! natsemi_address_ok ( natsemi, address ) ) { + DBGC ( natsemi, "NATSEMI %p cannot support 64-bit RX " + "buffer address\n", natsemi ); + netdev_rx_err ( netdev, iobuf, -ENOTSUP ); + return; + } + + /* Get next receive descriptor */ + rx_idx = ( natsemi->rx.prod++ % NATSEMI_NUM_RX_DESC ); + rx = &natsemi->rx.desc[rx_idx]; + + /* Populate receive descriptor */ + if ( natsemi->flags & NATSEMI_64BIT ) { + rx->d64.bufptr = cpu_to_le64 ( address ); + } else { + rx->d32pad.d32.bufptr = cpu_to_le32 ( address ); + } + wmb(); + rx->common.cmdsts = cpu_to_le32 ( NATSEMI_DESC_INTR | + NATSEMI_RX_MAX_LEN ); + wmb(); + + /* Record I/O buffer */ + assert ( natsemi->rx_iobuf[rx_idx] == NULL ); + natsemi->rx_iobuf[rx_idx] = iobuf; + + /* Notify card that there are descriptors available */ + writel ( NATSEMI_CR_RXE, natsemi->regs + NATSEMI_CR ); + + DBGC2 ( natsemi, "NATSEMI %p RX %d is [%llx,%llx)\n", natsemi, + rx_idx, ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + NATSEMI_RX_MAX_LEN)); + } +} + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int natsemi_open ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + int rc; + + /* Set MAC address */ + natsemi_pmatch ( natsemi, netdev->ll_addr ); + + /* Create transmit descriptor ring */ + if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->tx ) ) != 0 ) + goto err_create_tx; + + /* Set transmit configuration */ + writel ( ( NATSEMI_TXCFG_CSI | NATSEMI_TXCFG_HBI | NATSEMI_TXCFG_ATP | + NATSEMI_TXCFG_ECRETRY | NATSEMI_TXCFG_MXDMA_DEFAULT | + NATSEMI_TXCFG_FLTH_DEFAULT | NATSEMI_TXCFG_DRTH_DEFAULT ), + ( natsemi->regs + ( ( natsemi->flags & NATSEMI_64BIT ) ? + NATSEMI_TXCFG_64 : NATSEMI_TXCFG_32 ) ) ); + + /* Create receive descriptor ring */ + if ( ( rc = natsemi_create_ring ( natsemi, &natsemi->rx ) ) != 0 ) + goto err_create_rx; + + /* Set receive configuration */ + writel ( ( NATSEMI_RXCFG_ARP | NATSEMI_RXCFG_ATX | NATSEMI_RXCFG_ALP | + NATSEMI_RXCFG_MXDMA_DEFAULT | NATSEMI_RXCFG_DRTH_DEFAULT ), + ( natsemi->regs + ( ( natsemi->flags & NATSEMI_64BIT ) ? + NATSEMI_RXCFG_64 : NATSEMI_RXCFG_32 ) ) ); + + /* Set receive filter configuration */ + writel ( ( NATSEMI_RFCR_RFEN | NATSEMI_RFCR_AAB | NATSEMI_RFCR_AAM | + NATSEMI_RFCR_AAU ), natsemi->regs + NATSEMI_RFCR ); + + /* Fill receive ring */ + natsemi_refill_rx ( netdev ); + + /* Unmask transmit and receive interrupts. (Interrupts will + * not be generated unless enabled via the IER.) + */ + writel ( ( NATSEMI_IRQ_TXDESC | NATSEMI_IRQ_RXDESC ), + natsemi->regs + NATSEMI_IMR ); + + /* Update link state */ + natsemi_check_link ( netdev ); + + return 0; + + natsemi_destroy_ring ( natsemi, &natsemi->rx ); + err_create_rx: + natsemi_destroy_ring ( natsemi, &natsemi->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void natsemi_close ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + unsigned int i; + + /* Mask transmit and receive interrupts */ + writel ( 0, natsemi->regs + NATSEMI_IMR ); + + /* Reset and disable transmitter and receiver */ + writel ( ( NATSEMI_CR_RXR | NATSEMI_CR_TXR ), + natsemi->regs + NATSEMI_CR ); + + /* Discard any unused receive buffers */ + for ( i = 0 ; i < NATSEMI_NUM_RX_DESC ; i++ ) { + if ( natsemi->rx_iobuf[i] ) + free_iob ( natsemi->rx_iobuf[i] ); + natsemi->rx_iobuf[i] = NULL; + } + + /* Destroy receive descriptor ring */ + natsemi_destroy_ring ( natsemi, &natsemi->rx ); + + /* Destroy transmit descriptor ring */ + natsemi_destroy_ring ( natsemi, &natsemi->tx ); +} + +/** + * Transmit packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int natsemi_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct natsemi_nic *natsemi = netdev->priv; + union natsemi_descriptor *tx; + unsigned int tx_idx; + physaddr_t address; + + /* Check address is usable by card */ + address = virt_to_bus ( iobuf->data ); + if ( ! natsemi_address_ok ( natsemi, address ) ) { + DBGC ( natsemi, "NATSEMI %p cannot support 64-bit TX buffer " + "address\n", natsemi ); + return -ENOTSUP; + } + + /* Get next transmit descriptor */ + if ( ( natsemi->tx.prod - natsemi->tx.cons ) >= NATSEMI_NUM_TX_DESC ) { + DBGC ( natsemi, "NATSEMI %p out of transmit descriptors\n", + natsemi ); + return -ENOBUFS; + } + tx_idx = ( natsemi->tx.prod++ % NATSEMI_NUM_TX_DESC ); + tx = &natsemi->tx.desc[tx_idx]; + + /* Populate transmit descriptor */ + if ( natsemi->flags & NATSEMI_64BIT ) { + tx->d64.bufptr = cpu_to_le64 ( address ); + } else { + tx->d32pad.d32.bufptr = cpu_to_le32 ( address ); + } + wmb(); + tx->common.cmdsts = cpu_to_le32 ( NATSEMI_DESC_OWN | NATSEMI_DESC_INTR | + iob_len ( iobuf ) ); + wmb(); + + /* Notify card that there are packets ready to transmit */ + writel ( NATSEMI_CR_TXE, natsemi->regs + NATSEMI_CR ); + + DBGC2 ( natsemi, "NATSEMI %p TX %d is [%llx,%llx)\n", natsemi, tx_idx, + ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + iob_len ( iobuf ) ) ); + + return 0; +} + +/** + * Poll for completed packets + * + * @v netdev Network device + */ +static void natsemi_poll_tx ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + union natsemi_descriptor *tx; + unsigned int tx_idx; + + /* Check for completed packets */ + while ( natsemi->tx.cons != natsemi->tx.prod ) { + + /* Get next transmit descriptor */ + tx_idx = ( natsemi->tx.cons % NATSEMI_NUM_TX_DESC ); + tx = &natsemi->tx.desc[tx_idx]; + + /* Stop if descriptor is still in use */ + if ( tx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OWN ) ) + return; + + /* Complete TX descriptor */ + if ( tx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OK ) ) { + DBGC2 ( natsemi, "NATSEMI %p TX %d complete\n", + natsemi, tx_idx ); + netdev_tx_complete_next ( netdev ); + } else { + DBGC ( natsemi, "NATSEMI %p TX %d completion error " + "(%08x)\n", natsemi, tx_idx, + le32_to_cpu ( tx->common.cmdsts ) ); + netdev_tx_complete_next_err ( netdev, -EIO ); + } + natsemi->tx.cons++; + } +} + +/** + * Poll for received packets + * + * @v netdev Network device + */ +static void natsemi_poll_rx ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + union natsemi_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + size_t len; + + /* Check for received packets */ + while ( natsemi->rx.cons != natsemi->rx.prod ) { + + /* Get next receive descriptor */ + rx_idx = ( natsemi->rx.cons % NATSEMI_NUM_RX_DESC ); + rx = &natsemi->rx.desc[rx_idx]; + + /* Stop if descriptor is still in use */ + if ( ! ( rx->common.cmdsts & NATSEMI_DESC_OWN ) ) + return; + + /* Populate I/O buffer */ + iobuf = natsemi->rx_iobuf[rx_idx]; + natsemi->rx_iobuf[rx_idx] = NULL; + len = ( le32_to_cpu ( rx->common.cmdsts ) & + NATSEMI_DESC_SIZE_MASK ); + iob_put ( iobuf, len - 4 /* strip CRC */ ); + + /* Hand off to network stack */ + if ( rx->common.cmdsts & cpu_to_le32 ( NATSEMI_DESC_OK ) ) { + DBGC2 ( natsemi, "NATSEMI %p RX %d complete (length " + "%zd)\n", natsemi, rx_idx, len ); + netdev_rx ( netdev, iobuf ); + } else { + DBGC ( natsemi, "NATSEMI %p RX %d error (length %zd, " + "status %08x)\n", natsemi, rx_idx, len, + le32_to_cpu ( rx->common.cmdsts ) ); + netdev_rx_err ( netdev, iobuf, -EIO ); + } + natsemi->rx.cons++; + } +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void natsemi_poll ( struct net_device *netdev ) { + struct natsemi_nic *natsemi = netdev->priv; + uint32_t isr; + + /* Poll for link state. The PHY interrupt seems not to + * function as expected, and polling for the link state is + * only a single register read. + */ + natsemi_check_link ( netdev ); + + /* Check for and acknowledge interrupts */ + isr = readl ( natsemi->regs + NATSEMI_ISR ); + if ( ! isr ) + return; + + /* Poll for TX completions, if applicable */ + if ( isr & NATSEMI_IRQ_TXDESC ) + natsemi_poll_tx ( netdev ); + + /* Poll for RX completionsm, if applicable */ + if ( isr & NATSEMI_IRQ_RXDESC ) + natsemi_poll_rx ( netdev ); + + /* Refill RX ring */ + natsemi_refill_rx ( netdev ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void natsemi_irq ( struct net_device *netdev, int enable ) { + struct natsemi_nic *natsemi = netdev->priv; + + /* Enable or disable interrupts */ + writel ( ( enable ? NATSEMI_IER_IE : 0 ), natsemi->regs + NATSEMI_IER ); +} + +/** National Semiconductor network device operations */ +static struct net_device_operations natsemi_operations = { + .open = natsemi_open, + .close = natsemi_close, + .transmit = natsemi_transmit, + .poll = natsemi_poll, + .irq = natsemi_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + /** * Probe PCI device * - * @v pci PCI device - * @v id PCI ID - * @ret rc Return status code + * @v pci PCI device + * @ret rc Return status code */ -static int natsemi_probe (struct pci_device *pci) { +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; + struct natsemi_nic *natsemi; int rc; - /* Allocate net device - */ - netdev = alloc_etherdev (sizeof (*np)); - if (! netdev) - return -ENOMEM; - - 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; + /* 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 ); - if ((rc = register_netdev (netdev)) != 0) + /* 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; - /* Mark as link up; we don't yet handle link state */ - netdev_link_up ( netdev ); + /* Set initial link state */ + natsemi_check_link ( netdev ); return 0; -err_register_netdev: - - natsemi_reset (netdev); - netdev_put (netdev); + unregister_netdev ( netdev ); + err_register_netdev: + err_hwaddr: + natsemi_reset ( natsemi ); + err_reset: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: return rc; } /** * Remove PCI device * - * @v pci PCI device + * @v pci PCI device */ -static void natsemi_remove (struct pci_device *pci) { - struct net_device *netdev = pci_get_drvdata (pci); - - unregister_netdev (netdev); - natsemi_reset (netdev); +static void natsemi_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct natsemi_nic *natsemi = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + natsemi_reset ( natsemi ); + + /* Free network device */ netdev_nullify ( netdev ); - netdev_put (netdev); + netdev_put ( netdev ); } -/** - * Reset NIC - * - * @v NATSEMI NIC - * - * Issues a hardware reset and waits for the reset to complete. - */ -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]; +/** Flags for DP83815 */ +#define DP83815_FLAGS ( NATSEMI_EEPROM_LITTLE_ENDIAN | NATSEMI_EEPROM_INSANE ) - 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); -} - -/** - * Open NIC - * - * @v netdev Net device - * @ret rc Return status code - */ -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); - } - - /* 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; - } - outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr); - - DBG ("Natsemi Tx descriptor loaded with: %#08x\n", - inl (np->ioaddr + TxRingPtr)); - - /* 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); - } - outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr); - - DBG ("Natsemi Rx descriptor loaded with: %#08x\n", - inl (np->ioaddr + RxRingPtr)); - - /* Setup RX Filter - */ - outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys, - np->ioaddr + RxFilterAddr); - - /* Initialize other registers. - * Configure the PCI bus bursts and FIFO thresholds. - * Configure for standard, in-spec Ethernet. - */ - 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; - } - 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)); - - /*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; -} - -/** - * Close NIC - * - * @v netdev Net device - */ -static void natsemi_close (struct net_device *netdev) -{ - struct natsemi_private *np = netdev->priv; - int i; - - natsemi_reset (netdev); - - for (i = 0; i < NUM_RX_DESC ; i++) { - free_iob (np->iobuf[i]); - } -} - -/** - * 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_private *np = netdev->priv; - - if (np->tx[np->tx_cur].cmdsts != 0) { - DBG ("TX overflow\n"); - return -ENOBUFS; - } - - /* Used by netdev_tx_complete () - */ - np->tx_iobuf[np->tx_cur] = iobuf; - - /* 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 - */ - - /* 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; - - DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur, - virt_to_bus (&iobuf->data), iob_len (iobuf)); - - /* increment the circular buffer pointer to the next buffer location - */ - np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE; - - /*start the transmitter - */ - outl (TxOn, np->ioaddr + ChipCmd); - - return 0; -} - -/** - * Poll for received packets - * - * @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); - - if (!intr_status) - goto end; - - DBG ("natsemi_poll: intr_status = %#08x\n", intr_status); - - /* 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); - } else { - netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]); - DBG ("Success transmitting packet\n"); - } - - np->tx[np->tx_dirty].cmdsts = 0; - np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE; - i = (i + 1) % TX_RING_SIZE; - } - - /* 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); - } - 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; - } -end: - /* re-enable the potentially idle receive state machine - */ - outl (RxOn, np->ioaddr + ChipCmd); -} - -/** - * Enable/disable interrupts - * - * @v netdev Network device - * @v enable Non-zero for enable, zero for disable - */ -static void natsemi_irq (struct net_device *netdev, int enable) -{ - struct natsemi_private *np = netdev->priv; - - outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0), - np->ioaddr + IntrMask); - outl ((enable ? 1 : 0), np->ioaddr + IntrEnable); -} +/** 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/src/drivers/net/natsemi.h b/src/drivers/net/natsemi.h index ae827ba3..7e8d6f80 100644 --- a/src/drivers/net/natsemi.h +++ b/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 + * + */ -#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 +FILE_LICENCE ( GPL2_OR_LATER ); -struct natsemi_tx { +#include +#include +#include + +/** BAR size */ +#define NATSEMI_BAR_SIZE 0x100 + +/** A 32-bit packet descriptor */ +struct natsemi_descriptor_32 { + /** Link to next descriptor */ uint32_t link; + /** Command / status */ uint32_t cmdsts; + /** Buffer pointer */ uint32_t bufptr; +} __attribute__ (( packed )); + +/** A 64-bit packet descriptor */ +struct natsemi_descriptor_64 { + /** Link to next descriptor */ + uint64_t link; + /** Buffer pointer */ + uint64_t bufptr; + /** Command / status */ + uint32_t cmdsts; + /** Extended status */ + uint32_t extsts; +} __attribute__ (( packed )); + +/** A packet descriptor + * + * The 32-bit and 64-bit variants are overlaid such that "cmdsts" can + * be accessed as a common field, and the overall size is a power of + * two (to allow the descriptor ring length to be used as an + * alignment). + */ +union natsemi_descriptor { + /** Common fields */ + struct { + /** Reserved */ + uint8_t reserved_a[16]; + /** Command / status */ + uint32_t cmdsts; + /** Reserved */ + uint8_t reserved_b[12]; + } __attribute__ (( packed )) common; + /** 64-bit descriptor */ + struct natsemi_descriptor_64 d64; + /** 32-bit descriptor */ + struct { + /** Reserved */ + uint8_t reserved[12]; + /** Descriptor */ + struct natsemi_descriptor_32 d32; + } __attribute__ (( packed )) d32pad; }; -struct natsemi_rx { - uint32_t link; - uint32_t cmdsts; - uint32_t bufptr; +/** Descriptor buffer size mask */ +#define NATSEMI_DESC_SIZE_MASK 0xfff + +/** Packet descriptor flags */ +enum natsemi_descriptor_flags { + /** Descriptor is owned by NIC */ + NATSEMI_DESC_OWN = 0x80000000UL, + /** Request descriptor interrupt */ + NATSEMI_DESC_INTR = 0x20000000UL, + /** Packet OK */ + NATSEMI_DESC_OK = 0x08000000UL, }; -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]; +/** 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 */ - /* 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]; +/** Maximum time to wait for a reset, in milliseconds */ +#define NATSEMI_RESET_MAX_WAIT_MS 100 - /* 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]; +/** Configuration and Media Status Register */ +#define NATSEMI_CFG 0x0004 +#define NATSEMI_CFG_LNKSTS 0x80000000UL /**< Link status */ +#define NATSEMI_CFG_SPDSTS1 0x40000000UL /**< Speed status bit 1 */ +#define NATSEMI_CFG_MODE_1000 0x00400000UL /**< 1000 Mb/s mode control */ +#define NATSEMI_CFG_PCI64_DET 0x00002000UL /**< PCI 64-bit bus detected */ +#define NATSEMI_CFG_DATA64_EN 0x00001000UL /**< 64-bit data enable */ +#define NATSEMI_CFG_M64ADDR 0x00000800UL /**< 64-bit address enable */ +#define NATSEMI_CFG_EXTSTS_EN 0x00000100UL /**< Extended status enable */ + +/** EEPROM Access Register */ +#define NATSEMI_MEAR 0x0008 +#define NATSEMI_MEAR_EESEL 0x00000008UL /**< EEPROM chip select */ +#define NATSEMI_MEAR_EECLK 0x00000004UL /**< EEPROM serial clock */ +#define NATSEMI_MEAR_EEDO 0x00000002UL /**< EEPROM data out */ +#define NATSEMI_MEAR_EEDI 0x00000001UL /**< EEPROM data in */ + +/** Size of EEPROM (in bytes) */ +#define NATSEMI_EEPROM_SIZE 32 + +/** Word offset of MAC address within sane EEPROM layout */ +#define NATSEMI_EEPROM_MAC_SANE 0x0a + +/** Word offset of MAC address within insane EEPROM layout */ +#define NATSEMI_EEPROM_MAC_INSANE 0x06 + +/** PCI Test Control Register */ +#define NATSEMI_PTSCR 0x000c +#define NATSEMI_PTSCR_EELOAD_EN 0x00000004UL /**< Enable EEPROM load */ + +/** Maximum time to wait for a configuration reload, in milliseconds */ +#define NATSEMI_EELOAD_MAX_WAIT_MS 100 + +/** Interrupt Status Register */ +#define NATSEMI_ISR 0x0010 +#define NATSEMI_IRQ_TXDESC 0x00000080UL /**< TX descriptor */ +#define NATSEMI_IRQ_RXDESC 0x00000002UL /**< RX descriptor */ + +/** Interrupt Mask Register */ +#define NATSEMI_IMR 0x0014 + +/** Interrupt Enable Register */ +#define NATSEMI_IER 0x0018 +#define NATSEMI_IER_IE 0x00000001UL /**< Interrupt enable */ + +/** Transmit Descriptor Pointer */ +#define NATSEMI_TXDP 0x0020 + +/** Transmit Descriptor Pointer High Dword (64-bit) */ +#define NATSEMI_TXDP_HI_64 0x0024 + +/** Number of transmit descriptors */ +#define NATSEMI_NUM_TX_DESC 4 + +/** Transmit configuration register (32-bit) */ +#define NATSEMI_TXCFG_32 0x24 + +/** Transmit configuration register (64-bit) */ +#define NATSEMI_TXCFG_64 0x28 +#define NATSEMI_TXCFG_CSI 0x80000000UL /**< Carrier sense ignore */ +#define NATSEMI_TXCFG_HBI 0x40000000UL /**< Heartbeat ignore */ +#define NATSEMI_TXCFG_ATP 0x10000000UL /**< Automatic padding */ +#define NATSEMI_TXCFG_ECRETRY 0x00800000UL /**< Excess collision retry */ +#define NATSEMI_TXCFG_MXDMA(x) ( (x) << 20 ) /**< Max DMA burst size */ +#define NATSEMI_TXCFG_FLTH(x) ( (x) << 8 ) /**< Fill threshold */ +#define NATSEMI_TXCFG_DRTH(x) ( (x) << 0 ) /**< Drain threshold */ + +/** Max DMA burst size (encoded value) + * + * This represents 256-byte bursts on 83815 controllers and 512-byte + * bursts on 83820 controllers. + */ +#define NATSEMI_TXCFG_MXDMA_DEFAULT NATSEMI_TXCFG_MXDMA ( 0x7 ) + +/** Fill threshold (in units of 32 bytes) + * + * Must be at least as large as the max DMA burst size, so use a value + * of 512 bytes. + */ +#define NATSEMI_TXCFG_FLTH_DEFAULT NATSEMI_TXCFG_FLTH ( 512 / 32 ) + +/** Drain threshold (in units of 32 bytes) + * + * Start transmission once we receive a conservative 1024 bytes, to + * avoid FIFO underrun errors. (83815 does not allow us to specify a + * value of 0 for "wait until whole packet is present".) + * + * Fill threshold plus drain threshold must be less than the transmit + * FIFO size, which is 2kB on 83815 and 8kB on 83820. + */ +#define NATSEMI_TXCFG_DRTH_DEFAULT NATSEMI_TXCFG_DRTH ( 1024 / 32 ) + +/** Receive Descriptor Pointer */ +#define NATSEMI_RXDP 0x0030 + +/** Receive Descriptor Pointer High Dword (64-bit) */ +#define NATSEMI_RXDP_HI_64 0x0034 + +/** Number of receive descriptors */ +#define NATSEMI_NUM_RX_DESC 4 + +/** Receive buffer length */ +#define NATSEMI_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ ) + +/** Receive configuration register (32-bit) */ +#define NATSEMI_RXCFG_32 0x34 + +/** Receive configuration register (64-bit) */ +#define NATSEMI_RXCFG_64 0x38 +#define NATSEMI_RXCFG_ARP 0x40000000UL /**< Accept runt packets */ +#define NATSEMI_RXCFG_ATX 0x10000000UL /**< Accept transmit packets */ +#define NATSEMI_RXCFG_ALP 0x08000000UL /**< Accept long packets */ +#define NATSEMI_RXCFG_MXDMA(x) ( (x) << 20 ) /**< Max DMA burst size */ +#define NATSEMI_RXCFG_DRTH(x) ( (x) << 1 ) /**< Drain threshold */ + +/** Max DMA burst size (encoded value) + * + * This represents 256-byte bursts on 83815 controllers and 512-byte + * bursts on 83820 controllers. + */ +#define NATSEMI_RXCFG_MXDMA_DEFAULT NATSEMI_RXCFG_MXDMA ( 0x7 ) + +/** Drain threshold (in units of 8 bytes) + * + * Start draining after 64 bytes. + * + * Must be large enough to allow packet's accept/reject status to be + * determined before draining begins. + */ +#define NATSEMI_RXCFG_DRTH_DEFAULT NATSEMI_RXCFG_DRTH ( 64 / 8 ) + +/** Receive Filter/Match Control Register */ +#define NATSEMI_RFCR 0x0048 +#define NATSEMI_RFCR_RFEN 0x80000000UL /**< RX filter enable */ +#define NATSEMI_RFCR_AAB 0x40000000UL /**< Accept all broadcast */ +#define NATSEMI_RFCR_AAM 0x20000000UL /**< Accept all multicast */ +#define NATSEMI_RFCR_AAU 0x10000000UL /**< Accept all unicast */ +#define NATSEMI_RFCR_RFADDR( addr ) ( (addr) << 0 ) /**< Extended address */ +#define NATSEMI_RFCR_RFADDR_MASK NATSEMI_RFCR_RFADDR ( 0x3ff ) + +/** Perfect match filter address base */ +#define NATSEMI_RFADDR_PMATCH_BASE 0x000 + +/** Receive Filter/Match Data Register */ +#define NATSEMI_RFDR 0x004c +#define NATSEMI_RFDR_BMASK 0x00030000UL /**< Byte mask */ +#define NATSEMI_RFDR_DATA( value ) ( (value) & 0xffff ) /**< Filter data */ + +/** National Semiconductor network card flags */ +enum natsemi_nic_flags { + /** EEPROM is little-endian */ + NATSEMI_EEPROM_LITTLE_ENDIAN = 0x0001, + /** EEPROM layout is insane */ + NATSEMI_EEPROM_INSANE = 0x0002, + /** Card supports 64-bit operation */ + NATSEMI_64BIT = 0x0004, + /** Card supports 1000Mbps link */ + NATSEMI_1000 = 0x0008, +}; + +/** A National Semiconductor descriptor ring */ +struct natsemi_ring { + /** Descriptors */ + union natsemi_descriptor *desc; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; + + /** Number of descriptors */ + unsigned int count; + /** Descriptor start address register */ + unsigned int reg; +}; + +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Descriptor start address register + */ +static inline __attribute__ (( always_inline)) void +natsemi_init_ring ( struct natsemi_ring *ring, unsigned int count, + unsigned int reg ) { + ring->count = count; + ring->reg = reg; +} + +/** A National Semiconductor network card */ +struct natsemi_nic { + /** Flags */ + unsigned int flags; + /** Registers */ + void *regs; + /** SPI bit-bashing interface */ struct spi_bit_basher spibit; + /** EEPROM */ struct spi_device eeprom; - struct nvo_block nvo; + + /** 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; }; -/* - * 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 +/** + * Check if card can access physical address + * + * @v natsemi National Semiconductor device + * @v address Physical address + * @v address_ok Card can access physical address */ -#define PHYID_AM79C874 0x0022561b +static inline __attribute__ (( always_inline )) int +natsemi_address_ok ( struct natsemi_nic *natsemi, physaddr_t address ) { -enum { - MII_MCTRL = 0x15, /* mode control register */ - MII_FX_SEL = 0x0001, /* 100BASE-FX (fiber) */ - MII_EN_SCRM = 0x0004, /* enable scrambler (tp) */ -}; + /* 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; -/* 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 - -/* 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. - */ -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 - -}; - -/* 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 */ - -/* Bit in ChipCmd. - */ -enum ChipCmdBits { - ChipReset = 0x100, - RxReset = 0x20, - TxReset = 0x10, - RxOff = 0x08, - RxOn = 0x04, - TxOff = 0x02, - TxOn = 0x01 -}; - -enum ChipConfig_bits { - CfgPhyDis = 0x200, - CfgPhyRst = 0x400, - CfgExtPhy = 0x1000, - CfgAnegEnable = 0x2000, - CfgAneg100 = 0x4000, - CfgAnegFull = 0x8000, - CfgAnegDone = 0x8000000, - CfgFullDuplex = 0x20000000, - CfgSpeed100 = 0x40000000, - CfgLink = 0x80000000, -}; - - -/* 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 -}; - -/* Bits in network_desc.status - */ -enum desc_status_bits { - DescOwn = 0x80000000, - DescMore = 0x40000000, - DescIntr = 0x20000000, - DescNoCRC = 0x10000000, - DescPktOK = 0x08000000, - RxTooLong = 0x00400000 -}; - -/*Bits in Interrupt Mask register - */ -enum Intr_mask_register_bits { - RxOk = 0x001, - RxErr = 0x004, - TxOk = 0x040, - TxErr = 0x100 -}; - -enum MIntrCtrl_bits { - MICRIntEn = 0x2, -}; - -/* 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 -}; - -#define EE_Write0 (EE_ChipSelect) -#define EE_Write1 (EE_ChipSelect | EE_DataIn) - -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), -}; - -/* EEPROM access , values are devices specific - */ -#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 */ - -/* 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, -}; + return 0; +} +#endif /* _NATSEMI_H */ diff --git a/src/drivers/net/ns83820.c b/src/drivers/net/ns83820.c deleted file mode 100644 index 0b92a91b..00000000 --- a/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/src/drivers/net/r8169.c b/src/drivers/net/r8169.c deleted file mode 100644 index 13ab65ba..00000000 --- a/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/src/drivers/net/r8169.h b/src/drivers/net/r8169.h deleted file mode 100644 index bcf3df0b..00000000 --- a/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/src/drivers/net/realtek.c b/src/drivers/net/realtek.c new file mode 100644 index 00000000..c906f251 --- /dev/null +++ b/src/drivers/net/realtek.c @@ -0,0 +1,1061 @@ +/* + * 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 | RTL_9346CR_EEM1 ), +}; + +/** + * Read input bit + * + * @v basher Bit-bashing interface + * @v bit_id Bit number + * @ret zero Input is a logic 0 + * @ret non-zero Input is a logic 1 + */ +static int realtek_spi_read_bit ( struct bit_basher *basher, + unsigned int bit_id ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + uint8_t mask = realtek_eeprom_bits[bit_id]; + uint8_t reg; + + DBG_DISABLE ( DBGLVL_IO ); + reg = readb ( rtl->regs + RTL_9346CR ); + DBG_ENABLE ( DBGLVL_IO ); + return ( reg & mask ); +} + +/** + * Set/clear output bit + * + * @v basher Bit-bashing interface + * @v bit_id Bit number + * @v data Value to write + */ +static void realtek_spi_write_bit ( struct bit_basher *basher, + unsigned int bit_id, unsigned long data ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + uint8_t mask = realtek_eeprom_bits[bit_id]; + uint8_t reg; + + DBG_DISABLE ( DBGLVL_IO ); + reg = readb ( rtl->regs + RTL_9346CR ); + reg &= ~mask; + reg |= ( data & mask ); + writeb ( reg, rtl->regs + RTL_9346CR ); + DBG_ENABLE ( DBGLVL_IO ); +} + +/** SPI bit-bashing interface */ +static struct bit_basher_operations realtek_basher_ops = { + .read = realtek_spi_read_bit, + .write = realtek_spi_write_bit, +}; + +/** + * Initialise EEPROM + * + * @v netdev Network device + */ +static void realtek_init_eeprom ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + + /* Initialise SPI bit-bashing interface */ + rtl->spibit.basher.op = &realtek_basher_ops; + rtl->spibit.bus.mode = SPI_MODE_THREEWIRE; + init_spi_bit_basher ( &rtl->spibit ); + + /* Detect EEPROM type and initialise three-wire device */ + if ( readl ( rtl->regs + RTL_RCR ) & RTL_RCR_9356SEL ) { + DBGC ( rtl, "REALTEK %p EEPROM is a 93C56\n", rtl ); + init_at93c56 ( &rtl->eeprom, 16 ); + } else { + DBGC ( rtl, "REALTEK %p EEPROM is a 93C46\n", rtl ); + init_at93c46 ( &rtl->eeprom, 16 ); + } + rtl->eeprom.bus = &rtl->spibit.bus; + + /* Initialise space for non-volatile options, if available + * + * We use offset 0x40 (i.e. address 0x20), length 0x40. This + * block is marked as VPD in the Realtek datasheets, so we use + * it only if we detect that the card is not supporting VPD. + */ + if ( readb ( rtl->regs + RTL_CONFIG1 ) & RTL_CONFIG1_VPD ) { + DBGC ( rtl, "REALTEK %p EEPROM in use for VPD; cannot use " + "for options\n", rtl ); + } else { + nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, RTL_EEPROM_VPD, + RTL_EEPROM_VPD_LEN, NULL, &netdev->refcnt ); + } +} + +/****************************************************************************** + * + * MII interface + * + ****************************************************************************** + */ + +/** + * Read from MII register + * + * @v mii MII interface + * @v reg Register address + * @ret value Data read, or negative error + */ +static int realtek_mii_read ( struct mii_interface *mii, unsigned int reg ) { + struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii ); + unsigned int i; + uint32_t value; + + /* Fail if PHYAR register is not present */ + if ( ! rtl->have_phy_regs ) + return -ENOTSUP; + + /* Initiate read */ + writel ( RTL_PHYAR_VALUE ( 0, reg, 0 ), rtl->regs + RTL_PHYAR ); + + /* Wait for read to complete */ + for ( i = 0 ; i < RTL_MII_MAX_WAIT_US ; i++ ) { + + /* If read is not complete, delay 1us and retry */ + value = readl ( rtl->regs + RTL_PHYAR ); + if ( ! ( value & RTL_PHYAR_FLAG ) ) { + udelay ( 1 ); + continue; + } + + /* Return register value */ + return ( RTL_PHYAR_DATA ( value ) ); + } + + DBGC ( rtl, "REALTEK %p timed out waiting for MII read\n", rtl ); + return -ETIMEDOUT; +} + +/** + * Write to MII register + * + * @v mii MII interface + * @v reg Register address + * @v data Data to write + * @ret rc Return status code + */ +static int realtek_mii_write ( struct mii_interface *mii, unsigned int reg, + unsigned int data) { + struct realtek_nic *rtl = container_of ( mii, struct realtek_nic, mii ); + unsigned int i; + + /* Fail if PHYAR register is not present */ + if ( ! rtl->have_phy_regs ) + return -ENOTSUP; + + /* Initiate write */ + writel ( RTL_PHYAR_VALUE ( RTL_PHYAR_FLAG, reg, data ), + rtl->regs + RTL_PHYAR ); + + /* Wait for write to complete */ + for ( i = 0 ; i < RTL_MII_MAX_WAIT_US ; i++ ) { + + /* If write is not complete, delay 1us and retry */ + if ( readl ( rtl->regs + RTL_PHYAR ) & RTL_PHYAR_FLAG ) { + udelay ( 1 ); + continue; + } + + return 0; + } + + DBGC ( rtl, "REALTEK %p timed out waiting for MII write\n", rtl ); + return -ETIMEDOUT; +} + +/** Realtek MII operations */ +static struct mii_operations realtek_mii_operations = { + .read = realtek_mii_read, + .write = realtek_mii_write, +}; + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reset hardware + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_reset ( struct realtek_nic *rtl ) { + unsigned int i; + + /* Issue reset */ + writeb ( RTL_CR_RST, rtl->regs + RTL_CR ); + + /* Wait for reset to complete */ + for ( i = 0 ; i < RTL_RESET_MAX_WAIT_MS ; i++ ) { + + /* If reset is not complete, delay 1ms and retry */ + if ( readb ( rtl->regs + RTL_CR ) & RTL_CR_RST ) { + mdelay ( 1 ); + continue; + } + + return 0; + } + + DBGC ( rtl, "REALTEK %p timed out waiting for reset\n", rtl ); + return -ETIMEDOUT; +} + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Check link state + * + * @v netdev Network device + */ +static void realtek_check_link ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + uint8_t phystatus; + uint8_t msr; + int link_up; + + /* Determine link state */ + if ( rtl->have_phy_regs ) { + phystatus = readb ( rtl->regs + RTL_PHYSTATUS ); + link_up = ( phystatus & RTL_PHYSTATUS_LINKSTS ); + DBGC ( rtl, "REALTEK %p PHY status is %02x\n", rtl, phystatus ); + } else { + msr = readb ( rtl->regs + RTL_MSR ); + link_up = ( ! ( msr & RTL_MSR_LINKB ) ); + DBGC ( rtl, "REALTEK %p media status is %02x\n", rtl, msr ); + } + + /* Report link state */ + if ( link_up ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Create receive buffer (legacy mode) + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_create_buffer ( struct realtek_nic *rtl ) { + size_t len = ( RTL_RXBUF_LEN + RTL_RXBUF_PAD ); + physaddr_t address; + int rc; + + /* Do nothing unless in legacy mode */ + if ( ! rtl->legacy ) + return 0; + + /* Allocate buffer */ + rtl->rx_buffer = malloc_dma ( len, RTL_RXBUF_ALIGN ); + if ( ! rtl->rx_buffer ) { + rc = -ENOMEM; + goto err_alloc; + } + address = virt_to_bus ( rtl->rx_buffer ); + + /* Check that card can support address */ + if ( address & ~0xffffffffULL ) { + DBGC ( rtl, "REALTEK %p cannot support 64-bit RX buffer " + "address\n", rtl ); + rc = -ENOTSUP; + goto err_64bit; + } + + /* Program buffer address */ + writel ( address, rtl->regs + RTL_RBSTART ); + DBGC ( rtl, "REALTEK %p receive buffer is at [%08llx,%08llx,%08llx)\n", + rtl, ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + RTL_RXBUF_LEN ), + ( ( unsigned long long ) address + len ) ); + + return 0; + + err_64bit: + free_dma ( rtl->rx_buffer, len ); + rtl->rx_buffer = NULL; + err_alloc: + return rc; +} + +/** + * Destroy receive buffer (legacy mode) + * + * @v rtl Realtek device + */ +static void realtek_destroy_buffer ( struct realtek_nic *rtl ) { + size_t len = ( RTL_RXBUF_LEN + RTL_RXBUF_PAD ); + + /* Do nothing unless in legacy mode */ + if ( ! rtl->legacy ) + return; + + /* Clear buffer address */ + writel ( 0, rtl->regs + RTL_RBSTART ); + + /* Free buffer */ + free_dma ( rtl->rx_buffer, len ); + rtl->rx_buffer = NULL; + rtl->rx_offset = 0; +} + +/** + * Create descriptor ring + * + * @v rtl Realtek device + * @v ring Descriptor ring + * @ret rc Return status code + */ +static int realtek_create_ring ( struct realtek_nic *rtl, + struct realtek_ring *ring ) { + physaddr_t address; + + /* Do nothing in legacy mode */ + if ( rtl->legacy ) + return 0; + + /* Allocate descriptor ring */ + ring->desc = malloc_dma ( ring->len, RTL_RING_ALIGN ); + if ( ! ring->desc ) + return -ENOMEM; + + /* Initialise descriptor ring */ + memset ( ring->desc, 0, ring->len ); + + /* Program ring address */ + address = virt_to_bus ( ring->desc ); + writel ( ( address & 0xffffffffUL ), rtl->regs + ring->reg ); + if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { + writel ( ( ( ( uint64_t ) address ) >> 32 ), + rtl->regs + ring->reg + 4 ); + } + DBGC ( rtl, "REALTEK %p ring %02x is at [%08llx,%08llx)\n", + rtl, ring->reg, ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + ring->len ) ); + + return 0; +} + +/** + * Destroy descriptor ring + * + * @v rtl Realtek device + * @v ring Descriptor ring + */ +static void realtek_destroy_ring ( struct realtek_nic *rtl, + struct realtek_ring *ring ) { + + /* Do nothing in legacy mode */ + if ( rtl->legacy ) + return; + + /* Clear ring address */ + writel ( 0, rtl->regs + ring->reg ); + writel ( 0, rtl->regs + ring->reg + 4 ); + + /* Free descriptor ring */ + free_dma ( ring->desc, ring->len ); + ring->desc = NULL; + ring->prod = 0; + ring->cons = 0; +} + +/** + * Refill receive descriptor ring + * + * @v rtl Realtek device + */ +static void realtek_refill_rx ( struct realtek_nic *rtl ) { + struct realtek_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + physaddr_t address; + int is_last; + + /* Do nothing in legacy mode */ + if ( rtl->legacy ) + return; + + while ( ( rtl->rx.prod - rtl->rx.cons ) < RTL_NUM_RX_DESC ) { + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( RTL_RX_MAX_LEN ); + if ( ! iobuf ) { + /* Wait for next refill */ + return; + } + + /* Get next receive descriptor */ + rx_idx = ( rtl->rx.prod++ % RTL_NUM_RX_DESC ); + is_last = ( rx_idx == ( RTL_NUM_RX_DESC - 1 ) ); + rx = &rtl->rx.desc[rx_idx]; + + /* Populate receive descriptor */ + address = virt_to_bus ( iobuf->data ); + rx->address = cpu_to_le64 ( address ); + rx->length = RTL_RX_MAX_LEN; + wmb(); + rx->flags = ( cpu_to_le16 ( RTL_DESC_OWN ) | + ( is_last ? cpu_to_le16 ( RTL_DESC_EOR ) : 0 ) ); + wmb(); + + /* Record I/O buffer */ + assert ( rtl->rx_iobuf[rx_idx] == NULL ); + rtl->rx_iobuf[rx_idx] = iobuf; + + DBGC2 ( rtl, "REALTEK %p RX %d is [%llx,%llx)\n", rtl, rx_idx, + ( ( unsigned long long ) address ), + ( ( unsigned long long ) address + RTL_RX_MAX_LEN ) ); + } +} + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int realtek_open ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + uint32_t rcr; + int rc; + + /* Create transmit descriptor ring */ + if ( ( rc = realtek_create_ring ( rtl, &rtl->tx ) ) != 0 ) + goto err_create_tx; + + /* Create receive descriptor ring */ + if ( ( rc = realtek_create_ring ( rtl, &rtl->rx ) ) != 0 ) + goto err_create_rx; + + /* Create receive buffer */ + if ( ( rc = realtek_create_buffer ( rtl ) ) != 0 ) + goto err_create_buffer; + + /* Accept all packets */ + writel ( 0xffffffffUL, rtl->regs + RTL_MAR0 ); + writel ( 0xffffffffUL, rtl->regs + RTL_MAR4 ); + + /* Enable transmitter and receiver. RTL8139 requires that + * this happens before writing to RCR. + */ + writeb ( ( RTL_CR_TE | RTL_CR_RE ), rtl->regs + RTL_CR ); + + /* Configure receiver */ + rcr = readl ( rtl->regs + RTL_RCR ); + rcr &= ~( RTL_RCR_RBLEN_MASK ); + rcr |= ( RTL_RCR_RBLEN_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB | + RTL_RCR_AM | RTL_RCR_APM | RTL_RCR_AAP ); + writel ( rcr, rtl->regs + RTL_RCR ); + + /* Fill receive ring */ + realtek_refill_rx ( rtl ); + + /* Update link state */ + realtek_check_link ( netdev ); + + return 0; + + realtek_destroy_buffer ( rtl ); + err_create_buffer: + realtek_destroy_ring ( rtl, &rtl->rx ); + err_create_rx: + realtek_destroy_ring ( rtl, &rtl->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void realtek_close ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + unsigned int i; + + /* Disable receiver and transmitter */ + writeb ( 0, rtl->regs + RTL_CR ); + + /* Destroy receive buffer */ + realtek_destroy_buffer ( rtl ); + + /* Destroy receive descriptor ring */ + realtek_destroy_ring ( rtl, &rtl->rx ); + + /* Discard any unused receive buffers */ + for ( i = 0 ; i < RTL_NUM_RX_DESC ; i++ ) { + if ( rtl->rx_iobuf[i] ) + free_iob ( rtl->rx_iobuf[i] ); + rtl->rx_iobuf[i] = NULL; + } + + /* Destroy transmit descriptor ring */ + realtek_destroy_ring ( rtl, &rtl->tx ); +} + +/** + * Transmit packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * @ret rc Return status code + */ +static int realtek_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct realtek_nic *rtl = netdev->priv; + struct realtek_descriptor *tx; + unsigned int tx_idx; + physaddr_t address; + int is_last; + + /* Get next transmit descriptor */ + if ( ( rtl->tx.prod - rtl->tx.cons ) >= RTL_NUM_TX_DESC ) { + DBGC ( rtl, "REALTEK %p out of transmit descriptors\n", rtl ); + return -ENOBUFS; + } + tx_idx = ( rtl->tx.prod++ % RTL_NUM_TX_DESC ); + + /* Transmit packet */ + if ( rtl->legacy ) { + + /* Pad and align packet */ + iob_pad ( iobuf, ETH_ZLEN ); + address = virt_to_bus ( iobuf->data ); + + /* Check that card can support address */ + if ( address & ~0xffffffffULL ) { + DBGC ( rtl, "REALTEK %p cannot support 64-bit TX " + "buffer address\n", rtl ); + return -ENOTSUP; + } + + /* Add to transmit ring */ + writel ( address, rtl->regs + RTL_TSAD ( tx_idx ) ); + writel ( ( RTL_TSD_ERTXTH_DEFAULT | iob_len ( iobuf ) ), + rtl->regs + RTL_TSD ( tx_idx ) ); + + } else { + + /* Populate transmit descriptor */ + address = virt_to_bus ( iobuf->data ); + is_last = ( tx_idx == ( RTL_NUM_TX_DESC - 1 ) ); + tx = &rtl->tx.desc[tx_idx]; + tx->address = cpu_to_le64 ( address ); + tx->length = cpu_to_le16 ( iob_len ( iobuf ) ); + wmb(); + tx->flags = ( cpu_to_le16 ( RTL_DESC_OWN | RTL_DESC_FS | + RTL_DESC_LS ) | + ( is_last ? cpu_to_le16 ( RTL_DESC_EOR ) : 0 ) ); + wmb(); + + /* Notify card that there are packets ready to transmit */ + writeb ( RTL_TPPOLL_NPQ, rtl->regs + rtl->tppoll ); + } + + DBGC2 ( rtl, "REALTEK %p TX %d is [%llx,%llx)\n", rtl, tx_idx, + ( ( unsigned long long ) virt_to_bus ( iobuf->data ) ), + ( ( ( unsigned long long ) virt_to_bus ( iobuf->data ) ) + + iob_len ( iobuf ) ) ); + + return 0; +} + +/** + * Poll for completed packets + * + * @v netdev Network device + */ +static void realtek_poll_tx ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + struct realtek_descriptor *tx; + unsigned int tx_idx; + + /* Check for completed packets */ + while ( rtl->tx.cons != rtl->tx.prod ) { + + /* Get next transmit descriptor */ + tx_idx = ( rtl->tx.cons % RTL_NUM_TX_DESC ); + + /* Stop if descriptor is still in use */ + if ( rtl->legacy ) { + + /* Check ownership bit in transmit status register */ + if ( ! ( readl ( rtl->regs + RTL_TSD ( tx_idx ) ) & + RTL_TSD_OWN ) ) + return; + + } else { + + /* Check ownership bit in descriptor */ + tx = &rtl->tx.desc[tx_idx]; + if ( tx->flags & cpu_to_le16 ( RTL_DESC_OWN ) ) + return; + } + + DBGC2 ( rtl, "REALTEK %p TX %d complete\n", rtl, tx_idx ); + + /* Complete TX descriptor */ + netdev_tx_complete_next ( netdev ); + rtl->tx.cons++; + } +} + +/** + * Poll for received packets (legacy mode) + * + * @v netdev Network device + */ +static void realtek_legacy_poll_rx ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + struct realtek_legacy_header *rx; + struct io_buffer *iobuf; + size_t len; + + /* Check for received packets */ + while ( ! ( readb ( rtl->regs + RTL_CR ) & RTL_CR_BUFE ) ) { + + /* Extract packet from receive buffer */ + rx = ( rtl->rx_buffer + rtl->rx_offset ); + len = le16_to_cpu ( rx->length ); + if ( rx->status & cpu_to_le16 ( RTL_STAT_ROK ) ) { + + DBGC2 ( rtl, "REALTEK %p RX offset %x+%zx\n", + rtl, rtl->rx_offset, len ); + + /* Allocate I/O buffer */ + iobuf = alloc_iob ( len ); + if ( ! iobuf ) { + netdev_rx_err ( netdev, NULL, -ENOMEM ); + /* Leave packet for next poll */ + break; + } + + /* Copy data to I/O buffer */ + memcpy ( iob_put ( iobuf, len ), rx->data, len ); + iob_unput ( iobuf, 4 /* strip CRC */ ); + + /* Hand off to network stack */ + netdev_rx ( netdev, iobuf ); + + } else { + + DBGC ( rtl, "REALTEK %p RX offset %x+%zx error %04x\n", + rtl, rtl->rx_offset, len, + le16_to_cpu ( rx->status ) ); + netdev_rx_err ( netdev, NULL, -EIO ); + } + + /* Update buffer offset */ + rtl->rx_offset = ( rtl->rx_offset + sizeof ( *rx ) + len ); + rtl->rx_offset = ( ( rtl->rx_offset + 3 ) & ~3 ); + rtl->rx_offset = ( rtl->rx_offset % RTL_RXBUF_LEN ); + writew ( ( rtl->rx_offset - 16 ), rtl->regs + RTL_CAPR ); + } +} + +/** + * Poll for received packets + * + * @v netdev Network device + */ +static void realtek_poll_rx ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + struct realtek_descriptor *rx; + struct io_buffer *iobuf; + unsigned int rx_idx; + size_t len; + + /* Poll receive buffer if in legacy mode */ + if ( rtl->legacy ) { + realtek_legacy_poll_rx ( netdev ); + return; + } + + /* Check for received packets */ + while ( rtl->rx.cons != rtl->rx.prod ) { + + /* Get next receive descriptor */ + rx_idx = ( rtl->rx.cons % RTL_NUM_RX_DESC ); + rx = &rtl->rx.desc[rx_idx]; + + /* Stop if descriptor is still in use */ + if ( rx->flags & cpu_to_le16 ( RTL_DESC_OWN ) ) + return; + + /* Populate I/O buffer */ + iobuf = rtl->rx_iobuf[rx_idx]; + rtl->rx_iobuf[rx_idx] = NULL; + len = ( le16_to_cpu ( rx->length ) & RTL_DESC_SIZE_MASK ); + iob_put ( iobuf, ( len - 4 /* strip CRC */ ) ); + + DBGC2 ( rtl, "REALTEK %p RX %d complete (length %zd)\n", + rtl, rx_idx, len ); + + /* Hand off to network stack */ + if ( rx->flags & cpu_to_le16 ( RTL_DESC_RES ) ) { + netdev_rx_err ( netdev, iobuf, -EIO ); + } else { + netdev_rx ( netdev, iobuf ); + } + rtl->rx.cons++; + } +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void realtek_poll ( struct net_device *netdev ) { + struct realtek_nic *rtl = netdev->priv; + uint16_t isr; + + /* Check for and acknowledge interrupts */ + isr = readw ( rtl->regs + RTL_ISR ); + if ( ! isr ) + return; + writew ( isr, rtl->regs + RTL_ISR ); + + /* Poll for TX completions, if applicable */ + if ( isr & ( RTL_IRQ_TER | RTL_IRQ_TOK ) ) + realtek_poll_tx ( netdev ); + + /* Poll for RX completionsm, if applicable */ + if ( isr & ( RTL_IRQ_RER | RTL_IRQ_ROK ) ) + realtek_poll_rx ( netdev ); + + /* Check link state, if applicable */ + if ( isr & RTL_IRQ_PUN_LINKCHG ) + realtek_check_link ( netdev ); + + /* Refill RX ring */ + realtek_refill_rx ( rtl ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void realtek_irq ( struct net_device *netdev, int enable ) { + struct realtek_nic *rtl = netdev->priv; + uint16_t imr; + + /* Set interrupt mask */ + imr = ( enable ? ( RTL_IRQ_PUN_LINKCHG | RTL_IRQ_TER | RTL_IRQ_TOK | + RTL_IRQ_RER | RTL_IRQ_ROK ) : 0 ); + writew ( imr, rtl->regs + RTL_IMR ); +} + +/** Realtek network device operations */ +static struct net_device_operations realtek_operations = { + .open = realtek_open, + .close = realtek_close, + .transmit = realtek_transmit, + .poll = realtek_poll, + .irq = realtek_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Detect device type + * + * @v rtl Realtek device + */ +static void realtek_detect ( struct realtek_nic *rtl ) { + uint16_t rms; + uint16_t check_rms; + uint16_t cpcr; + uint16_t check_cpcr; + + /* The RX Packet Maximum Size register is present only on + * 8169. Try to set to our intended MTU. + */ + rms = RTL_RX_MAX_LEN; + writew ( rms, rtl->regs + RTL_RMS ); + check_rms = readw ( rtl->regs + RTL_RMS ); + + /* The C+ Command register is present only on 8169 and 8139C+. + * Try to enable C+ mode and PCI Dual Address Cycle (for + * 64-bit systems), if supported. + */ + cpcr = ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX | + RTL_CPCR_CPTX ); + writew ( cpcr, rtl->regs + RTL_CPCR ); + check_cpcr = readw ( rtl->regs + RTL_CPCR ); + + /* Detect device type */ + if ( check_rms == rms ) { + DBGC ( rtl, "REALTEK %p appears to be an RTL8169\n", rtl ); + rtl->have_phy_regs = 1; + rtl->tppoll = RTL_TPPOLL_8169; + } else { + if ( check_cpcr == cpcr ) { + DBGC ( rtl, "REALTEK %p appears to be an RTL8139C+\n", + rtl ); + rtl->tppoll = RTL_TPPOLL_8139CP; + } else { + DBGC ( rtl, "REALTEK %p appears to be an RTL8139\n", + rtl ); + rtl->legacy = 1; + } + } +} + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int realtek_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct realtek_nic *rtl; + unsigned int i; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *rtl ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &realtek_operations ); + rtl = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + memset ( rtl, 0, sizeof ( *rtl ) ); + realtek_init_ring ( &rtl->tx, RTL_NUM_TX_DESC, RTL_TNPDS ); + realtek_init_ring ( &rtl->rx, RTL_NUM_RX_DESC, RTL_RDSAR ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + rtl->regs = ioremap ( pci->membase, RTL_BAR_SIZE ); + + /* Reset the NIC */ + if ( ( rc = realtek_reset ( rtl ) ) != 0 ) + goto err_reset; + + /* Detect device type */ + realtek_detect ( rtl ); + + /* Initialise EEPROM */ + realtek_init_eeprom ( netdev ); + + /* Read MAC address from EEPROM */ + if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC, + netdev->hw_addr, ETH_ALEN ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not read MAC address: %s\n", + rtl, strerror ( rc ) ); + goto err_nvs_read; + } + + /* The EEPROM may not be present for onboard NICs. Fall back + * to reading the current ID register value, which will + * hopefully have been programmed by the platform firmware. + */ + if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { + DBGC ( rtl, "REALTEK %p seems to have no EEPROM\n", rtl ); + for ( i = 0 ; i < ETH_ALEN ; i++ ) + netdev->hw_addr[i] = readb ( rtl->regs + RTL_IDR0 + i ); + } + + /* Initialise and reset MII interface */ + mii_init ( &rtl->mii, &realtek_mii_operations ); + if ( rtl->have_phy_regs && + ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) ) { + DBGC ( rtl, "REALTEK %p could not reset MII: %s\n", + rtl, strerror ( rc ) ); + goto err_mii_reset; + } + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + /* Set initial link state */ + realtek_check_link ( netdev ); + + /* Register non-volatile options, if applicable */ + if ( rtl->nvo.nvs ) { + if ( ( rc = register_nvo ( &rtl->nvo, + netdev_settings ( netdev ) ) ) != 0) + goto err_register_nvo; + } + + return 0; + + err_register_nvo: + unregister_netdev ( netdev ); + err_register_netdev: + err_mii_reset: + err_nvs_read: + realtek_reset ( rtl ); + err_reset: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void realtek_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct realtek_nic *rtl = netdev->priv; + + /* Unregister non-volatile options, if applicable */ + if ( rtl->nvo.nvs ) + unregister_nvo ( &rtl->nvo ); + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + realtek_reset ( rtl ); + + /* Free network device */ + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** Realtek PCI device IDs */ +static struct pci_device_id realtek_nics[] = { + PCI_ROM ( 0x0001, 0x8168, "clone8169", "Cloned 8169", 0 ), + PCI_ROM ( 0x018a, 0x0106, "fpc0106tx", "LevelOne FPC-0106TX", 0 ), + PCI_ROM ( 0x021b, 0x8139, "hne300", "Compaq HNE-300", 0 ), + PCI_ROM ( 0x02ac, 0x1012, "s1012", "SpeedStream 1012", 0 ), + PCI_ROM ( 0x0357, 0x000a, "ttpmon", "TTTech TTP-Monitoring", 0 ), + PCI_ROM ( 0x10ec, 0x8129, "rtl8129", "RTL-8129", 0 ), + PCI_ROM ( 0x10ec, 0x8136, "rtl8136", "RTL8101E/RTL8102E", 0 ), + PCI_ROM ( 0x10ec, 0x8138, "rtl8138", "RT8139 (B/C)", 0 ), + PCI_ROM ( 0x10ec, 0x8139, "rtl8139", "RTL-8139/8139C/8139C+", 0 ), + PCI_ROM ( 0x10ec, 0x8167, "rtl8167", "RTL-8110SC/8169SC", 0 ), + PCI_ROM ( 0x10ec, 0x8168, "rtl8168", "RTL8111/8168B", 0 ), + PCI_ROM ( 0x10ec, 0x8169, "rtl8169", "RTL-8169", 0 ), + PCI_ROM ( 0x1113, 0x1211, "smc1211", "SMC2-1211TX", 0 ), + PCI_ROM ( 0x1186, 0x1300, "dfe538", "DFE530TX+/DFE538TX", 0 ), + PCI_ROM ( 0x1186, 0x1340, "dfe690", "DFE-690TXD", 0 ), + PCI_ROM ( 0x1186, 0x4300, "dge528t", "DGE-528T", 0 ), + PCI_ROM ( 0x11db, 0x1234, "sega8139", "Sega Enterprises 8139", 0 ), + PCI_ROM ( 0x1259, 0xa117, "allied8139", "Allied Telesyn 8139", 0 ), + PCI_ROM ( 0x1259, 0xa11e, "allied81xx", "Allied Telesyn 81xx", 0 ), + PCI_ROM ( 0x1259, 0xc107, "allied8169", "Allied Telesyn 8169", 0 ), + PCI_ROM ( 0x126c, 0x1211, "northen8139","Northern Telecom 8139", 0 ), + PCI_ROM ( 0x13d1, 0xab06, "fe2000vx", "Abocom FE2000VX", 0 ), + PCI_ROM ( 0x1432, 0x9130, "edi8139", "Edimax 8139", 0 ), + PCI_ROM ( 0x14ea, 0xab06, "fnw3603tx", "Planex FNW-3603-TX", 0 ), + PCI_ROM ( 0x14ea, 0xab07, "fnw3800tx", "Planex FNW-3800-TX", 0 ), + PCI_ROM ( 0x1500, 0x1360, "delta8139", "Delta Electronics 8139", 0 ), + PCI_ROM ( 0x16ec, 0x0116, "usr997902", "USR997902", 0 ), + PCI_ROM ( 0x1737, 0x1032, "linksys8169","Linksys 8169", 0 ), + PCI_ROM ( 0x1743, 0x8139, "rolf100", "Peppercorn ROL/F-100", 0 ), + PCI_ROM ( 0x4033, 0x1360, "addron8139", "Addtron 8139", 0 ), + PCI_ROM ( 0xffff, 0x8139, "clonse8139", "Cloned 8139", 0 ), +}; + +/** Realtek PCI driver */ +struct pci_driver realtek_driver __pci_driver = { + .ids = realtek_nics, + .id_count = ( sizeof ( realtek_nics ) / sizeof ( realtek_nics[0] ) ), + .probe = realtek_probe, + .remove = realtek_remove, +}; diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h new file mode 100644 index 00000000..1c6bc544 --- /dev/null +++ b/src/drivers/net/realtek.h @@ -0,0 +1,273 @@ +#ifndef _REALTEK_H +#define _REALTEK_H + +/** @file + * + * Realtek 10/100/1000 network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#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 + +/** Receive (Rx) Configuration Register (dword) */ +#define RTL_RCR 0x44 +#define RTL_RCR_RBLEN(x) ( (x) << 11 ) /**< Receive buffer length */ +#define RTL_RCR_RBLEN_MASK RTL_RCR_RBLEN ( 0x3 ) +#define RTL_RCR_RBLEN_DEFAULT RTL_RCR_RBLEN ( 0 /* 8kB */ ) +#define RTL_RCR_WRAP 0x00000080UL /**< Overrun receive buffer */ +#define RTL_RCR_9356SEL 0x00000040UL /**< EEPROM is a 93C56 */ +#define RTL_RCR_AB 0x00000008UL /**< Accept broadcast packets */ +#define RTL_RCR_AM 0x00000004UL /**< Accept multicast packets */ +#define RTL_RCR_APM 0x00000002UL /**< Accept physical match */ +#define RTL_RCR_AAP 0x00000001UL /**< Accept all packets */ + +/** 93C46 (93C56) Command Register (byte) */ +#define RTL_9346CR 0x50 +#define RTL_9346CR_EEM1 0x80 /**< Mode select bit 1 */ +#define RTL_9346CR_EEM0 0x40 /**< Mode select bit 0 */ +#define RTL_9346CR_EECS 0x08 /**< Chip select */ +#define RTL_9346CR_EESK 0x04 /**< Clock */ +#define RTL_9346CR_EEDI 0x02 /**< Data in */ +#define RTL_9346CR_EEDO 0x01 /**< Data out */ + +/** Word offset of MAC address within EEPROM */ +#define RTL_EEPROM_MAC ( 0x0e / 2 ) + +/** Word offset of VPD / non-volatile options within EEPROM */ +#define RTL_EEPROM_VPD ( 0x40 / 2 ) + +/** Length of VPD / non-volatile options within EEPROM */ +#define RTL_EEPROM_VPD_LEN 0x40 + +/** Configuration Register 1 (byte) */ +#define RTL_CONFIG1 0x52 +#define RTL_CONFIG1_VPD 0x02 /**< Vital Product Data enabled */ + +/** Media Status Register (byte, 8139 only) */ +#define RTL_MSR 0x58 +#define RTL_MSR_LINKB 0x04 /**< Inverse of link status */ + +/** PHY Access Register (dword, 8169 only) */ +#define RTL_PHYAR 0x60 +#define RTL_PHYAR_FLAG 0x80000000UL /**< Read/write flag */ + +/** Construct PHY Access Register value */ +#define RTL_PHYAR_VALUE( flag, reg, data ) ( (flag) | ( (reg) << 16 ) | (data) ) + +/** Extract PHY Access Register data */ +#define RTL_PHYAR_DATA( value ) ( (value) & 0xffff ) + +/** Maximum time to wait for PHY access, in microseconds */ +#define RTL_MII_MAX_WAIT_US 500 + +/** PHY (GMII, MII, or TBI) Status Register (byte, 8169 only) */ +#define RTL_PHYSTATUS 0x6c +#define RTL_PHYSTATUS_LINKSTS 0x02 /**< Link ok */ + +/** Transmit Priority Polling Register (byte, 8139C+ only) */ +#define RTL_TPPOLL_8139CP 0xd9 + +/** RX Packet Maximum Size Register (word) */ +#define RTL_RMS 0xda + +/** C+ Command Register (word) */ +#define RTL_CPCR 0xe0 +#define RTL_CPCR_DAC 0x0010 /**< PCI Dual Address Cycle Enable */ +#define RTL_CPCR_MULRW 0x0008 /**< PCI Multiple Read/Write Enable */ +#define RTL_CPCR_CPRX 0x0002 /**< C+ receive enable */ +#define RTL_CPCR_CPTX 0x0001 /**< C+ transmit enable */ + +/** Receive Descriptor Start Address Register (qword) */ +#define RTL_RDSAR 0xe4 + +/** Number of receive descriptors */ +#define RTL_NUM_RX_DESC 4 + +/** Receive buffer length */ +#define RTL_RX_MAX_LEN ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ ) + +/** A Realtek descriptor ring */ +struct realtek_ring { + /** Descriptors */ + struct realtek_descriptor *desc; + /** Producer index */ + unsigned int prod; + /** Consumer index */ + unsigned int cons; + + /** Descriptor start address register */ + unsigned int reg; + /** Length (in bytes) */ + size_t len; +}; + +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Number of descriptors + * @v reg Descriptor start address register + */ +static inline __attribute__ (( always_inline)) void +realtek_init_ring ( struct realtek_ring *ring, unsigned int count, + unsigned int reg ) { + ring->len = ( count * sizeof ( ring->desc[0] ) ); + ring->reg = reg; +} + +/** A Realtek network card */ +struct realtek_nic { + /** Registers */ + void *regs; + /** SPI bit-bashing interface */ + struct spi_bit_basher spibit; + /** EEPROM */ + struct spi_device eeprom; + /** Non-volatile options */ + struct nvo_block nvo; + /** MII interface */ + struct mii_interface mii; + + /** Legacy datapath mode */ + int legacy; + /** PHYAR and PHYSTATUS registers are present */ + int have_phy_regs; + /** TPPoll register offset */ + unsigned int tppoll; + + /** Transmit descriptor ring */ + struct realtek_ring tx; + /** Receive descriptor ring */ + struct realtek_ring rx; + /** Receive I/O buffers */ + struct io_buffer *rx_iobuf[RTL_NUM_RX_DESC]; + /** Receive buffer (legacy mode) */ + void *rx_buffer; + /** Offset within receive buffer (legacy mode) */ + unsigned int rx_offset; +}; + +#endif /* _REALTEK_H */ diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c deleted file mode 100644 index 2da8223a..00000000 --- a/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 ( ! ( inb ( 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/src/drivers/net/skeleton.c b/src/drivers/net/skeleton.c new file mode 100644 index 00000000..3e1e2d54 --- /dev/null +++ b/src/drivers/net/skeleton.c @@ -0,0 +1,308 @@ +/* + * 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: + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void skeleton_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct skeleton_nic *skel = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset card */ + skeleton_reset ( skel ); + + /* Free network device */ + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** Skeleton PCI device IDs */ +static struct pci_device_id skeleton_nics[] = { + PCI_ROM ( 0x5ce1, 0x5ce1, "skel", "Skeleton", 0 ), +}; + +/** Skeleton PCI driver */ +struct pci_driver skeleton_driver __pci_driver = { + .ids = skeleton_nics, + .id_count = ( sizeof ( skeleton_nics ) / sizeof ( skeleton_nics[0] ) ), + .probe = skeleton_probe, + .remove = skeleton_remove, +}; diff --git a/src/drivers/net/skeleton.h b/src/drivers/net/skeleton.h new file mode 100644 index 00000000..3de2afa5 --- /dev/null +++ b/src/drivers/net/skeleton.h @@ -0,0 +1,23 @@ +#ifndef _SKELETON_H +#define _SKELETON_H + +/** @file + * + * Skeleton network driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** Skeleton BAR size */ +#define SKELETON_BAR_SIZE 256 + +/** A skeleton network card */ +struct skeleton_nic { + /** Registers */ + void *regs; + /** MII interface */ + struct mii_interface mii; +}; + +#endif /* _SKELETON_H */ diff --git a/src/hci/commands/digest_cmd.c b/src/hci/commands/digest_cmd.c index 6ca12eff..fac49765 100644 --- a/src/hci/commands/digest_cmd.c +++ b/src/hci/commands/digest_cmd.c @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -74,8 +75,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/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c index 999442ca..1ae33074 100644 --- a/src/hci/commands/image_cmd.c +++ b/src/hci/commands/image_cmd.c @@ -34,123 +34,158 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ -/** "imgfetch" options */ -struct imgfetch_options { +/** "img{single}" options */ +struct imgsingle_options { /** Image name */ const char *name; }; -/** "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 ), }; -/** "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 ] [...]" ); + +/** An "img{single}" family command descriptor */ +struct imgsingle_descriptor { + /** Command descriptor */ + struct command_descriptor *cmd; + /** Function to use to acquire the image */ + int ( * acquire ) ( const char *name, struct image **image ); + /** Pre-action to take upon image, or NULL */ + void ( * preaction ) ( struct image *image ); + /** Action to take upon image, or NULL */ + int ( * action ) ( struct image *image ); + /** Verb to describe action */ + const char *verb; +}; /** - * The "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 command line */ - if ( argv[ optind + 1 ] != NULL ) { - cmdline = concat_args ( &argv[ optind + 1 ] ); - if ( ! cmdline ) { - rc = -ENOMEM; - goto err_cmdline; + /* 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; + } } } - /* 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; + /* 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; + } } - /* Free command line */ - free ( cmdline ); + /* Carry out command pre-action, if applicable */ + if ( desc->preaction ) + desc->preaction ( image ); - return 0; + /* 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; + } + } - err_imgdownload: + /* Set the command-line arguments, if applicable */ + if ( cmdline ) { + if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) { + printf ( "Could not set arguments: %s\n", + strerror ( rc ) ); + goto err_set_cmdline; + } + } + + /* Carry out command action, if applicable */ + if ( desc->action ) { + if ( ( rc = desc->action ( image ) ) != 0 ) { + printf ( "Could not %s: %s\n", + desc->verb, strerror ( rc ) ); + goto err_action; + } + } + + /* Success */ + rc = 0; + + err_action: + err_set_cmdline: + err_set_name: + err_acquire: free ( cmdline ); - err_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 ] [...]" ); + +/** "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", NULL ); + return imgsingle_exec ( argc, argv, &imgfetch_desc ); } -/** - * The "kernel" command - * - * @v argc Argument count - * @v argv Argument list - * @ret rc Return status code - */ -static int kernel_exec ( int argc, char **argv ) { - - return imgfetch_core_exec ( argc, argv, "select", image_select ); -} - -/** - * The "chain" 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", image_exec ); -} - -/** "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, - "" ); +/** "imgselect" family command descriptor */ +struct imgsingle_descriptor imgselect_desc = { + .cmd = &imgsingle_cmd, + .acquire = imgacquire, + .action = image_select, + .verb = "select", +}; /** * The "imgselect" command @@ -160,38 +195,40 @@ static struct command_descriptor imgselect_cmd = * @ret rc Return status code */ static int imgselect_exec ( int argc, char **argv ) { - struct imgselect_options opts; - struct image *image; - int rc; - - /* Parse options */ - if ( ( rc = parse_options ( argc, argv, &imgselect_cmd, &opts ) ) != 0 ) - return rc; - - /* Parse image name */ - if ( ( rc = parse_image ( argv[optind], &image ) ) != 0 ) - return rc; - - /* Load image */ - if ( ( rc = imgselect ( image ) ) != 0 ) { - printf ( "Could not select %s: %s\n", - image->name, strerror ( rc ) ); - return rc; - } - - return 0; + return imgsingle_exec ( argc, argv, &imgselect_desc ); } -/** "imgargs" options */ -struct imgargs_options {}; +/** "imgexec" command descriptor */ +static struct command_descriptor imgexec_cmd = + COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, + 0, MAX_ARGUMENTS, + "[--name ] [ [...]]" ); -/** "imgargs" option list */ -static struct option_descriptor imgargs_opts[] = {}; +/** "imgexec" family command descriptor */ +struct imgsingle_descriptor imgexec_desc = { + .cmd = &imgexec_cmd, + .acquire = imgacquire, + .action = image_exec, + .verb = "boot", +}; -/** "imgargs" command descriptor */ -static struct command_descriptor imgargs_cmd = - COMMAND_DESC ( struct imgargs_options, imgargs_opts, 1, MAX_ARGUMENTS, - " [...]" ); +/** + * The "imgexec" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int imgexec_exec ( int argc, char **argv) { + return imgsingle_exec ( argc, argv, &imgexec_desc ); +} + +/** "imgargs" family command descriptor */ +struct imgsingle_descriptor imgargs_desc = { + .cmd = &imgsingle_cmd, + .acquire = imgacquire, + .preaction = image_clear_cmdline, +}; /** * The "imgargs" command body @@ -201,105 +238,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 * @@ -308,33 +300,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 * @@ -343,28 +311,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 */ @@ -383,19 +330,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/src/hci/commands/image_trust_cmd.c b/src/hci/commands/image_trust_cmd.c new file mode 100644 index 00000000..25e77dde --- /dev/null +++ b/src/hci/commands/image_trust_cmd.c @@ -0,0 +1,172 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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/src/hci/commands/menu_cmd.c b/src/hci/commands/menu_cmd.c new file mode 100644 index 00000000..ff3b76fa --- /dev/null +++ b/src/hci/commands/menu_cmd.c @@ -0,0 +1,284 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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, item->label ) ) != 0 ) { + printf ( "Could not store \"%s\": %s\n", + setting, strerror ( rc ) ); + goto err_store; + } + + /* Success */ + rc = 0; + + err_store: + err_show_menu: + /* Destroy menu, if applicable */ + if ( ! opts.keep ) + destroy_menu ( menu ); + err_parse_menu: + err_parse_options: + return rc; +} + +/** Menu commands */ +struct command menu_commands[] __command = { + { + .name = "menu", + .exec = menu_exec, + }, + { + .name = "item", + .exec = item_exec, + }, + { + .name = "choose", + .exec = choose_exec, + }, +}; diff --git a/src/hci/editstring.c b/src/hci/editstring.c index 996528ff..35a5b2c1 100644 --- a/src/hci/editstring.c +++ b/src/hci/editstring.c @@ -36,6 +36,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 +109,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 +180,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/src/hci/keymap/keymap_no-latin1.c b/src/hci/keymap/keymap_no-latin1.c new file mode 100644 index 00000000..8c3e81b3 --- /dev/null +++ b/src/hci/keymap/keymap_no-latin1.c @@ -0,0 +1,34 @@ +/** @file + * + * "no-latin1" keyboard mapping + * + * This file is automatically generated; do not edit + * + */ + +FILE_LICENCE ( PUBLIC_DOMAIN ); + +#include <ipxe/keymap.h> + +/** "no-latin1" keyboard mapping */ +struct key_mapping no_latin1_mapping[] __keymap = { + { 0x26, 0x2f }, /* '&' => '/' */ + { 0x28, 0x29 }, /* '(' => ')' */ + { 0x29, 0x3d }, /* ')' => '=' */ + { 0x2a, 0x28 }, /* '*' => '(' */ + { 0x2b, 0x60 }, /* '+' => '`' */ + { 0x2d, 0x2b }, /* '-' => '+' */ + { 0x2f, 0x2d }, /* '/' => '-' */ + { 0x3c, 0x3b }, /* '<' => ';' */ + { 0x3d, 0x5c }, /* '=' => '\\' */ + { 0x3e, 0x3a }, /* '>' => ':' */ + { 0x3f, 0x5f }, /* '?' => '_' */ + { 0x40, 0x22 }, /* '@' => '"' */ + { 0x5c, 0x27 }, /* '\\' => '\'' */ + { 0x5d, 0x7e }, /* ']' => '~' */ + { 0x5e, 0x26 }, /* '^' => '&' */ + { 0x5f, 0x3f }, /* '_' => '?' */ + { 0x60, 0x7c }, /* '`' => '|' */ + { 0x7c, 0x2a }, /* '|' => '*' */ + { 0x7d, 0x5e }, /* '}' => '^' */ +}; diff --git a/src/hci/mucurses/ansi_screen.c b/src/hci/mucurses/ansi_screen.c index cc342f7c..d952e5f2 100644 --- a/src/hci/mucurses/ansi_screen.c +++ b/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/src/hci/mucurses/mucurses.c b/src/hci/mucurses/mucurses.c index 7c162021..ab9a6535 100644 --- a/src/hci/mucurses/mucurses.c +++ b/src/hci/mucurses/mucurses.c @@ -1,4 +1,3 @@ -#include <ipxe/console.h> #include <curses.h> #include "mucurses.h" diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c new file mode 100644 index 00000000..30d93ad2 --- /dev/null +++ b/src/hci/tui/menu_ui.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Menu interface + * + */ + +#include <string.h> +#include <errno.h> +#include <curses.h> +#include <ipxe/keys.h> +#include <ipxe/timer.h> +#include <ipxe/console.h> +#include <ipxe/menu.h> + +/* Colour pairs */ +#define CPAIR_NORMAL 1 +#define CPAIR_SELECT 2 +#define CPAIR_SEPARATOR 3 + +/* Screen layout */ +#define TITLE_ROW 1 +#define MENU_ROW 3 +#define MENU_COL 1 +#define MENU_ROWS 18 +#define MENU_COLS 78 +#define MENU_PAD 2 + +/** A menu user interface */ +struct menu_ui { + /** Menu */ + struct menu *menu; + /** Number of menu items */ + int count; + /** Currently selected item */ + int selected; + /** First visible item */ + int first_visible; + /** Timeout (0=indefinite) */ + unsigned long timeout; +}; + +/** + * Return a numbered menu item + * + * @v menu Menu + * @v index Index + * @ret item Menu item, or NULL + */ +static struct menu_item * menu_item ( struct menu *menu, unsigned int index ) { + struct menu_item *item; + + list_for_each_entry ( item, &menu->items, list ) { + if ( index-- == 0 ) + return item; + } + + return NULL; +} + +/** + * Draw a numbered menu item + * + * @v ui Menu user interface + * @v index Index + */ +static void draw_menu_item ( struct menu_ui *ui, int index ) { + struct menu_item *item; + unsigned int row_offset; + char buf[ MENU_COLS + 1 /* NUL */ ]; + char timeout_buf[6]; /* "(xxx)" + NUL */ + size_t timeout_len; + size_t max_len; + size_t len; + + /* Move to start of row */ + row_offset = ( index - ui->first_visible ); + move ( ( MENU_ROW + row_offset ), MENU_COL ); + + /* Get menu item */ + item = menu_item ( ui->menu, index ); + if ( item ) { + + /* Draw separators in a different colour */ + if ( ! item->label ) + color_set ( CPAIR_SEPARATOR, NULL ); + + /* Highlight if this is the selected item */ + if ( index == ui->selected ) { + color_set ( CPAIR_SELECT, NULL ); + attron ( A_BOLD ); + } + + /* Construct row */ + memset ( buf, ' ', ( sizeof ( buf ) - 1 ) ); + buf[ sizeof ( buf ) -1 ] = '\0'; + len = strlen ( item->text ); + max_len = ( sizeof ( buf ) - 1 /* NUL */ - ( 2 * MENU_PAD ) ); + if ( len > max_len ) + len = max_len; + memcpy ( ( buf + MENU_PAD ), item->text, len ); + + /* Add timeout if applicable */ + timeout_len = + snprintf ( timeout_buf, sizeof ( timeout_buf ), "(%ld)", + ( ( ui->timeout + TICKS_PER_SEC - 1 ) / + TICKS_PER_SEC ) ); + if ( ( index == ui->selected ) && ( ui->timeout != 0 ) ) { + memcpy ( ( buf + MENU_COLS - MENU_PAD - timeout_len ), + timeout_buf, timeout_len ); + } + + /* Print row */ + printw ( "%s", buf ); + + /* Reset attributes */ + color_set ( CPAIR_NORMAL, NULL ); + attroff ( A_BOLD ); + + } else { + /* Clear row if there is no corresponding menu item */ + clrtoeol(); + } + + /* Move cursor back to start of row */ + move ( ( MENU_ROW + row_offset ), MENU_COL ); +} + +/** + * Draw the current block of menu items + * + * @v ui Menu user interface + */ +static void draw_menu_items ( struct menu_ui *ui ) { + unsigned int i; + + /* Jump scroll to correct point in list */ + while ( ui->first_visible < ui->selected ) + ui->first_visible += MENU_ROWS; + while ( ui->first_visible > ui->selected ) + ui->first_visible -= MENU_ROWS; + + /* Draw ellipses before and/or after the list as necessary */ + color_set ( CPAIR_SEPARATOR, NULL ); + mvaddstr ( ( MENU_ROW - 1 ), ( MENU_COL + MENU_PAD ), + ( ( ui->first_visible > 0 ) ? "..." : " " ) ); + mvaddstr ( ( MENU_ROW + MENU_ROWS ), ( MENU_COL + MENU_PAD ), + ( ( ( ui->first_visible + MENU_ROWS ) < ui->count ) ? + "..." : " " ) ); + color_set ( CPAIR_NORMAL, NULL ); + + /* Draw visible items */ + for ( i = 0 ; i < MENU_ROWS ; i++ ) + draw_menu_item ( ui, ( ui->first_visible + i ) ); +} + +/** + * Menu main loop + * + * @v ui Menu user interface + * @ret selected Selected item + * @ret rc Return status code + */ +static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) { + struct menu_item *item; + unsigned long timeout; + unsigned int delta; + int current; + int key; + int i; + int move; + int chosen = 0; + int rc = 0; + + do { + /* Record current selection */ + current = ui->selected; + + /* Calculate timeout as remainder of current second */ + timeout = ( ui->timeout % TICKS_PER_SEC ); + if ( ( timeout == 0 ) && ( ui->timeout != 0 ) ) + timeout = TICKS_PER_SEC; + ui->timeout -= timeout; + + /* Get key */ + move = 0; + key = getkey ( timeout ); + if ( key < 0 ) { + /* Choose default if we finally time out */ + if ( ui->timeout == 0 ) + chosen = 1; + } else { + /* Cancel any timeout */ + ui->timeout = 0; + + /* Handle key */ + switch ( key ) { + case KEY_UP: + move = -1; + break; + case KEY_DOWN: + move = +1; + break; + case KEY_PPAGE: + move = ( ui->first_visible - ui->selected - 1 ); + break; + case KEY_NPAGE: + move = ( ui->first_visible - ui->selected + + MENU_ROWS ); + break; + case KEY_HOME: + move = -ui->count; + break; + case KEY_END: + move = +ui->count; + break; + case ESC: + case CTRL_C: + rc = -ECANCELED; + break; + case CR: + case LF: + chosen = 1; + break; + default: + i = 0; + list_for_each_entry ( item, &ui->menu->items, + list ) { + if ( item->shortcut == key ) { + ui->selected = i; + chosen = 1; + break; + } + i++; + } + break; + } + } + + /* Move selection, if applicable */ + while ( move ) { + ui->selected += move; + if ( ui->selected < 0 ) { + ui->selected = 0; + move = +1; + } else if ( ui->selected >= ui->count ) { + ui->selected = ( ui->count - 1 ); + move = -1; + } + item = menu_item ( ui->menu, ui->selected ); + if ( item->label ) + break; + move = ( ( move > 0 ) ? +1 : -1 ); + } + + /* Redraw selection if necessary */ + if ( ( ui->selected != current ) || ( timeout != 0 ) ) { + draw_menu_item ( ui, current ); + delta = ( ui->selected - ui->first_visible ); + if ( delta >= MENU_ROWS ) + draw_menu_items ( ui ); + draw_menu_item ( ui, ui->selected ); + } + + /* Refuse to choose unlabelled items (i.e. separators) */ + item = menu_item ( ui->menu, ui->selected ); + if ( ! item->label ) + chosen = 0; + + /* Record selection */ + *selected = item; + + } while ( ( rc == 0 ) && ! chosen ); + + return rc; +} + +/** + * Show menu + * + * @v menu Menu + * @v wait_ms Time to wait, in milliseconds (0=indefinite) + * @ret selected Selected item + * @ret rc Return status code + */ +int show_menu ( struct menu *menu, unsigned int timeout_ms, + const char *select, struct menu_item **selected ) { + struct menu_item *item; + struct menu_ui ui; + int labelled_count = 0; + int rc; + + /* Initialise UI */ + memset ( &ui, 0, sizeof ( ui ) ); + ui.menu = menu; + ui.timeout = ( ( timeout_ms * TICKS_PER_SEC ) / 1000 ); + list_for_each_entry ( item, &menu->items, list ) { + if ( item->label ) { + if ( ! labelled_count ) + ui.selected = ui.count; + labelled_count++; + if ( select ) { + if ( strcmp ( select, item->label ) == 0 ) + ui.selected = ui.count; + } else { + if ( item->is_default ) + ui.selected = ui.count; + } + } + ui.count++; + } + if ( ! labelled_count ) { + /* Menus with no labelled items cannot be selected + * from, and will seriously confuse the navigation + * logic. Refuse to display any such menus. + */ + return -ENOENT; + } + + /* Initialise screen */ + initscr(); + start_color(); + init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); + init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED ); + init_pair ( CPAIR_SEPARATOR, COLOR_CYAN, COLOR_BLUE ); + color_set ( CPAIR_NORMAL, NULL ); + erase(); + + /* Draw initial content */ + attron ( A_BOLD ); + mvprintw ( TITLE_ROW, ( ( COLS - strlen ( ui.menu->title ) ) / 2 ), + "%s", ui.menu->title ); + attroff ( A_BOLD ); + draw_menu_items ( &ui ); + draw_menu_item ( &ui, ui.selected ); + + /* Enter main loop */ + rc = menu_loop ( &ui, selected ); + assert ( *selected ); + + /* Clear screen */ + endwin(); + + return rc; +} diff --git a/src/image/elf.c b/src/image/elf.c index 406a8d47..26666ec5 100644 --- a/src/image/elf.c +++ b/src/image/elf.c @@ -38,6 +38,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 +47,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 +82,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 +97,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 +127,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 +146,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 +168,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/src/image/script.c b/src/image/script.c index fb89e422..b032d18f 100644 --- a/src/image/script.c +++ b/src/image/script.c @@ -58,6 +58,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 +72,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 ); @@ -302,7 +303,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/src/include/btext.h b/src/include/btext.h deleted file mode 100644 index 1d3f9e59..00000000 --- a/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/src/include/compiler.h b/src/include/compiler.h index feea5167..ed9af237 100644 --- a/src/include/compiler.h +++ b/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/src/include/etherboot.h b/src/include/etherboot.h index b2fbe4f6..ba79cb16 100644 --- a/src/include/etherboot.h +++ b/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/src/include/ipxe/aes.h b/src/include/ipxe/aes.h index 5d645b20..4e44f985 100644 --- a/src/include/ipxe/aes.h +++ b/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/src/include/ipxe/ansiesc.h b/src/include/ipxe/ansiesc.h index 35438e43..c00af258 100644 --- a/src/include/ipxe/ansiesc.h +++ b/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/src/include/ipxe/arp.h b/src/include/ipxe/arp.h index f7b99c68..00396d82 100644 --- a/src/include/ipxe/arp.h +++ b/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/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 7ac10862..1c433c5e 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -9,38 +9,235 @@ FILE_LICENCE ( GPL2_OR_LATER ); -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OID 0x06 -#define ASN1_SEQUENCE 0x30 -#define ASN1_IP_ADDRESS 0x40 -#define ASN1_EXPLICIT_TAG 0xa0 +#include <stdint.h> +#include <ipxe/tables.h> -/** - * A DER-encoded ASN.1 object cursor - */ +/** An ASN.1 object cursor */ struct asn1_cursor { /** Start of data */ - void *data; + const void *data; /** Length of data */ size_t len; }; +/** 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 UTC time */ +#define ASN1_UTC_TIME 0x17 + +/** ASN.1 generalized time */ +#define ASN1_GENERALIZED_TIME 0x18 + +/** ASN.1 sequence */ +#define ASN1_SEQUENCE 0x30 + +/** ASN.1 set */ +#define ASN1_SET 0x31 + +/** ASN.1 implicit tag */ +#define ASN1_IMPLICIT_TAG( number) ( 0x80 | (number) ) + +/** ASN.1 explicit tag */ +#define ASN1_EXPLICIT_TAG( number) ( 0xa0 | (number) ) + +/** ASN.1 "any tag" magic value */ +#define ASN1_ANY -1U + +/** Initial OID byte */ +#define ASN1_OID_INITIAL( first, second ) ( ( (first) * 40 ) + (second) ) + +/** Single-byte OID value + * + * Valid for values up to 127 + */ +#define ASN1_OID_SINGLE( value ) ( (value) & 0x7f ) + +/** Double-byte OID value + * + * Valid for values up to 16383 + */ +#define ASN1_OID_DOUBLE( value ) \ + ( 0x80 | ( ( (value) >> 7 ) & 0x7f ) ), ASN1_OID_SINGLE ( (value) ) + +/** Double-byte OID value + * + * Valid for values up to 2097151 + */ +#define ASN1_OID_TRIPLE( value ) \ + ( 0x80 | ( ( (value) >> 14 ) & 0x7f ) ), ASN1_OID_DOUBLE ( (value) ) + +/** ASN.1 OID for rsaEncryption (1.2.840.113549.1.1.1) */ +#define ASN1_OID_RSAENCRYPTION \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 1 ) + +/** ASN.1 OID for md5WithRSAEncryption (1.2.840.113549.1.1.4) */ +#define ASN1_OID_MD5WITHRSAENCRYPTION \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 4 ) + +/** ASN.1 OID for sha1WithRSAEncryption (1.2.840.113549.1.1.5) */ +#define ASN1_OID_SHA1WITHRSAENCRYPTION \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ) + +/** ASN.1 OID for sha256WithRSAEncryption (1.2.840.113549.1.1.11) */ +#define ASN1_OID_SHA256WITHRSAENCRYPTION \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 11 ) + +/** ASN.1 OID for id-md5 (1.2.840.113549.2.5) */ +#define ASN1_OID_MD5 \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 2 ), \ + ASN1_OID_SINGLE ( 5 ) + +/** ASN.1 OID for id-sha1 (1.3.14.3.2.26) */ +#define ASN1_OID_SHA1 \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 14 ), \ + ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 2 ), \ + ASN1_OID_SINGLE ( 26 ) + +/** ASN.1 OID for id-sha256 (2.16.840.1.101.3.4.2.1) */ +#define ASN1_OID_SHA256 \ + ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 101 ), \ + ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 4 ), \ + ASN1_OID_SINGLE ( 2 ), ASN1_OID_SINGLE ( 1 ) + +/** ASN.1 OID for commonName (2.5.4.3) */ +#define ASN1_OID_COMMON_NAME \ + ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 4 ), \ + ASN1_OID_SINGLE ( 3 ) + +/** ASN.1 OID for id-ce-keyUsage (2.5.29.15) */ +#define ASN1_OID_KEYUSAGE \ + ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \ + ASN1_OID_SINGLE ( 15 ) + +/** ASN.1 OID for id-ce-basicConstraints (2.5.29.19) */ +#define ASN1_OID_BASICCONSTRAINTS \ + ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \ + ASN1_OID_SINGLE ( 19 ) + +/** ASN.1 OID for id-ce-extKeyUsage (2.5.29.37) */ +#define ASN1_OID_EXTKEYUSAGE \ + ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ), \ + ASN1_OID_SINGLE ( 37 ) + +/** ASN.1 OID for id-kp-codeSigning (1.3.6.1.5.5.7.3.3) */ +#define ASN1_OID_CODESIGNING \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \ + ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ + ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 3 ) + +/** ASN.1 OID for pkcs-signedData (1.2.840.113549.1.7.2) */ +#define ASN1_OID_SIGNEDDATA \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 2 ) + +/** ASN.1 OID for id-pe-authorityInfoAccess (1.3.6.1.5.5.7.1.1) */ +#define ASN1_OID_AUTHORITYINFOACCESS \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \ + ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 1 ) + +/** ASN.1 OID for id-ad-ocsp (1.3.6.1.5.5.7.48.1) */ +#define ASN1_OID_OCSP \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \ + ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ + ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 ) + +/** 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 boolean */ +struct asn1_boolean { + /** Value */ + uint8_t value; +} __attribute__ (( packed )); + +/** An ASN.1 bit string */ +struct asn1_bit_string { + /** Number of unused bits */ + uint8_t unused; + /** Data */ + uint8_t data[0]; +} __attribute__ (( packed )); + /** - * Invalidate ASN.1 object cursor + * Extract ASN.1 type * * @v cursor ASN.1 object cursor + * @ret type Type */ -static inline __attribute__ (( always_inline )) void -asn1_invalidate_cursor ( struct asn1_cursor *cursor ) { - cursor->len = 0; +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_compare ( const struct asn1_cursor *cursor1, + const struct asn1_cursor *cursor2 ); +extern struct asn1_algorithm * +asn1_algorithm ( const struct asn1_cursor *cursor ); #endif /* _IPXE_ASN1_H */ diff --git a/src/include/ipxe/bigint.h b/src/include/ipxe/bigint.h new file mode 100644 index 00000000..97fbce24 --- /dev/null +++ b/src/include/ipxe/bigint.h @@ -0,0 +1,301 @@ +#ifndef _IPXE_BIGINT_H +#define _IPXE_BIGINT_H + +/** @file + * + * Big integer support + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * Define a big-integer type + * + * @v size Number of elements + * @ret bigint_t Big integer type + */ +#define bigint_t( size ) \ + struct { \ + bigint_element_t element[ (size) ]; \ + } + +/** + * Determine number of elements required for a big-integer type + * + * @v len Maximum length of big integer, in bytes + * @ret size Number of elements + */ +#define bigint_required_size( len ) \ + ( ( (len) + sizeof ( bigint_element_t ) - 1 ) / \ + sizeof ( bigint_element_t ) ) + +/** + * Determine number of elements in big-integer type + * + * @v bigint Big integer + * @ret size Number of elements + */ +#define bigint_size( bigint ) \ + ( sizeof ( *(bigint) ) / sizeof ( (bigint)->element[0] ) ) + +/** + * Initialise big integer + * + * @v value Big integer to initialise + * @v data Raw data + * @v len Length of raw data + */ +#define bigint_init( value, data, len ) do { \ + unsigned int size = bigint_size (value); \ + assert ( (len) <= ( size * sizeof ( (value)->element[0] ) ) ); \ + bigint_init_raw ( (value)->element, size, (data), (len) ); \ + } while ( 0 ) + +/** + * Finalise big integer + * + * @v value Big integer to finalise + * @v out Output buffer + * @v len Length of output buffer + */ +#define bigint_done( value, out, len ) do { \ + unsigned int size = bigint_size (value); \ + bigint_done_raw ( (value)->element, size, (out), (len) ); \ + } while ( 0 ) + +/** + * Add big integers + * + * @v addend Big integer to add + * @v value Big integer to be added to + */ +#define bigint_add( addend, value ) do { \ + unsigned int size = bigint_size (addend); \ + bigint_add_raw ( (addend)->element, (value)->element, size ); \ + } while ( 0 ) + +/** + * Subtract big integers + * + * @v subtrahend Big integer to subtract + * @v value Big integer to be subtracted from + */ +#define bigint_subtract( subtrahend, value ) do { \ + unsigned int size = bigint_size (subtrahend); \ + bigint_subtract_raw ( (subtrahend)->element, (value)->element, \ + size ); \ + } while ( 0 ) + +/** + * Rotate big integer left + * + * @v value Big integer + */ +#define bigint_rol( value ) do { \ + unsigned int size = bigint_size (value); \ + bigint_rol_raw ( (value)->element, size ); \ + } while ( 0 ) + +/** + * Rotate big integer right + * + * @v value Big integer + */ +#define bigint_ror( value ) do { \ + unsigned int size = bigint_size (value); \ + bigint_ror_raw ( (value)->element, size ); \ + } while ( 0 ) + +/** + * Test if big integer is equal to zero + * + * @v value Big integer + * @v size Number of elements + * @ret is_zero Big integer is equal to zero + */ +#define bigint_is_zero( value ) ( { \ + unsigned int size = bigint_size (value); \ + bigint_is_zero_raw ( (value)->element, size ); } ) + +/** + * Compare big integers + * + * @v value Big integer + * @v reference Reference big integer + * @ret geq Big integer is greater than or equal to the reference + */ +#define bigint_is_geq( value, reference ) ( { \ + unsigned int size = bigint_size (value); \ + bigint_is_geq_raw ( (value)->element, (reference)->element, \ + size ); } ) + +/** + * Test if bit is set in big integer + * + * @v value Big integer + * @v bit Bit to test + * @ret is_set Bit is set + */ +#define bigint_bit_is_set( value, bit ) ( { \ + unsigned int size = bigint_size (value); \ + bigint_bit_is_set_raw ( (value)->element, size, bit ); } ) + +/** + * Find highest bit set in big integer + * + * @v value Big integer + * @ret max_bit Highest bit set + 1 (or 0 if no bits set) + */ +#define bigint_max_set_bit( value ) ( { \ + unsigned int size = bigint_size (value); \ + bigint_max_set_bit_raw ( (value)->element, size ); } ) + +/** + * Grow big integer + * + * @v source Source big integer + * @v dest Destination big integer + */ +#define bigint_grow( source, dest ) do { \ + unsigned int source_size = bigint_size (source); \ + unsigned int dest_size = bigint_size (dest); \ + bigint_grow_raw ( (source)->element, source_size, \ + (dest)->element, dest_size ); \ + } while ( 0 ) + +/** + * Shrink big integer + * + * @v source Source big integer + * @v dest Destination big integer + */ +#define bigint_shrink( source, dest ) do { \ + unsigned int source_size = bigint_size (source); \ + unsigned int dest_size = bigint_size (dest); \ + bigint_shrink_raw ( (source)->element, source_size, \ + (dest)->element, dest_size ); \ + } while ( 0 ) + +/** + * Multiply big integers + * + * @v multiplicand Big integer to be multiplied + * @v multiplier Big integer to be multiplied + * @v result Big integer to hold result + */ +#define bigint_multiply( multiplicand, multiplier, result ) do { \ + unsigned int size = bigint_size (multiplicand); \ + bigint_multiply_raw ( (multiplicand)->element, \ + (multiplier)->element, (result)->element, \ + size ); \ + } while ( 0 ) + +/** + * Perform modular multiplication of big integers + * + * @v multiplicand Big integer to be multiplied + * @v multiplier Big integer to be multiplied + * @v modulus Big integer modulus + * @v result Big integer to hold result + * @v tmp Temporary working space + */ +#define bigint_mod_multiply( multiplicand, multiplier, modulus, \ + result, tmp ) do { \ + unsigned int size = bigint_size (multiplicand); \ + bigint_mod_multiply_raw ( (multiplicand)->element, \ + (multiplier)->element, \ + (modulus)->element, \ + (result)->element, size, tmp ); \ + } while ( 0 ) + +/** + * Calculate temporary working space required for moduluar multiplication + * + * @v modulus Big integer modulus + * @ret len Length of temporary working space + */ +#define bigint_mod_multiply_tmp_len( modulus ) ( { \ + unsigned int size = bigint_size (modulus); \ + sizeof ( struct { \ + bigint_t ( size * 2 ) temp_result; \ + bigint_t ( size * 2 ) temp_modulus; \ + } ); } ) + +/** + * Perform modular exponentiation of big integers + * + * @v base Big integer base + * @v modulus Big integer modulus + * @v exponent Big integer exponent + * @v result Big integer to hold result + * @v tmp Temporary working space + */ +#define bigint_mod_exp( base, modulus, exponent, result, tmp ) do { \ + unsigned int size = bigint_size (base); \ + unsigned int exponent_size = bigint_size (exponent); \ + bigint_mod_exp_raw ( (base)->element, (modulus)->element, \ + (exponent)->element, (result)->element, \ + size, exponent_size, tmp ); \ + } while ( 0 ) + +/** + * Calculate temporary working space required for moduluar exponentiation + * + * @v modulus Big integer modulus + * @v exponent Big integer exponent + * @ret len Length of temporary working space + */ +#define bigint_mod_exp_tmp_len( modulus, exponent ) ( { \ + unsigned int size = bigint_size (modulus); \ + unsigned int exponent_size = bigint_size (exponent); \ + size_t mod_multiply_len = \ + bigint_mod_multiply_tmp_len (modulus); \ + sizeof ( struct { \ + bigint_t ( size ) temp_base; \ + bigint_t ( exponent_size ) temp_exponent; \ + uint8_t mod_multiply[mod_multiply_len]; \ + } ); } ) + +#include <bits/bigint.h> + +void bigint_init_raw ( bigint_element_t *value0, unsigned int size, + const void *data, size_t len ); +void bigint_done_raw ( const bigint_element_t *value0, unsigned int size, + void *out, size_t len ); +void bigint_add_raw ( const bigint_element_t *addend0, + bigint_element_t *value0, unsigned int size ); +void bigint_subtract_raw ( const bigint_element_t *subtrahend0, + bigint_element_t *value0, unsigned int size ); +void bigint_rol_raw ( bigint_element_t *value0, unsigned int size ); +void bigint_ror_raw ( bigint_element_t *value0, unsigned int size ); +int bigint_is_zero_raw ( const bigint_element_t *value0, unsigned int size ); +int bigint_is_geq_raw ( const bigint_element_t *value0, + const bigint_element_t *reference0, + unsigned int size ); +int bigint_bit_is_set_raw ( const bigint_element_t *value0, unsigned int size, + unsigned int bit ); +int bigint_max_set_bit_raw ( const bigint_element_t *value0, + unsigned int size ); +void bigint_grow_raw ( const bigint_element_t *source0, + unsigned int source_size, bigint_element_t *dest0, + unsigned int dest_size ); +void bigint_shrink_raw ( const bigint_element_t *source0, + unsigned int source_size, bigint_element_t *dest0, + unsigned int dest_size ); +void bigint_multiply_raw ( const bigint_element_t *multiplicand0, + const bigint_element_t *multiplier0, + bigint_element_t *result0, + unsigned int size ); +void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0, + const bigint_element_t *multiplier0, + const bigint_element_t *modulus0, + bigint_element_t *result0, + unsigned int size, void *tmp ); +void bigint_mod_exp_raw ( const bigint_element_t *base0, + const bigint_element_t *modulus0, + const bigint_element_t *exponent0, + bigint_element_t *result0, + unsigned int size, unsigned int exponent_size, + void *tmp ); + +#endif /* _IPXE_BIGINT_H */ diff --git a/src/include/ipxe/clientcert.h b/src/include/ipxe/clientcert.h new file mode 100644 index 00000000..08f62eb7 --- /dev/null +++ b/src/include/ipxe/clientcert.h @@ -0,0 +1,43 @@ +#ifndef _IPXE_CLIENTCERT_H +#define _IPXE_CLIENTCERT_H + +/** @file + * + * Client certificate store + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> + +/** A client certificate */ +struct client_certificate { + /** Data */ + const void *data; + /** Length */ + size_t len; +}; + +/** A client private key */ +struct client_private_key { + /** Data */ + const void *data; + /** Length */ + size_t len; +}; + +extern struct client_certificate client_certificate; +extern struct client_private_key client_private_key; + +/** + * Check for presence of a client certificate + * + * @ret have_cert We have a client certificate and private key + */ +static inline int have_client_certificate ( void ) { + return ( ( client_certificate.len > 0 ) && + ( client_private_key.len > 0 ) ); +} + +#endif /* _IPXE_CLIENTCERT_H */ diff --git a/src/include/ipxe/cms.h b/src/include/ipxe/cms.h new file mode 100644 index 00000000..eadeca4b --- /dev/null +++ b/src/include/ipxe/cms.h @@ -0,0 +1,75 @@ +#ifndef _IPXE_CMS_H +#define _IPXE_CMS_H + +/** @file + * + * Cryptographic Message Syntax (PKCS #7) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <time.h> +#include <ipxe/asn1.h> +#include <ipxe/crypto.h> +#include <ipxe/x509.h> +#include <ipxe/refcnt.h> +#include <ipxe/uaccess.h> + +/** CMS signer information */ +struct cms_signer_info { + /** List of signer information blocks */ + struct list_head list; + + /** Certificate chain */ + struct x509_chain *chain; + + /** Digest algorithm */ + struct digest_algorithm *digest; + /** Public-key algorithm */ + struct pubkey_algorithm *pubkey; + + /** Signature */ + void *signature; + /** Length of signature */ + size_t signature_len; +}; + +/** A CMS signature */ +struct cms_signature { + /** Reference count */ + struct refcnt refcnt; + /** List of all certificates */ + struct x509_chain *certificates; + /** List of signer information blocks */ + struct list_head info; +}; + +/** + * Get reference to CMS signature + * + * @v sig CMS signature + * @ret sig CMS signature + */ +static inline __attribute__ (( always_inline )) struct cms_signature * +cms_get ( struct cms_signature *sig ) { + ref_get ( &sig->refcnt ); + return sig; +} + +/** + * Drop reference to CMS signature + * + * @v sig CMS signature + */ +static inline __attribute__ (( always_inline )) void +cms_put ( struct cms_signature *sig ) { + ref_put ( &sig->refcnt ); +} + +extern int cms_signature ( const void *data, size_t len, + struct cms_signature **sig ); +extern int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len, + const char *name, time_t time, struct x509_root *root ); + +#endif /* _IPXE_CMS_H */ diff --git a/src/include/ipxe/console.h b/src/include/ipxe/console.h index 3bfa5033..e2bf4be9 100644 --- a/src/include/ipxe/console.h +++ b/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/src/include/ipxe/crypto.h b/src/include/ipxe/crypto.h index 9383c076..d7d42b66 100644 --- a/src/include/ipxe/crypto.h +++ b/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/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h index 06fb33bc..34b4d3fd 100644 --- a/src/include/ipxe/dhcp.h +++ b/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> @@ -351,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 @@ -458,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__ diff --git a/src/include/ipxe/drbg.h b/src/include/ipxe/drbg.h index a09d136d..6374e778 100644 --- a/src/include/ipxe/drbg.h +++ b/src/include/ipxe/drbg.h @@ -10,16 +10,28 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> +#include <ipxe/sha256.h> #include <ipxe/hmac_drbg.h> -/** Maximum security strength */ -#define DRBG_MAX_SECURITY_STRENGTH HMAC_DRBG_MAX_SECURITY_STRENGTH +/** 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 -/** Security strength */ -#define DRBG_SECURITY_STRENGTH HMAC_DRBG_SECURITY_STRENGTH +/** 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 +#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 @@ -39,6 +51,8 @@ struct drbg_state { struct hmac_drbg_state internal; /** Reseed required flag */ int reseed_required; + /** State is valid */ + int valid; }; /** @@ -58,7 +72,8 @@ static inline void drbg_instantiate_algorithm ( struct drbg_state *state, size_t entropy_len, const void *personal, size_t personal_len ) { - hmac_drbg_instantiate ( &state->internal, entropy, entropy_len, + hmac_drbg_instantiate ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ), + &state->internal, entropy, entropy_len, personal, personal_len ); } @@ -79,7 +94,8 @@ static inline void drbg_reseed_algorithm ( struct drbg_state *state, size_t entropy_len, const void *additional, size_t additional_len ) { - hmac_drbg_reseed ( &state->internal, entropy, entropy_len, + hmac_drbg_reseed ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ), + &state->internal, entropy, entropy_len, additional, additional_len ); } @@ -102,7 +118,8 @@ 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 ( &state->internal, additional, + return hmac_drbg_generate ( HMAC_DRBG_HASH ( HMAC_DRBG_ALGORITHM ), + &state->internal, additional, additional_len, data, len ); } diff --git a/src/include/ipxe/elf.h b/src/include/ipxe/elf.h index e5fed2f8..ec675c04 100644 --- a/src/include/ipxe/elf.h +++ b/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/src/include/ipxe/entropy.h b/src/include/ipxe/entropy.h index d9b70848..adf325e7 100644 --- a/src/include/ipxe/entropy.h +++ b/src/include/ipxe/entropy.h @@ -10,9 +10,72 @@ 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> -/** min-entropy per entropy sample +/** + * 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 @@ -20,71 +83,142 @@ FILE_LICENCE ( GPL2_OR_LATER ); * H_min = -log2 ( p_max ) * * where p_max is the probability of the most likely sample value. + * + * This must be a compile-time constant. */ -#define MIN_ENTROPY_PER_SAMPLE 0.16 - -/** Length of each entropy sample (in bits) */ -#define ENTROPY_SAMPLE_LEN_BITS 12 +double min_entropy_per_sample ( void ); /** - * Calculate entropy buffer size + * Get noise sample * - * @v entropy_bits Amount of entropy required, in bits - * @v min_len Minimum buffer size, in bytes - * @v max_len Maximum buffer size, in bytes - * @ret len Buffer size, in bytes + * @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. */ -static inline __attribute__ (( const, always_inline )) size_t -entropy_bufsize ( unsigned int entropy_bits, size_t min_len, size_t max_len ) { - unsigned int min_len_bits; - double min_samples; - double samples; - unsigned int samples_int; - unsigned int len_bits; - size_t len; +int get_noise ( noise_sample_t *noise ); - /* Sanity check */ - linker_assert ( MIN_ENTROPY_PER_SAMPLE <= ENTROPY_SAMPLE_LEN_BITS, +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 */ - samples = ( ( entropy_bits * 1.0 ) / MIN_ENTROPY_PER_SAMPLE ); - - /* Increase to minimum length if necessary */ - min_len_bits = ( min_len * 8 ); - min_samples = ( ( min_len_bits * 1.0 ) / ENTROPY_SAMPLE_LEN_BITS ); - if ( samples < min_samples ) - samples = min_samples; + 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. */ - samples_int = samples; - if ( samples_int < samples ) - samples_int++; - assert ( samples_int >= samples ); - - /* Calculate buffer length in bits */ - len_bits = ( samples_int * ENTROPY_SAMPLE_LEN_BITS ); - - /* Calculate buffer length in bytes (rounding up) */ - len = ( ( len_bits + 7 ) / 8 ); - - /* Check that buffer is within allowed lengths */ - linker_assert ( len >= min_len, entropy_bufsize_too_short ); - linker_assert ( len <= max_len, entropy_bufsize_too_long ); + 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 length is a compile-time constant. + * unless the calculated number of samples is a compile-time + * constant. */ - linker_assert ( __builtin_constant_p ( len ), - entropy_bufsize_not_constant ); + linker_assert ( __builtin_constant_p ( num_samples ), + num_samples_not_constant ); - return len; + /* (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; + } } -extern int get_entropy_input ( unsigned int entropy_bits, void *data, - size_t min_len, size_t max_len ); - #endif /* _IPXE_ENTROPY_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 8f6c3641..2109cf2f 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -60,6 +60,8 @@ 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_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) @@ -140,6 +142,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 ) @@ -161,7 +168,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 ) @@ -244,6 +251,15 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 ) /** @} */ diff --git a/src/include/ipxe/ethernet.h b/src/include/ipxe/ethernet.h index 7e49655a..3d2d462e 100644 --- a/src/include/ipxe/ethernet.h +++ b/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,12 @@ static inline int is_valid_ether_addr ( const void *addr ) { ( ! is_zero_ether_addr ( addr ) ) ); } +extern int eth_push ( struct net_device *netdev, struct io_buffer *iobuf, + const void *ll_dest, const void *ll_source, + uint16_t net_proto ); +extern int eth_pull ( struct net_device *netdev, struct io_buffer *iobuf, + const void **ll_dest, const void **ll_source, + uint16_t *net_proto, unsigned int *flags ); extern void eth_init_addr ( const void *hw_addr, void *ll_addr ); extern const char * eth_ntoa ( const void *ll_addr ); extern int eth_mc_hash ( unsigned int af, const void *net_addr, diff --git a/src/include/ipxe/features.h b/src/include/ipxe/features.h index 660015cd..498ec944 100644 --- a/src/include/ipxe/features.h +++ b/src/include/ipxe/features.h @@ -52,6 +52,7 @@ 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 */ /** @} */ diff --git a/src/include/ipxe/hash_df.h b/src/include/ipxe/hash_df.h new file mode 100644 index 00000000..607a4a61 --- /dev/null +++ b/src/include/ipxe/hash_df.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_HASH_DF_H +#define _IPXE_HASH_DF_H + +/** @file + * + * Hash-based derivation function (Hash_df) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/crypto.h> + +extern void hash_df ( struct digest_algorithm *hash, const void *input, + size_t input_len, void *output, size_t output_len ); + +#endif /* _IPXE_HASH_DF_H */ diff --git a/src/include/ipxe/hmac_drbg.h b/src/include/ipxe/hmac_drbg.h index c751cbcb..8dfd2924 100644 --- a/src/include/ipxe/hmac_drbg.h +++ b/src/include/ipxe/hmac_drbg.h @@ -10,48 +10,148 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> -#include <ipxe/sha1.h> +#include <ipxe/crypto.h> -/** Use SHA-1 as the underlying hash algorithm +/** Declare an HMAC_DRBG algorithm * - * HMAC_DRBG using SHA-1 is an Approved algorithm in ANS X9.82. + * @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_algorithm sha1_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 * - * 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). + * @v hmac_drbg HMAC_DRBG algorithm + * @ret max_security_strength Maxmimum security strength */ -#define HMAC_DRBG_MAX_SECURITY_STRENGTH 128 +#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 -/** Security strength +/** Output block length, in bits * - * For the sake of implementation simplicity, only a single security - * strength is supported, which is the maximum security strength - * supported by the algorithm. + * @v hmac_drbg HMAC_DRBG algorithm + * @ret out_len_bits Output block length, in bits */ -#define HMAC_DRBG_SECURITY_STRENGTH HMAC_DRBG_MAX_SECURITY_STRENGTH +#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 -/** Underlying hash algorithm output length (in bytes) */ -#define HMAC_DRBG_OUTLEN_BYTES SHA1_DIGEST_SIZE +/** 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_BYTES ( HMAC_DRBG_SECURITY_STRENGTH / 8 ) +#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 ( HMAC_DRBG_SECURITY_STRENGTH / 8 ) +#define HMAC_DRBG_MIN_ENTROPY_LEN_BYTES( security_strength ) \ + ( (security_strength) / 8 ) /** Maximum entropy input length * @@ -59,9 +159,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); * 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 2^32-1 bytes (i.e. 2^35-8 bits). + * We choose to allow up to 32 bytes. */ -#define HMAC_DRBG_MAX_ENTROPY_LEN_BYTES 0xffffffffUL +#define HMAC_DRBG_MAX_ENTROPY_LEN_BYTES 32 /** Maximum personalisation string length * @@ -95,19 +195,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Reseed interval * - * The maximum permitted reseed interval for HMAC_DRBG using SHA-1 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. + * 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 -/** Underlying hash algorithm context size (in bytes) */ -#define HMAC_DRBG_CTX_SIZE SHA1_CTX_SIZE - /** * HMAC_DRBG internal state * @@ -124,13 +221,13 @@ struct hmac_drbg_state { * "The value V of outlen bits, which is updated each time * another outlen bits of output are produced" */ - uint8_t value[HMAC_DRBG_OUTLEN_BYTES]; + 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_OUTLEN_BYTES]; + uint8_t key[HMAC_DRBG_MAX_OUTLEN_BYTES]; /** Reseed counter * * "A counter (reseed_counter) that indicates the number of @@ -140,13 +237,16 @@ struct hmac_drbg_state { unsigned int reseed_counter; }; -extern void hmac_drbg_instantiate ( struct hmac_drbg_state *state, +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 hmac_drbg_state *state, +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 hmac_drbg_state *state, +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 ); diff --git a/src/include/ipxe/http.h b/src/include/ipxe/http.h index d8f4ca5a..cf8c0c7f 100644 --- a/src/include/ipxe/http.h +++ b/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/src/include/ipxe/image.h b/src/include/ipxe/image.h index dbcd6d64..ac97137b 100644 --- a/src/include/ipxe/image.h +++ b/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,9 @@ struct image { /** Image is selected for execution */ #define IMAGE_SELECTED 0x0002 +/** Image is trusted */ +#define IMAGE_TRUSTED 0x0004 + /** An executable image type */ struct image_type { /** Name of this image type */ @@ -119,6 +122,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 +144,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 +155,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 +178,30 @@ static inline void image_put ( struct image *image ) { } /** - * Set image name + * Clear image command line * * @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_clear_cmdline ( struct image *image ) { + image_set_cmdline ( image, NULL ); +} + +/** + * Set image as trusted + * + * @v image Image + */ +static inline void image_trust ( struct image *image ) { + image->flags |= IMAGE_TRUSTED; +} + +/** + * Set image as untrusted + * + * @v image Image + */ +static inline void image_untrust ( struct image *image ) { + image->flags &= ~IMAGE_TRUSTED; } #endif /* _IPXE_IMAGE_H */ diff --git a/src/include/ipxe/iscsi.h b/src/include/ipxe/iscsi.h index 5d3d73b0..b4de793a 100644 --- a/src/include/ipxe/iscsi.h +++ b/src/include/ipxe/iscsi.h @@ -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/src/include/ipxe/lineconsole.h b/src/include/ipxe/lineconsole.h new file mode 100644 index 00000000..925c0acc --- /dev/null +++ b/src/include/ipxe/lineconsole.h @@ -0,0 +1,36 @@ +#ifndef _IPXE_LINECONSOLE_H +#define _IPXE_LINECONSOLE_H + +/** @file + * + * Line-based console + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/ansiesc.h> + +/** A line-based console */ +struct line_console { + /** Data buffer + * + * Must initially be filled with NULs + */ + char *buffer; + /** Current index within buffer */ + size_t index; + /** Length of buffer + * + * The final character of the buffer will only ever be used as + * a potential terminating NUL. + */ + size_t len; + /** ANSI escape sequence context */ + struct ansiesc_context ctx; +}; + +extern size_t line_putchar ( struct line_console *line, int character ); + +#endif /* _IPXE_LINECONSOLE_H */ diff --git a/src/include/ipxe/linux/linux_entropy.h b/src/include/ipxe/linux/linux_entropy.h new file mode 100644 index 00000000..bd89bd52 --- /dev/null +++ b/src/include/ipxe/linux/linux_entropy.h @@ -0,0 +1,32 @@ +#ifndef _IPXE_LINUX_ENTROPY_H +#define _IPXE_LINUX_ENTROPY_H + +/** @file + * + * iPXE entropy API for linux + * + */ + +FILE_LICENCE(GPL2_OR_LATER); + +#ifdef ENTROPY_LINUX +#define ENTROPY_PREFIX_linux +#else +#define ENTROPY_PREFIX_linux __linux_ +#endif + +/** + * min-entropy per sample + * + * @ret min_entropy min-entropy of each sample + */ +static inline __always_inline double +ENTROPY_INLINE ( linux, min_entropy_per_sample ) ( void ) { + + /* We read single bytes from /dev/random and assume that each + * contains full entropy. + */ + return 8; +} + +#endif /* _IPXE_LINUX_ENTROPY_H */ diff --git a/src/include/ipxe/linux/linux_time.h b/src/include/ipxe/linux/linux_time.h new file mode 100644 index 00000000..93a25773 --- /dev/null +++ b/src/include/ipxe/linux/linux_time.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_LINUX_TIME_H +#define _IPXE_LINUX_TIME_H + +/** @file + * + * Linux time source + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef TIME_LINUX +#define TIME_PREFIX_linux +#else +#define TIME_PREFIX_linux __linux_ +#endif + +#endif /* _IPXE_LINUX_TIME_H */ diff --git a/src/include/ipxe/list.h b/src/include/ipxe/list.h index 231383d1..b14a83d7 100644 --- a/src/include/ipxe/list.h +++ b/src/include/ipxe/list.h @@ -324,6 +324,19 @@ static inline void list_splice_tail_init ( struct list_head *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 * @@ -378,6 +391,32 @@ static inline void list_splice_tail_init ( 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 * diff --git a/src/include/ipxe/md5.h b/src/include/ipxe/md5.h index c3dfeb7e..860bc476 100644 --- a/src/include/ipxe/md5.h +++ b/src/include/ipxe/md5.h @@ -1,23 +1,72 @@ #ifndef _IPXE_MD5_H #define _IPXE_MD5_H +/** @file + * + * MD5 algorithm + * + */ + FILE_LICENCE ( GPL2_OR_LATER ); -struct digest_algorithm; - #include <stdint.h> +#include <ipxe/crypto.h> -#define MD5_DIGEST_SIZE 16 -#define MD5_BLOCK_WORDS 16 -#define MD5_HASH_WORDS 4 - -struct md5_ctx { - u32 hash[MD5_HASH_WORDS]; - u32 block[MD5_BLOCK_WORDS]; - u64 byte_count; +/** An MD5 digest */ +struct md5_digest { + /** Hash output */ + uint32_t h[4]; }; -#define MD5_CTX_SIZE sizeof ( struct md5_ctx ) +/** An MD5 data block */ +union md5_block { + /** Raw bytes */ + uint8_t byte[64]; + /** Raw dwords */ + uint32_t dword[16]; + /** Final block structure */ + struct { + /** Padding */ + uint8_t pad[56]; + /** Length in bits */ + uint64_t len; + } final; +}; + +/** MD5 digest and data block + * + * The order of fields within this structure is designed to minimise + * code size. + */ +struct md5_digest_data { + /** Digest of data already processed */ + struct md5_digest digest; + /** Accumulated data */ + union md5_block data; +} __attribute__ (( packed )); + +/** MD5 digest and data block */ +union md5_digest_data_dwords { + /** Digest and data block */ + struct md5_digest_data dd; + /** Raw dwords */ + uint32_t dword[ sizeof ( struct md5_digest_data ) / + sizeof ( uint32_t ) ]; +}; + +/** An MD5 context */ +struct md5_context { + /** Amount of accumulated data */ + size_t len; + /** Digest and accumulated data */ + union md5_digest_data_dwords ddd; +} __attribute__ (( packed )); + +/** MD5 context size */ +#define MD5_CTX_SIZE sizeof ( struct md5_context ) + +/** MD5 digest size */ +#define MD5_DIGEST_SIZE sizeof ( struct md5_digest ) extern struct digest_algorithm md5_algorithm; diff --git a/src/include/ipxe/menu.h b/src/include/ipxe/menu.h new file mode 100644 index 00000000..993b027e --- /dev/null +++ b/src/include/ipxe/menu.h @@ -0,0 +1,49 @@ +#ifndef _IPXE_MENU_H +#define _IPXE_MENU_H + +/** @file + * + * Menu selection + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/list.h> + +/** A menu */ +struct menu { + /** List of menus */ + struct list_head list; + /** Name */ + const char *name; + /** Title */ + const char *title; + /** Menu items */ + struct list_head items; +}; + +/** A menu item */ +struct menu_item { + /** List of menu items */ + struct list_head list; + /** Label */ + const char *label; + /** Text */ + const char *text; + /** Shortcut key */ + int shortcut; + /** Is default item */ + int is_default; +}; + +extern struct menu * create_menu ( const char *name, const char *title ); +extern struct menu_item * add_menu_item ( struct menu *menu, const char *label, + const char *text, int shortcut, + int is_default ); +extern void destroy_menu ( struct menu *menu ); +extern struct menu * find_menu ( const char *name ); +extern int show_menu ( struct menu *menu, unsigned int timeout_ms, + const char *select, struct menu_item **selected ); + +#endif /* _IPXE_MENU_H */ diff --git a/src/include/ipxe/mii.h b/src/include/ipxe/mii.h new file mode 100644 index 00000000..a33a31d9 --- /dev/null +++ b/src/include/ipxe/mii.h @@ -0,0 +1,86 @@ +#ifndef _IPXE_MII_H +#define _IPXE_MII_H + +/** @file + * + * Media Independent Interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <mii.h> +#include <ipxe/netdevice.h> + +struct mii_interface; + +/** MII interface operations */ +struct mii_operations { + /** + * Read from MII register + * + * @v mii MII interface + * @v reg Register address + * @ret data Data read, or negative error + */ + int ( * read ) ( struct mii_interface *mii, unsigned int reg ); + /** + * Write to MII register + * + * @v mii MII interface + * @v reg Register address + * @v data Data to write + * @ret rc Return status code + */ + int ( * write ) ( struct mii_interface *mii, unsigned int reg, + unsigned int data ); +}; + +/** An MII interface */ +struct mii_interface { + /** Interface operations */ + struct mii_operations *op; +}; + +/** + * Initialise MII interface + * + * @v mii MII interface + * @v op MII interface operations + */ +static inline __attribute__ (( always_inline )) void +mii_init ( struct mii_interface *mii, struct mii_operations *op ) { + mii->op = op; +} + +/** + * Read from MII register + * + * @v mii MII interface + * @v reg Register address + * @ret data Data read, or negative error + */ +static inline __attribute__ (( always_inline )) int +mii_read ( struct mii_interface *mii, unsigned int reg ) { + return mii->op->read ( mii, reg ); +} + +/** + * Write to MII register + * + * @v mii MII interface + * @v reg Register address + * @v data Data to write + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +mii_write ( struct mii_interface *mii, unsigned int reg, unsigned int data ) { + return mii->op->write ( mii, reg, data ); +} + +/** Maximum time to wait for a reset, in milliseconds */ +#define MII_RESET_MAX_WAIT_MS 500 + +extern int mii_reset ( struct mii_interface *mii ); + +#endif /* _IPXE_MII_H */ diff --git a/src/include/ipxe/null_entropy.h b/src/include/ipxe/null_entropy.h new file mode 100644 index 00000000..646d1a17 --- /dev/null +++ b/src/include/ipxe/null_entropy.h @@ -0,0 +1,52 @@ +#ifndef _IPXE_NULL_ENTROPY_H +#define _IPXE_NULL_ENTROPY_H + +/** @file + * + * Nonexistent entropy source + * + * This source provides no entropy and must NOT be used in a + * security-sensitive environment. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> + +#ifdef ENTROPY_NULL +#define ENTROPY_PREFIX_null +#else +#define ENTROPY_PREFIX_null __null_ +#endif + +static inline __always_inline int +ENTROPY_INLINE ( null, entropy_enable ) ( void ) { + /* Do nothing */ + return 0; +} + +static inline __always_inline void +ENTROPY_INLINE ( null, entropy_disable ) ( void ) { + /* Do nothing */ +} + +static inline __always_inline double +ENTROPY_INLINE ( null, min_entropy_per_sample ) ( void ) { + /* Actual amount of min-entropy is zero. To avoid + * division-by-zero errors and to allow compilation of + * entropy-consuming code, pretend to have 1 bit of entropy in + * each sample. + */ + return 1.0; +} + +static inline __always_inline int +ENTROPY_INLINE ( null, get_noise ) ( noise_sample_t *noise ) { + + /* All sample values are constant */ + *noise = 0x01; + + return 0; +} + +#endif /* _IPXE_NULL_ENTROPY_H */ diff --git a/src/include/ipxe/null_time.h b/src/include/ipxe/null_time.h new file mode 100644 index 00000000..2b72cdf5 --- /dev/null +++ b/src/include/ipxe/null_time.h @@ -0,0 +1,23 @@ +#ifndef _IPXE_NULL_TIME_H +#define _IPXE_NULL_TIME_H + +/** @file + * + * Nonexistent time source + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef TIME_NULL +#define TIME_PREFIX_null +#else +#define TIME_PREFIX_null __null_ +#endif + +static inline __always_inline time_t +TIME_INLINE ( null, time_now ) ( void ) { + return 0; +} + +#endif /* _IPXE_NULL_TIME_H */ diff --git a/src/include/ipxe/parseopt.h b/src/include/ipxe/parseopt.h index 8c456a64..b492a51e 100644 --- a/src/include/ipxe/parseopt.h +++ b/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,8 +117,9 @@ 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 ); diff --git a/src/include/ipxe/random_nz.h b/src/include/ipxe/random_nz.h new file mode 100644 index 00000000..6bb80d2a --- /dev/null +++ b/src/include/ipxe/random_nz.h @@ -0,0 +1,16 @@ +#ifndef _IPXE_RANDOM_NZ_H +#define _IPXE_RANDOM_NZ_H + +/** @file + * + * HMAC_DRBG algorithm + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> + +extern int get_random_nz ( void *data, size_t len ); + +#endif /* _IPXE_RANDOM_NZ_H */ diff --git a/src/include/ipxe/rbg.h b/src/include/ipxe/rbg.h new file mode 100644 index 00000000..9689142f --- /dev/null +++ b/src/include/ipxe/rbg.h @@ -0,0 +1,43 @@ +#ifndef _IPXE_RBG_H +#define _IPXE_RBG_H + +/** @file + * + * RBG mechanism + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/drbg.h> + +/** An RBG */ +struct random_bit_generator { + /** DRBG state */ + struct drbg_state state; +}; + +extern struct random_bit_generator rbg; + +/** + * Generate bits using RBG + * + * @v additional Additional input + * @v additional_len Length of additional input + * @v prediction_resist Prediction resistance is required + * @v data Output buffer + * @v len Length of output buffer + * @ret rc Return status code + * + * This is the RBG_Generate function defined in ANS X9.82 Part 4 + * (April 2011 Draft) Section 9.1.2.2. + */ +static inline int rbg_generate ( const void *additional, size_t additional_len, + int prediction_resist, void *data, + size_t len ) { + return drbg_generate ( &rbg.state, additional, additional_len, + prediction_resist, data, len ); +} + +#endif /* _IPXE_RBG_H */ diff --git a/src/include/ipxe/rootcert.h b/src/include/ipxe/rootcert.h new file mode 100644 index 00000000..6525df87 --- /dev/null +++ b/src/include/ipxe/rootcert.h @@ -0,0 +1,16 @@ +#ifndef _IPXE_ROOTCERT_H +#define _IPXE_ROOTCERT_H + +/** @file + * + * Root certificate store + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/x509.h> + +extern struct x509_root root_certificates; + +#endif /* _IPXE_ROOTCERT_H */ diff --git a/src/include/ipxe/rotate.h b/src/include/ipxe/rotate.h index 745d84e6..ba271ca7 100644 --- a/src/include/ipxe/rotate.h +++ b/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/src/include/ipxe/rsa.h b/src/include/ipxe/rsa.h index a080f9f0..1a5ad8ba 100644 --- a/src/include/ipxe/rsa.h +++ b/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> + +/** RSA digestAlgorithm sequence contents */ +#define RSA_DIGESTALGORITHM_CONTENTS( ... ) \ + ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__, \ + ASN1_NULL, 0x00 + +/** RSA digestAlgorithm sequence */ +#define RSA_DIGESTALGORITHM( ... ) \ + ASN1_SEQUENCE, \ + VA_ARG_COUNT ( RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ ) ), \ + RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ ) + +/** RSA digest prefix */ +#define RSA_DIGEST_PREFIX( digest_size ) \ + ASN1_OCTET_STRING, digest_size + +/** RSA digestInfo prefix */ +#define RSA_DIGESTINFO_PREFIX( digest_size, ... ) \ + ASN1_SEQUENCE, \ + ( VA_ARG_COUNT ( RSA_DIGESTALGORITHM ( __VA_ARGS__ ) ) + \ + VA_ARG_COUNT ( RSA_DIGEST_PREFIX ( digest_size ) ) + \ + digest_size ), \ + RSA_DIGESTALGORITHM ( __VA_ARGS__ ), \ + RSA_DIGEST_PREFIX ( digest_size ) + +/** An RSA digestInfo prefix */ +struct rsa_digestinfo_prefix { + /** Digest algorithm */ + struct digest_algorithm *digest; + /** Prefix */ + const void *data; + /** Length of prefix */ + size_t len; +}; + +/** RSA digestInfo prefix table */ +#define RSA_DIGESTINFO_PREFIXES \ + __table ( struct rsa_digestinfo_prefix, "rsa_digestinfo_prefixes" ) + +/** Declare an RSA digestInfo prefix */ +#define __rsa_digestinfo_prefix __table_entry ( RSA_DIGESTINFO_PREFIXES, 01 ) + +/** An RSA context */ +struct rsa_context { + /** Allocated memory */ + void *dynamic; + /** Modulus */ + bigint_element_t *modulus0; + /** Modulus size */ + unsigned int size; + /** Modulus length */ + size_t max_len; + /** Exponent */ + bigint_element_t *exponent0; + /** Exponent size */ + unsigned int exponent_size; + /** Input buffer */ + bigint_element_t *input0; + /** Output buffer */ + bigint_element_t *output0; + /** Temporary working space for modular exponentiation */ + void *tmp; +}; extern struct pubkey_algorithm rsa_algorithm; -#include "crypto/axtls/crypto.h" - #endif /* _IPXE_RSA_H */ diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index f88a2b97..d0a142fa 100644 --- a/src/include/ipxe/settings.h +++ b/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 ); @@ -273,6 +275,8 @@ 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 ); @@ -283,6 +287,7 @@ extern int fetchf_named_setting ( const char *name, char *name_buf, 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; @@ -353,22 +358,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 * diff --git a/src/include/ipxe/sha1.h b/src/include/ipxe/sha1.h index 9b6f5514..a97035ec 100644 --- a/src/include/ipxe/sha1.h +++ b/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; +}; + +/** SHA-1 digest and data block + * + * The order of fields within this structure is designed to minimise + * code size. + */ +struct sha1_digest_data { + /** Digest of data already processed */ + struct sha1_digest digest; + /** Accumulated data */ + union sha1_block data; +} __attribute__ (( packed )); + +/** SHA-1 digest and data block */ +union sha1_digest_data_dwords { + /** Digest and data block */ + struct sha1_digest_data dd; + /** Raw dwords */ + uint32_t dword[ sizeof ( struct sha1_digest_data ) / + sizeof ( uint32_t ) ]; +}; + +/** An SHA-1 context */ +struct sha1_context { + /** Amount of accumulated data */ + size_t len; + /** Digest and accumulated data */ + union sha1_digest_data_dwords ddd; +} __attribute__ (( packed )); + +/** SHA-1 context size */ +#define SHA1_CTX_SIZE sizeof ( struct sha1_context ) + +/** SHA-1 digest size */ +#define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest ) extern struct digest_algorithm sha1_algorithm; -/* SHA1-wrapping functions defined in sha1extra.c: */ - -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 ); - -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/src/include/ipxe/sha256.h b/src/include/ipxe/sha256.h new file mode 100644 index 00000000..9aa9f3e5 --- /dev/null +++ b/src/include/ipxe/sha256.h @@ -0,0 +1,73 @@ +#ifndef _IPXE_SHA256_H +#define _IPXE_SHA256_H + +/** @file + * + * SHA-256 algorithm + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/crypto.h> + +/** An SHA-256 digest */ +struct sha256_digest { + /** Hash output */ + uint32_t h[8]; +}; + +/** An SHA-256 data block */ +union sha256_block { + /** Raw bytes */ + uint8_t byte[64]; + /** Raw dwords */ + uint32_t dword[16]; + /** Final block structure */ + struct { + /** Padding */ + uint8_t pad[56]; + /** Length in bits */ + uint64_t len; + } final; +}; + +/** SHA-256 digest and data block + * + * The order of fields within this structure is designed to minimise + * code size. + */ +struct sha256_digest_data { + /** Digest of data already processed */ + struct sha256_digest digest; + /** Accumulated data */ + union sha256_block data; +} __attribute__ (( packed )); + +/** SHA-256 digest and data block */ +union sha256_digest_data_dwords { + /** Digest and data block */ + struct sha256_digest_data dd; + /** Raw dwords */ + uint32_t dword[ sizeof ( struct sha256_digest_data ) / + sizeof ( uint32_t ) ]; +}; + +/** An SHA-256 context */ +struct sha256_context { + /** Amount of accumulated data */ + size_t len; + /** Digest and accumulated data */ + union sha256_digest_data_dwords ddd; +} __attribute__ (( packed )); + +/** SHA-256 context size */ +#define SHA256_CTX_SIZE sizeof ( struct sha256_context ) + +/** SHA-256 digest size */ +#define SHA256_DIGEST_SIZE sizeof ( struct sha256_digest ) + +extern struct digest_algorithm sha256_algorithm; + +#endif /* _IPXE_SHA256_H */ diff --git a/src/include/ipxe/syslog.h b/src/include/ipxe/syslog.h index 25edc6b0..035ca670 100644 --- a/src/include/ipxe/syslog.h +++ b/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,17 +20,17 @@ 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) ) diff --git a/src/include/ipxe/threewire.h b/src/include/ipxe/threewire.h index 135ef56a..b5513ecd 100644 --- a/src/include/ipxe/threewire.h +++ b/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/src/include/ipxe/time.h b/src/include/ipxe/time.h new file mode 100644 index 00000000..673fe098 --- /dev/null +++ b/src/include/ipxe/time.h @@ -0,0 +1,59 @@ +#ifndef _IPXE_TIME_H +#define _IPXE_TIME_H + +/** @file + * + * Time source + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <sys/time.h> +#include <ipxe/api.h> +#include <config/time.h> + +/** + * Calculate static inline time API function name + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @ret _subsys_func Subsystem API function + */ +#define TIME_INLINE( _subsys, _api_func ) \ + SINGLE_API_INLINE ( TIME_PREFIX_ ## _subsys, _api_func ) + +/** + * Provide a time API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @v _func Implementing function + */ +#define PROVIDE_TIME( _subsys, _api_func, _func ) \ + PROVIDE_SINGLE_API ( TIME_PREFIX_ ## _subsys, _api_func, _func ) + +/** + * Provide a static inline time API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + */ +#define PROVIDE_TIME_INLINE( _subsys, _api_func ) \ + PROVIDE_SINGLE_API_INLINE ( TIME_PREFIX_ ## _subsys, _api_func ) + +/* Include all architecture-independent time API headers */ +#include <ipxe/null_time.h> +#include <ipxe/linux/linux_time.h> + +/* Include all architecture-dependent time API headers */ +#include <bits/time.h> + +/** + * Get current time in seconds + * + * @ret time Time, in seconds + */ +time_t time_now ( void ); + +#endif /* _IPXE_TIME_H */ diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 94cd322c..7de1f19e 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -16,6 +16,7 @@ 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> /** A TLS header */ @@ -40,6 +41,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 +77,20 @@ 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 extension types */ +#define TLS_SERVER_NAME 0 +#define TLS_SERVER_NAME_HOST_NAME 0 /** TLS RX state machine state */ enum tls_rx_state { @@ -80,18 +98,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 +117,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 +138,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 +172,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 +224,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 has finished security negotiation */ + unsigned int client_finished; + /** Server has finished security negotiation */ + unsigned int server_finished; /** TX sequence number */ uint64_t tx_seq; - /** TX state */ - enum tls_tx_state tx_state; + /** TX pending transmissions */ + unsigned int tx_pending; /** TX process */ struct process process; @@ -181,7 +264,7 @@ struct tls_session { void *rx_data; }; -extern int add_tls ( struct interface *xfer, +extern int add_tls ( struct interface *xfer, const char *name, struct interface **next ); #endif /* _IPXE_TLS_H */ diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 2f3c2248..5de56b94 100644 --- a/src/include/ipxe/uuid.h +++ b/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/src/include/ipxe/validator.h b/src/include/ipxe/validator.h new file mode 100644 index 00000000..23bdab42 --- /dev/null +++ b/src/include/ipxe/validator.h @@ -0,0 +1,17 @@ +#ifndef _IPXE_VALIDATOR_H +#define _IPXE_VALIDATOR_H + +/** @file + * + * Certificate validator + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/interface.h> +#include <ipxe/x509.h> + +extern int create_validator ( struct interface *job, struct x509_chain *chain ); + +#endif /* _IPXE_VALIDATOR_H */ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 37c5a4ee..8753bb05 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -10,32 +10,366 @@ 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 bit string */ +struct x509_bit_string { + /** Data */ + const void *data; + /** Length */ + size_t len; + /** Unused bits at end of data */ + unsigned int unused; +}; -/** 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; +/** An X.509 serial number */ +struct x509_serial { + /** Raw serial number */ + struct asn1_cursor raw; +}; + +/** An X.509 issuer */ +struct x509_issuer { + /** Raw issuer */ + struct asn1_cursor raw; +}; + +/** An X.509 time */ +struct x509_time { + /** Seconds since the Epoch */ + time_t time; +}; + +/** An X.509 certificate validity period */ +struct x509_validity { + /** Not valid before */ + struct x509_time not_before; + /** Not valid after */ + struct x509_time not_after; +}; + +/** An X.509 certificate public key */ +struct x509_public_key { + /** Raw public key */ + struct asn1_cursor raw; + /** Public key algorithm */ + struct asn1_algorithm *algorithm; +}; + +/** 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 x509_bit_string value; +}; + +/** An X.509 certificate basic constraints set */ +struct x509_basic_constraints { + /** Subject is a CA */ + int ca; + /** Path length */ + unsigned int path_len; +}; + +/** Unlimited path length + * + * We use -2U, since this quantity represents one *fewer* than the + * maximum number of remaining certificates in a chain. + */ +#define X509_PATH_LEN_UNLIMITED -2U + +/** An X.509 certificate key usage */ +struct x509_key_usage { + /** Key usage extension is present */ + int present; + /** Usage bits */ + unsigned int bits; +}; + +/** X.509 certificate key usage bits */ +enum x509_key_usage_bits { + X509_DIGITAL_SIGNATURE = 0x0080, + X509_NON_REPUDIATION = 0x0040, + X509_KEY_ENCIPHERMENT = 0x0020, + X509_DATA_ENCIPHERMENT = 0x0010, + X509_KEY_AGREEMENT = 0x0008, + X509_KEY_CERT_SIGN = 0x0004, + X509_CRL_SIGN = 0x0002, + X509_ENCIPHER_ONLY = 0x0001, + X509_DECIPHER_ONLY = 0x8000, +}; + +/** An X.509 certificate extended key usage */ +struct x509_extended_key_usage { + /** Usage bits */ + unsigned int bits; +}; + +/** X.509 certificate extended key usage bits + * + * Extended key usages are identified by OID; these bits are purely an + * internal definition. + */ +enum x509_extended_key_usage_bits { + X509_CODE_SIGNING = 0x0001, +}; + +/** X.509 certificate OCSP responder */ +struct x509_ocsp_responder { + /** URI */ + char *uri; +}; + +/** 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 struct x509_chain * x509_alloc_chain ( void ); +extern int x509_append ( struct x509_chain *chain, + struct x509_certificate *cert ); +extern int x509_append_raw ( struct x509_chain *chain, const void *data, + size_t len ); +extern int x509_auto_append ( struct x509_chain *chain, + struct x509_chain *certs ); +extern int x509_validate_chain ( struct x509_chain *chain, time_t time, + struct x509_root *root ); + +/* Functions exposed only for unit testing */ +extern int x509_check_issuer ( struct x509_certificate *cert, + struct x509_certificate *issuer ); +extern void x509_fingerprint ( struct x509_certificate *cert, + struct digest_algorithm *digest, + void *fingerprint ); +extern int x509_check_root ( struct x509_certificate *cert, + struct x509_root *root ); +extern int x509_check_time ( struct x509_certificate *cert, time_t time ); + +/** + * Invalidate X.509 certificate + * + * @v cert X.509 certificate + */ +static inline void x509_invalidate ( struct x509_certificate *cert ) { + cert->valid = 0; + cert->path_remaining = 0; +} + +/** + * Invalidate X.509 certificate chain + * + * @v chain X.509 certificate chain + */ +static inline void x509_invalidate_chain ( struct x509_chain *chain ) { + struct x509_link *link; + + list_for_each_entry ( link, &chain->links, list ) + x509_invalidate ( link->cert ); +} #endif /* _IPXE_X509_H */ diff --git a/src/include/ipxe/xferbuf.h b/src/include/ipxe/xferbuf.h new file mode 100644 index 00000000..2ca871e5 --- /dev/null +++ b/src/include/ipxe/xferbuf.h @@ -0,0 +1,31 @@ +#ifndef _IPXE_XFERBUF_H +#define _IPXE_XFERBUF_H + +/** @file + * + * Data transfer buffer + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/iobuf.h> +#include <ipxe/xfer.h> + +/** A data transfer buffer */ +struct xfer_buffer { + /** Data */ + void *data; + /** Size of data */ + size_t len; + /** Current offset within data */ + size_t pos; +}; + +extern void xferbuf_done ( struct xfer_buffer *xferbuf ); +extern int xferbuf_deliver ( struct xfer_buffer *xferbuf, + struct io_buffer *iobuf, + struct xfer_metadata *meta ); + +#endif /* _IPXE_XFERBUF_H */ diff --git a/src/include/linux_api.h b/src/include/linux_api.h index 066cdd30..94dc991f 100644 --- a/src/include/linux_api.h +++ b/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/src/include/mii.h b/src/include/mii.h index 2baff2f1..e2afef85 100644 --- a/src/include/mii.h +++ b/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 + * + * Media Independent Interface constants + * + * Extracted from Linux's include/linux/mii.h * * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) * - * Copied Form Linux 2.4.25 an unneeded items removed by: - * Timothy Legge (timlegge at etherboot dot org) - * - * 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_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_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_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_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/src/include/stdarg.h b/src/include/stdarg.h index 78b261ae..f317238a 100644 --- a/src/include/stdarg.h +++ b/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/src/include/stdio.h b/src/include/stdio.h index 84181f0a..91840af5 100644 --- a/src/include/stdio.h +++ b/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/src/include/stdlib.h b/src/include/stdlib.h index 19a7c8e0..3d30858f 100644 --- a/src/include/stdlib.h +++ b/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/src/include/sys/time.h b/src/include/sys/time.h index 21fb7e99..6c9b7421 100644 --- a/src/include/sys/time.h +++ b/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/src/include/syslog.h b/src/include/syslog.h new file mode 100644 index 00000000..93f32f86 --- /dev/null +++ b/src/include/syslog.h @@ -0,0 +1,100 @@ +#ifndef _SYSLOG_H +#define _SYSLOG_H + +/** @file + * + * System logger + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdarg.h> +#include <ipxe/ansiesc.h> +#include <config/console.h> + +/** + * @defgroup syslogpri Syslog priorities + * + * These values are chosen to match those used in the syslog network + * protocol (RFC 5424). + * + * @{ + */ + +/** Emergency: system is unusable */ +#define LOG_EMERG 0 + +/** Alert: action must be taken immediately */ +#define LOG_ALERT 1 + +/** Critical: critical conditions */ +#define LOG_CRIT 2 + +/** Error: error conditions */ +#define LOG_ERR 3 + +/** Warning: warning conditions */ +#define LOG_WARNING 4 + +/** Notice: normal but significant conditions */ +#define LOG_NOTICE 5 + +/** Informational: informational messages */ +#define LOG_INFO 6 + +/** Debug: debug-level messages */ +#define LOG_DEBUG 7 + +/** @} */ + +/** Do not log any messages */ +#define LOG_NONE -1 + +/** Log all messages */ +#define LOG_ALL LOG_DEBUG + +extern void log_vprintf ( const char *fmt, va_list args ); + +extern void __attribute__ (( format ( printf, 1, 2 ) )) +log_printf ( const char *fmt, ... ); + +/** ANSI private escape sequence to set syslog priority + * + * @v priority Priority + */ +#define SYSLOG_SET_PRIORITY( priority ) \ + "\033[" #priority "p" + +/** ANSI private escape sequence to clear syslog priority */ +#define SYSLOG_CLEAR_PRIORITY "\033[p" + +/** + * Write message to system log + * + * @v priority Message priority + * @v fmt Format string + * @v ... Arguments + */ +#define vsyslog( priority, fmt, args ) do { \ + if ( (priority) <= LOG_LEVEL ) { \ + log_vprintf ( SYSLOG_SET_PRIORITY ( priority ) fmt \ + SYSLOG_CLEAR_PRIORITY, (args) ); \ + } \ + } while ( 0 ) + +/** + * Write message to system log + * + * @v priority Message priority + * @v fmt Format string + * @v ... Arguments + */ +#define syslog( priority, fmt, ... ) do { \ + if ( (priority) <= LOG_LEVEL ) { \ + log_printf ( SYSLOG_SET_PRIORITY ( priority ) fmt \ + SYSLOG_CLEAR_PRIORITY, ##__VA_ARGS__ ); \ + } \ + } while ( 0 ) + +#endif /* _SYSLOG_H */ diff --git a/src/include/time.h b/src/include/time.h index 6ea927c3..bc73af4c 100644 --- a/src/include/time.h +++ b/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/src/include/usr/imgmgmt.h b/src/include/usr/imgmgmt.h index 71d587ba..8db5c978 100644 --- a/src/include/usr/imgmgmt.h +++ b/src/include/usr/imgmgmt.h @@ -11,41 +11,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/image.h> -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/src/include/usr/imgtrust.h b/src/include/usr/imgtrust.h new file mode 100644 index 00000000..f47105af --- /dev/null +++ b/src/include/usr/imgtrust.h @@ -0,0 +1,17 @@ +#ifndef _USR_IMGTRUST_H +#define _USR_IMGTRUST_H + +/** @file + * + * Image trust management + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <ipxe/image.h> + +extern int imgverify ( struct image *image, struct image *signature, + const char *name ); + +#endif /* _USR_IMGTRUST_H */ diff --git a/src/interface/efi/efi_console.c b/src/interface/efi/efi_console.c index 1303a427..6b612438 100644 --- a/src/interface/efi/efi_console.c +++ b/src/interface/efi/efi_console.c @@ -23,6 +23,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 +49,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 +280,5 @@ struct console_driver efi_console __console_driver = { .putchar = efi_putchar, .getchar = efi_getchar, .iskey = efi_iskey, + .usage = CONSOLE_EFI, }; diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 4c499826..4df221c5 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -1282,8 +1282,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" ) ); } /** diff --git a/src/interface/linux/linux_console.c b/src/interface/linux/linux_console.c index aeb7c661..5105eaa9 100644 --- a/src/interface/linux/linux_console.c +++ b/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/src/interface/linux/linux_entropy.c b/src/interface/linux/linux_entropy.c new file mode 100644 index 00000000..d82aabaa --- /dev/null +++ b/src/interface/linux/linux_entropy.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Linux entropy source + * + */ + +#include <stdint.h> +#include <errno.h> +#include <linux_api.h> +#include <ipxe/entropy.h> + +/** Entropy source filename */ +static const char entropy_filename[] = "/dev/random"; + +/** Entropy source file handle */ +static int entropy_fd; + +/** + * Enable entropy gathering + * + * @ret rc Return status code + */ +static int linux_entropy_enable ( void ) { + + /* Open entropy source */ + entropy_fd = linux_open ( entropy_filename, O_RDONLY ); + if ( entropy_fd < 0 ) { + DBGC ( &entropy_fd, "ENTROPY could not open %s: %s\n", + entropy_filename, linux_strerror ( linux_errno ) ); + return entropy_fd; + } + + return 0; +} + +/** + * Disable entropy gathering + * + */ +static void linux_entropy_disable ( void ) { + + /* Close entropy source */ + linux_close ( entropy_fd ); +} + +/** + * Get noise sample + * + * @ret noise Noise sample + * @ret rc Return status code + */ +static int linux_get_noise ( noise_sample_t *noise ) { + uint8_t byte; + ssize_t len; + + /* Read a single byte from entropy source */ + len = linux_read ( entropy_fd, &byte, sizeof ( byte ) ); + if ( len < 0 ) { + DBGC ( &entropy_fd, "ENTROPY could not read from %s: %s\n", + entropy_filename, linux_strerror ( linux_errno ) ); + return len; + } + if ( len == 0 ) { + DBGC ( &entropy_fd, "ENTROPY EOF on reading from %s: %s\n", + entropy_filename, linux_strerror ( linux_errno ) ); + return -EPIPE; + } + *noise = byte; + + return 0; +} + +PROVIDE_ENTROPY_INLINE ( linux, min_entropy_per_sample ); +PROVIDE_ENTROPY ( linux, entropy_enable, linux_entropy_enable ); +PROVIDE_ENTROPY ( linux, entropy_disable, linux_entropy_disable ); +PROVIDE_ENTROPY ( linux, get_noise, linux_get_noise ); diff --git a/src/interface/linux/linux_time.c b/src/interface/linux/linux_time.c new file mode 100644 index 00000000..6d722aad --- /dev/null +++ b/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/src/net/80211/wpa.c b/src/net/80211/wpa.c index 38ddb911..45def8c1 100644 --- a/src/net/80211/wpa.c +++ b/src/net/80211/wpa.c @@ -29,9 +29,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 +516,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/src/net/80211/wpa_ccmp.c b/src/net/80211/wpa_ccmp.c index 89bb36fd..38fd199f 100644 --- a/src/net/80211/wpa_ccmp.c +++ b/src/net/80211/wpa_ccmp.c @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/crypto.h> #include <ipxe/hmac.h> diff --git a/src/net/80211/wpa_psk.c b/src/net/80211/wpa_psk.c index 780738e7..c88f556e 100644 --- a/src/net/80211/wpa_psk.c +++ b/src/net/80211/wpa_psk.c @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/sha1.h> #include <ipxe/wpa.h> diff --git a/src/net/80211/wpa_tkip.c b/src/net/80211/wpa_tkip.c index 0a94df07..871666ee 100644 --- a/src/net/80211/wpa_tkip.c +++ b/src/net/80211/wpa_tkip.c @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <ipxe/net80211.h> #include <ipxe/crypto.h> #include <ipxe/hmac.h> @@ -543,15 +544,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/src/net/arp.c b/src/net/arp.c index fd1ce02d..4283b669 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdint.h> +#include <stdlib.h> #include <string.h> #include <byteswap.h> #include <errno.h> @@ -26,6 +27,10 @@ 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/arp.h> /** @file @@ -38,104 +43,263 @@ 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 { + /** 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 - * - * This is a global cache, covering all network interfaces, - * network-layer protocols and link-layer protocols. - */ -#define NUM_ARP_ENTRIES 4 - /** The ARP cache */ -static struct arp_entry arp_table[NUM_ARP_ENTRIES]; -#define arp_table_end &arp_table[NUM_ARP_ENTRIES] - -static unsigned int next_new_arp_entry = 0; +static LIST_HEAD ( arp_entries ); struct net_protocol arp_protocol __net_protocol; +static void arp_expired ( struct retry_timer *timer, int over ); + +/** + * Create ARP cache entry + * + * @v netdev Network device + * @v net_protocol Network-layer protocol + * @v net_dest Destination network-layer address + * @v net_source Source network-layer address + * @ret arp ARP cache entry, or NULL if allocation failed + */ +static struct arp_entry * arp_create ( struct net_device *netdev, + struct net_protocol *net_protocol, + const void *net_dest, + const void *net_source ) { + struct arp_entry *arp; + + /* Allocate entry and add to cache */ + arp = zalloc ( sizeof ( *arp ) ); + if ( ! arp ) + return NULL; + + /* Initialise entry and add to cache */ + arp->netdev = netdev_get ( netdev ); + arp->net_protocol = net_protocol; + memcpy ( arp->net_dest, net_dest, + net_protocol->net_addr_len ); + memcpy ( arp->net_source, net_source, + net_protocol->net_addr_len ); + timer_init ( &arp->timer, arp_expired, NULL ); + arp->timer.min_timeout = ARP_MIN_TIMEOUT; + arp->timer.max_timeout = ARP_MAX_TIMEOUT; + INIT_LIST_HEAD ( &arp->tx_queue ); + list_add ( &arp->list, &arp_entries ); + + /* Start timer running to trigger initial transmission */ + start_timer_nodelay ( &arp->timer ); + + DBGC ( arp, "ARP %p %s %s %s created\n", arp, netdev->name, + net_protocol->name, net_protocol->ntoa ( net_dest ) ); + return arp; +} + /** * Find entry in the ARP cache * - * @v 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; + struct io_buffer *tmp; + + /* Stop timer */ + stop_timer ( &arp->timer ); + + /* Discard any outstanding I/O buffers */ + list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) { + DBGC2 ( arp, "ARP %p %s %s %s discarding deferred packet: " + "%s\n", arp, netdev->name, net_protocol->name, + net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) ); + list_del ( &iobuf->list ); + netdev_tx_err ( arp->netdev, iobuf, rc ); + } + + DBGC ( arp, "ARP %p %s %s %s destroyed: %s\n", arp, netdev->name, + net_protocol->name, net_protocol->ntoa ( arp->net_dest ), + strerror ( rc ) ); + + /* Drop reference to network device, remove from cache and free */ + netdev_put ( arp->netdev ); + list_del ( &arp->list ); + free ( arp ); +} + +/** + * Test if ARP cache entry has a valid link-layer address + * + * @v arp ARP cache entry + * @ret resolved ARP cache entry is resolved + */ +static inline int arp_resolved ( struct arp_entry *arp ) { + return ( ! timer_running ( &arp->timer ) ); +} + +/** + * Transmit packet, determining link-layer address via ARP + * + * @v iobuf I/O buffer * @v netdev Network device * @v net_protocol Network-layer protocol - * @v 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 - * - * 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. - * - * 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. */ -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 ) { +int arp_tx ( struct io_buffer *iobuf, struct net_device *netdev, + struct net_protocol *net_protocol, const void *net_dest, + const void *net_source, const void *ll_source ) { + struct arp_entry *arp; + + /* Find or create ARP cache entry */ + arp = arp_find ( netdev, net_protocol, net_dest ); + if ( ! arp ) { + arp = arp_create ( netdev, net_protocol, net_dest, + net_source ); + if ( ! arp ) + return -ENOMEM; + } + + /* If a link-layer address is available then transmit + * immediately, otherwise queue for later transmission. + */ + if ( arp_resolved ( arp ) ) { + return net_tx ( iobuf, netdev, net_protocol, arp->ll_dest, + ll_source ); + } else { + DBGC2 ( arp, "ARP %p %s %s %s deferring packet\n", + arp, netdev->name, net_protocol->name, + net_protocol->ntoa ( net_dest ) ); + list_add_tail ( &iobuf->list, &arp->tx_queue ); + return -EAGAIN; + } +} + +/** + * Update ARP cache entry + * + * @v arp ARP cache entry + * @v ll_dest Destination link-layer address + */ +static void arp_update ( struct arp_entry *arp, const void *ll_dest ) { + struct net_device *netdev = arp->netdev; struct ll_protocol *ll_protocol = netdev->ll_protocol; - const struct arp_entry *arp; + struct net_protocol *net_protocol = arp->net_protocol; + struct io_buffer *iobuf; + struct io_buffer *tmp; + int rc; + + DBGC ( arp, "ARP %p %s %s %s updated => %s\n", arp, netdev->name, + net_protocol->name, net_protocol->ntoa ( arp->net_dest ), + ll_protocol->ntoa ( ll_dest ) ); + + /* Fill in link-layer address */ + memcpy ( arp->ll_dest, ll_dest, ll_protocol->ll_addr_len ); + + /* Stop retransmission timer */ + stop_timer ( &arp->timer ); + + /* Transmit any packets in queue */ + list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) { + DBGC2 ( arp, "ARP %p %s %s %s transmitting deferred packet\n", + arp, netdev->name, net_protocol->name, + net_protocol->ntoa ( arp->net_dest ) ); + list_del ( &iobuf->list ); + if ( ( rc = net_tx ( iobuf, netdev, net_protocol, ll_dest, + netdev->ll_addr ) ) != 0 ) { + DBGC ( arp, "ARP %p could not transmit deferred " + "packet: %s\n", arp, strerror ( rc ) ); + /* Ignore error and continue */ + } + } +} + +/** + * Handle ARP timer expiry + * + * @v timer Retry timer + * @v fail Failure indicator + */ +static void arp_expired ( struct retry_timer *timer, int fail ) { + struct arp_entry *arp = container_of ( timer, struct arp_entry, timer ); + struct net_device *netdev = arp->netdev; + struct ll_protocol *ll_protocol = netdev->ll_protocol; + struct net_protocol *net_protocol = arp->net_protocol; struct io_buffer *iobuf; struct arphdr *arphdr; int rc; - /* 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 +312,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; + } } /** @@ -188,12 +353,6 @@ static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) { * @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, @@ -204,71 +363,68 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev, 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 ) ); - 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 ) ); } - /* See if we own the target protocol address */ - if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0) - goto done; - - /* Create new ARP table entry if necessary */ - if ( ( arphdr->ar_op == htons ( ARPOP_REPLY ) ) && (! 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 ) ); + /* See if we have an entry for this sender, and update it if so */ + arp = arp_find ( netdev, net_protocol, arp_sender_pa ( arphdr ) ); + if ( arp ) { + arp_update ( arp, arp_sender_ha ( arphdr ) ); } /* If it's not a request, there's nothing more to do */ - if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) ) + if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) ) { + rc = 0; goto done; + } + + /* See if we own the target protocol address */ + if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0){ + rc = 0; + goto done; + } /* Change request to a reply */ - 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; } /** @@ -290,3 +446,59 @@ 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 */ + list_for_each_entry_reverse ( arp, &arp_entries, list ) { + arp_destroy ( arp, -ENOBUFS ); + return 1; + } + + return 0; +} + +/** ARP cache discarder */ +struct cache_discarder arp_cache_discarder __cache_discarder = { + .discard = arp_discard, +}; diff --git a/src/net/ethernet.c b/src/net/ethernet.c index c63fd9bc..a842bc11 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -50,9 +50,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 */ @@ -74,10 +74,9 @@ static int eth_push ( struct net_device *netdev __unused, * @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, - unsigned int *flags ) { +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 */ diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 99c2580e..08249d41 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -281,35 +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 netmask IPv4 subnet mask - * @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 in_addr netmask, struct net_device *netdev, - uint8_t *ll_dest ) { - struct ll_protocol *ll_protocol = netdev->ll_protocol; - - if ( ( ( dest.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0 ) { - /* 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 * @@ -335,7 +306,8 @@ static int ipv4_tx ( struct io_buffer *iobuf, struct ipv4_miniroute *miniroute; struct in_addr next_hop; struct in_addr netmask = { .s_addr = 0 }; - uint8_t ll_dest[MAX_LL_ADDR_LEN]; + uint8_t ll_dest_buf[MAX_LL_ADDR_LEN]; + const void *ll_dest; int rc; /* Fill up the IP header, except source address */ @@ -373,16 +345,6 @@ static int ipv4_tx ( struct io_buffer *iobuf, ( ( netdev->rx_stats.bad & 0xf ) << 4 ) | ( ( netdev->rx_stats.good & 0xf ) << 0 ) ); - /* Determine link-layer destination address */ - if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netmask, netdev, - ll_dest ) ) != 0 ) { - DBGC ( sin_dest->sin_addr, "IPv4 has no link-layer address for " - "%s: %s\n", inet_ntoa ( next_hop ), strerror ( rc ) ); - /* Record error for diagnosis */ - netdev_tx_err ( netdev, iob_disown ( iobuf ), rc ); - goto err; - } - /* Fix up checksums */ if ( trans_csum ) *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum ); @@ -395,12 +357,42 @@ static int ipv4_tx ( struct io_buffer *iobuf, 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 ) { - DBGC ( sin_dest->sin_addr, "IPv4 could not transmit packet " - "via %s: %s\n", netdev->name, strerror ( rc ) ); - return rc; + /* 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; diff --git a/src/net/mii.c b/src/net/mii.c deleted file mode 100644 index dbaecf11..00000000 --- a/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/src/net/tcp.c b/src/net/tcp.c index 58a4155e..6ea55b36 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -7,6 +7,7 @@ #include <ipxe/timer.h> #include <ipxe/iobuf.h> #include <ipxe/malloc.h> +#include <ipxe/init.h> #include <ipxe/retry.h> #include <ipxe/refcnt.h> #include <ipxe/xfer.h> @@ -343,6 +344,7 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { /* 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 ); @@ -1143,7 +1145,7 @@ static int tcp_rx ( struct io_buffer *iobuf, 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 ); @@ -1262,6 +1264,26 @@ struct cache_discarder tcp_cache_discarder __cache_discarder = { .discard = tcp_discard, }; +/** + * Shut down all TCP connections + * + */ +static void tcp_shutdown ( int booting __unused ) { + struct tcp_connection *tcp; + + while ( ( tcp = list_first_entry ( &tcp_conns, struct tcp_connection, + list ) ) != NULL ) { + tcp->tcp_state = TCP_CLOSED; + tcp_dump_state ( tcp ); + tcp_close ( tcp, -ECANCELED ); + } +} + +/** TCP shutdown function */ +struct startup_fn tcp_startup_fn __startup_fn ( STARTUP_EARLY ) = { + .shutdown = tcp_shutdown, +}; + /*************************************************************************** * * Data transfer interface diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c index cee75133..0c038885 100644 --- a/src/net/tcp/http.c +++ b/src/net/tcp/http.c @@ -25,869 +25,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/blockdev.h> -#include <ipxe/acpi.h> #include <ipxe/http.h> +#include <ipxe/features.h> FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 ); -/** Block size used for HTTP block device request */ -#define HTTP_BLKSIZE 512 - -/** HTTP flags */ -enum http_flags { - /** Request is waiting to be transmitted */ - HTTP_TX_PENDING = 0x0001, - /** Fetch header only */ - HTTP_HEAD_ONLY = 0x0002, - /** Keep connection alive */ - HTTP_KEEPALIVE = 0x0004, -}; - -/** HTTP receive state */ -enum http_rx_state { - HTTP_RX_RESPONSE = 0, - HTTP_RX_HEADER, - HTTP_RX_CHUNK_LEN, - HTTP_RX_DATA, - HTTP_RX_TRAILER, - HTTP_RX_IDLE, - HTTP_RX_DEAD, -}; - -/** - * An HTTP request - * - */ -struct http_request { - /** Reference count */ - struct refcnt refcnt; - /** Data transfer interface */ - struct interface xfer; - /** Partial transfer interface */ - struct interface partial; - - /** URI being fetched */ - struct uri *uri; - /** Transport layer interface */ - struct interface socket; - - /** Flags */ - unsigned int flags; - /** Starting offset of partial transfer (if applicable) */ - size_t partial_start; - /** Length of partial transfer (if applicable) */ - size_t partial_len; - - /** TX process */ - struct process process; - - /** RX state */ - enum http_rx_state rx_state; - /** Received length */ - size_t rx_len; - /** Length remaining (or 0 if unknown) */ - size_t remaining; - /** HTTP is using Transfer-Encoding: chunked */ - int chunked; - /** Current chunk length remaining (if applicable) */ - size_t chunk_remaining; - /** Line buffer for received header lines */ - struct line_buffer linebuf; - /** Receive data buffer (if applicable) */ - userptr_t rx_buffer; -}; - -/** - * Free HTTP request - * - * @v refcnt Reference counter - */ -static void http_free ( struct refcnt *refcnt ) { - struct http_request *http = - container_of ( refcnt, struct http_request, refcnt ); - - uri_put ( http->uri ); - empty_line_buffer ( &http->linebuf ); - free ( http ); -}; - -/** - * Close HTTP request - * - * @v http HTTP request - * @v rc Return status code - */ -static void http_close ( struct http_request *http, int rc ) { - - /* Prevent further processing of any current packet */ - http->rx_state = HTTP_RX_DEAD; - - /* If we had a Content-Length, and the received content length - * isn't correct, flag an error - */ - if ( http->remaining != 0 ) { - DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n", - http, http->rx_len, ( http->rx_len + http->remaining ) ); - if ( rc == 0 ) - rc = -EIO; - } - - /* Remove process */ - process_del ( &http->process ); - - /* Close all data transfer interfaces */ - intf_shutdown ( &http->socket, rc ); - intf_shutdown ( &http->partial, rc ); - intf_shutdown ( &http->xfer, rc ); -} - -/** - * Mark HTTP request as completed successfully - * - * @v http HTTP request - */ -static void http_done ( struct http_request *http ) { - - /* If we had a Content-Length, and the received content length - * isn't correct, force an error - */ - if ( http->remaining != 0 ) { - http_close ( http, -EIO ); - return; - } - - /* Enter idle state */ - http->rx_state = HTTP_RX_IDLE; - http->rx_len = 0; - assert ( http->remaining == 0 ); - assert ( http->chunked == 0 ); - assert ( http->chunk_remaining == 0 ); - - /* Close partial transfer interface */ - intf_restart ( &http->partial, 0 ); - - /* Close everything unless we are keeping the connection alive */ - if ( ! ( http->flags & HTTP_KEEPALIVE ) ) - http_close ( http, 0 ); -} - -/** - * Convert HTTP response code to return status code - * - * @v response HTTP response code - * @ret rc Return status code - */ -static int http_response_to_rc ( unsigned int response ) { - switch ( response ) { - case 200: - case 206: - case 301: - case 302: - 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; - unsigned int code; - int rc; - - DBGC ( http, "HTTP %p response \"%s\"\n", http, response ); - - /* Check response starts with "HTTP/" */ - if ( strncmp ( response, "HTTP/", 5 ) != 0 ) - return -EIO; - - /* Locate and check response code */ - spc = strchr ( response, ' ' ); - if ( ! spc ) - return -EIO; - code = strtoul ( spc, NULL, 10 ); - if ( ( rc = http_response_to_rc ( code ) ) != 0 ) - return rc; - - /* Move to received headers */ - http->rx_state = HTTP_RX_HEADER; - return 0; -} - -/** - * Handle HTTP Location header - * - * @v http HTTP request - * @v value HTTP header value - * @ret rc Return status code - */ -static int http_rx_location ( struct http_request *http, const char *value ) { - int rc; - - /* Redirect to new location */ - DBGC ( http, "HTTP %p redirecting to %s\n", http, value ); - if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING, - value ) ) != 0 ) { - DBGC ( http, "HTTP %p could not redirect: %s\n", - http, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Handle HTTP Content-Length header - * - * @v http HTTP request - * @v value HTTP header value - * @ret rc Return status code - */ -static int http_rx_content_length ( struct http_request *http, - const char *value ) { - struct block_device_capacity capacity; - size_t content_len; - char *endp; - - /* Parse content length */ - content_len = strtoul ( value, &endp, 10 ); - if ( *endp != '\0' ) { - DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n", - http, value ); - return -EIO; - } - - /* 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; - } - if ( ! ( http->flags & HTTP_HEAD_ONLY ) ) - http->remaining = content_len; - - /* Use seek() to notify recipient of filesize */ - xfer_seek ( &http->xfer, http->remaining ); - xfer_seek ( &http->xfer, 0 ); - - /* Report block device capacity if applicable */ - if ( http->flags & HTTP_HEAD_ONLY ) { - capacity.blocks = ( content_len / HTTP_BLKSIZE ); - capacity.blksize = HTTP_BLKSIZE; - capacity.max_count = -1U; - block_capacity ( &http->partial, &capacity ); - } - return 0; -} - -/** - * Handle HTTP Transfer-Encoding header - * - * @v http HTTP request - * @v value HTTP header value - * @ret rc Return status code - */ -static int http_rx_transfer_encoding ( struct http_request *http, - const char *value ) { - - if ( strcmp ( value, "chunked" ) == 0 ) { - /* Mark connection as using chunked transfer encoding */ - http->chunked = 1; - } - - return 0; -} - -/** An HTTP header handler */ -struct http_header_handler { - /** Name (e.g. "Content-Length") */ - const char *header; - /** Handle received header - * - * @v http HTTP request - * @v value HTTP header value - * @ret rc Return status code - * - * If an error is returned, the download will be aborted. - */ - int ( * rx ) ( struct http_request *http, const char *value ); -}; - -/** List of HTTP header handlers */ -static struct http_header_handler http_header_handlers[] = { - { - .header = "Location", - .rx = http_rx_location, - }, - { - .header = "Content-Length", - .rx = http_rx_content_length, - }, - { - .header = "Transfer-Encoding", - .rx = http_rx_transfer_encoding, - }, - { NULL, NULL } -}; - -/** - * Handle HTTP header - * - * @v http HTTP request - * @v header HTTP header - * @ret rc Return status code - */ -static int http_rx_header ( struct http_request *http, char *header ) { - struct http_header_handler *handler; - char *separator; - char *value; - int rc; - - /* An empty header line marks the end of this phase */ - if ( ! header[0] ) { - empty_line_buffer ( &http->linebuf ); - if ( ( http->rx_state == HTTP_RX_HEADER ) && - ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) { - DBGC ( http, "HTTP %p start of data\n", http ); - http->rx_state = ( http->chunked ? - HTTP_RX_CHUNK_LEN : HTTP_RX_DATA ); - return 0; - } else { - DBGC ( http, "HTTP %p end of trailer\n", http ); - http_done ( http ); - return 0; - } - } - - DBGC ( http, "HTTP %p header \"%s\"\n", http, header ); - - /* Split header at the ": " */ - separator = strstr ( header, ": " ); - if ( ! separator ) { - DBGC ( http, "HTTP %p malformed header\n", http ); - return -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; -} - -/** - * 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 -EIO; - } - - /* Terminate chunked encoding if applicable */ - if ( http->chunk_remaining == 0 ) { - DBGC ( http, "HTTP %p end of chunks\n", http ); - http->chunked = 0; - http->rx_state = HTTP_RX_TRAILER; - return 0; - } - - /* Use seek() to notify recipient of new filesize */ - DBGC ( http, "HTTP %p start of chunk of length %zd\n", - http, http->chunk_remaining ); - xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) ); - xfer_seek ( &http->xfer, http->rx_len ); - - /* Start receiving data */ - http->rx_state = HTTP_RX_DATA; - - return 0; -} - -/** An HTTP line-based data handler */ -struct http_line_handler { - /** Handle line - * - * @v http HTTP request - * @v line Line to handle - * @ret rc Return status code - */ - int ( * rx ) ( struct http_request *http, char *line ); -}; - -/** List of HTTP line-based data handlers */ -static struct http_line_handler http_line_handlers[] = { - [HTTP_RX_RESPONSE] = { .rx = http_rx_response }, - [HTTP_RX_HEADER] = { .rx = http_rx_header }, - [HTTP_RX_CHUNK_LEN] = { .rx = http_rx_chunk_len }, - [HTTP_RX_TRAILER] = { .rx = http_rx_header }, -}; - -/** - * Handle new data arriving via HTTP connection - * - * @v http HTTP request - * @v iobuf I/O buffer - * @v meta Data transfer metadata - * @ret rc Return status code - */ -static int http_socket_deliver ( struct http_request *http, - struct io_buffer *iobuf, - struct xfer_metadata *meta __unused ) { - struct http_line_handler *lh; - char *line; - size_t data_len; - ssize_t line_len; - int rc = 0; - - while ( iobuf && iob_len ( iobuf ) ) { - - switch ( http->rx_state ) { - case HTTP_RX_IDLE: - /* Receiving any data in this state is an error */ - DBGC ( http, "HTTP %p received %zd bytes while %s\n", - http, iob_len ( iobuf ), - ( ( http->rx_state == HTTP_RX_IDLE ) ? - "idle" : "dead" ) ); - rc = -EPROTO; - goto done; - case HTTP_RX_DEAD: - /* Do no further processing */ - goto done; - case HTTP_RX_DATA: - /* Pass received data to caller */ - data_len = iob_len ( iobuf ); - if ( http->chunk_remaining && - ( http->chunk_remaining < data_len ) ) { - data_len = http->chunk_remaining; - } - if ( http->remaining && - ( http->remaining < data_len ) ) { - data_len = http->remaining; - } - if ( http->rx_buffer != UNULL ) { - /* Copy to partial transfer buffer */ - copy_to_user ( http->rx_buffer, http->rx_len, - iobuf->data, data_len ); - iob_pull ( iobuf, data_len ); - } else if ( data_len < iob_len ( iobuf ) ) { - /* Deliver partial buffer as raw data */ - rc = xfer_deliver_raw ( &http->xfer, - iobuf->data, data_len ); - iob_pull ( iobuf, data_len ); - if ( rc != 0 ) - goto done; - } else { - /* Deliver whole I/O buffer */ - if ( ( rc = xfer_deliver_iob ( &http->xfer, - iob_disown ( iobuf ) ) ) != 0 ) - goto done; - } - http->rx_len += data_len; - if ( http->chunk_remaining ) { - http->chunk_remaining -= data_len; - if ( http->chunk_remaining == 0 ) - http->rx_state = HTTP_RX_CHUNK_LEN; - } - if ( http->remaining ) { - http->remaining -= data_len; - if ( ( http->remaining == 0 ) && - ( http->rx_state == HTTP_RX_DATA ) ) { - http_done ( http ); - } - } - break; - case HTTP_RX_RESPONSE: - case HTTP_RX_HEADER: - case HTTP_RX_CHUNK_LEN: - case HTTP_RX_TRAILER: - /* In the other phases, buffer and process a - * line at a time - */ - line_len = line_buffer ( &http->linebuf, iobuf->data, - iob_len ( iobuf ) ); - if ( line_len < 0 ) { - rc = line_len; - DBGC ( http, "HTTP %p could not buffer line: " - "%s\n", http, strerror ( rc ) ); - goto done; - } - iob_pull ( iobuf, line_len ); - line = buffered_line ( &http->linebuf ); - if ( line ) { - lh = &http_line_handlers[http->rx_state]; - if ( ( rc = lh->rx ( http, line ) ) != 0 ) - goto done; - } - break; - default: - assert ( 0 ); - break; - } - } - - done: - if ( rc ) - http_close ( http, rc ); - free_iob ( iobuf ); - return rc; -} - -/** - * Check HTTP socket flow control window - * - * @v http HTTP request - * @ret len Length of window - */ -static size_t http_socket_window ( struct http_request *http __unused ) { - - /* Window is always open. This is to prevent TCP from - * stalling if our parent window is not currently open. - */ - return ( ~( ( size_t ) 0 ) ); -} - -/** - * HTTP process - * - * @v http HTTP request - */ -static void http_step ( struct http_request *http ) { - const char *host = http->uri->host; - const char *user = http->uri->user; - const char *password = - ( http->uri->password ? http->uri->password : "" ); - size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ + - strlen ( password ) ) : 0 ); - size_t user_pw_base64_len = base64_encoded_len ( user_pw_len ); - 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 ); - char request[ request_len + 1 /* NUL */ ]; - char range[48]; /* Enough for two 64-bit integers in decimal */ - int partial; - - /* 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; - - /* Construct path?query request */ - unparse_uri ( request, sizeof ( request ), http->uri, - URI_PATH_BIT | URI_QUERY_BIT ); - - /* 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 ); - } - - /* Force a HEAD request if we have nowhere to send any received data */ - if ( ( xfer_window ( &http->xfer ) == 0 ) && - ( http->rx_buffer == UNULL ) ) { - http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE ); - } - - /* Determine type of request */ - partial = ( http->partial_len != 0 ); - snprintf ( range, sizeof ( range ), "%zd-%zd", http->partial_start, - ( http->partial_start + http->partial_len - 1 ) ); - - /* Mark request as transmitted */ - http->flags &= ~HTTP_TX_PENDING; - - /* Send GET request */ - if ( ( rc = xfer_printf ( &http->socket, - "%s %s%s HTTP/1.1\r\n" - "User-Agent: iPXE/" VERSION "\r\n" - "Host: %s%s%s\r\n" - "%s%s%s%s%s%s%s" - "\r\n", - ( ( http->flags & HTTP_HEAD_ONLY ) ? - "HEAD" : "GET" ), - ( http->uri->path ? "" : "/" ), - request, host, - ( http->uri->port ? - ":" : "" ), - ( http->uri->port ? - http->uri->port : "" ), - ( ( http->flags & HTTP_KEEPALIVE ) ? - "Connection: Keep-Alive\r\n" : "" ), - ( partial ? "Range: bytes=" : "" ), - ( partial ? range : "" ), - ( partial ? "\r\n" : "" ), - ( user ? - "Authorization: Basic " : "" ), - ( user ? user_pw_base64 : "" ), - ( user ? "\r\n" : "" ) ) ) != 0 ) { - http_close ( http, rc ); - } -} - -/** - * Check HTTP data transfer flow control window - * - * @v http HTTP request - * @ret len Length of window - */ -static size_t http_xfer_window ( struct http_request *http ) { - - /* New block commands may be issued only when we are idle */ - return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 ); -} - -/** - * Initiate HTTP partial read - * - * @v http HTTP request - * @v partial Partial transfer interface - * @v offset Starting offset - * @v buffer Data buffer - * @v len Length - * @ret rc Return status code - */ -static int http_partial_read ( struct http_request *http, - struct interface *partial, - size_t offset, userptr_t buffer, size_t len ) { - - /* Sanity check */ - if ( http_xfer_window ( http ) == 0 ) - return -EBUSY; - - /* Initialise partial transfer parameters */ - http->rx_buffer = buffer; - http->partial_start = offset; - http->partial_len = len; - http->remaining = len; - - /* Schedule request */ - http->rx_state = HTTP_RX_RESPONSE; - http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE ); - if ( ! len ) - http->flags |= HTTP_HEAD_ONLY; - process_add ( &http->process ); - - /* Attach to parent interface and return */ - intf_plug_plug ( &http->partial, partial ); - - return 0; -} - -/** - * Issue HTTP block device read - * - * @v http HTTP request - * @v block Block data interface - * @v lba Starting logical block address - * @v count Number of blocks to transfer - * @v buffer Data buffer - * @v len Length of data buffer - * @ret rc Return status code - */ -static int http_block_read ( struct http_request *http, - struct interface *block, - uint64_t lba, unsigned int count, - userptr_t buffer, size_t len __unused ) { - - return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ), - buffer, ( count * HTTP_BLKSIZE ) ); -} - -/** - * Read HTTP block device capacity - * - * @v http HTTP request - * @v block Block data interface - * @ret rc Return status code - */ -static int http_block_read_capacity ( struct http_request *http, - struct interface *block ) { - - return http_partial_read ( http, block, 0, 0, 0 ); -} - -/** - * Describe HTTP device in an ACPI table - * - * @v http HTTP request - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code - */ -static int http_acpi_describe ( struct http_request *http, - struct acpi_description_header *acpi, - size_t len ) { - - DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n", - http ); - ( void ) acpi; - ( void ) len; - return 0; -} - -/** HTTP socket interface operations */ -static struct interface_operation http_socket_operations[] = { - INTF_OP ( xfer_window, struct http_request *, http_socket_window ), - INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ), - INTF_OP ( xfer_window_changed, struct http_request *, http_step ), - INTF_OP ( intf_close, struct http_request *, http_close ), -}; - -/** HTTP socket interface descriptor */ -static struct interface_descriptor http_socket_desc = - INTF_DESC_PASSTHRU ( struct http_request, socket, - http_socket_operations, xfer ); - -/** HTTP partial transfer interface operations */ -static struct interface_operation http_partial_operations[] = { - INTF_OP ( intf_close, struct http_request *, http_close ), -}; - -/** HTTP partial transfer interface descriptor */ -static struct interface_descriptor http_partial_desc = - INTF_DESC ( struct http_request, partial, http_partial_operations ); - -/** HTTP data transfer interface operations */ -static struct interface_operation http_xfer_operations[] = { - INTF_OP ( xfer_window, struct http_request *, http_xfer_window ), - INTF_OP ( block_read, struct http_request *, http_block_read ), - INTF_OP ( block_read_capacity, struct http_request *, - http_block_read_capacity ), - INTF_OP ( intf_close, struct http_request *, http_close ), - INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ), -}; - -/** HTTP data transfer interface descriptor */ -static struct interface_descriptor http_xfer_desc = - INTF_DESC_PASSTHRU ( struct http_request, xfer, - http_xfer_operations, socket ); - -/** HTTP process descriptor */ -static struct process_descriptor http_process_desc = - PROC_DESC_ONCE ( struct http_request, process, http_step ); - -/** - * Initiate an HTTP connection, with optional filter - * - * @v xfer Data transfer interface - * @v uri Uniform Resource Identifier - * @v default_port Default port number - * @v filter Filter to apply to socket, or NULL - * @ret rc Return status code - */ -int http_open_filter ( struct interface *xfer, struct uri *uri, - unsigned int default_port, - int ( * filter ) ( struct interface *xfer, - struct interface **next ) ) { - struct http_request *http; - struct sockaddr_tcpip server; - struct interface *socket; - int rc; - - /* Sanity checks */ - if ( ! uri->host ) - return -EINVAL; - - /* Allocate and populate HTTP structure */ - http = zalloc ( sizeof ( *http ) ); - if ( ! http ) - return -ENOMEM; - ref_init ( &http->refcnt, http_free ); - intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt ); - intf_init ( &http->partial, &http_partial_desc, &http->refcnt ); - http->uri = uri_get ( uri ); - intf_init ( &http->socket, &http_socket_desc, &http->refcnt ); - process_init ( &http->process, &http_process_desc, &http->refcnt ); - http->flags = HTTP_TX_PENDING; - - /* Open socket */ - memset ( &server, 0, sizeof ( server ) ); - server.st_port = htons ( uri_port ( http->uri, default_port ) ); - socket = &http->socket; - if ( filter ) { - if ( ( rc = filter ( socket, &socket ) ) != 0 ) - goto err; - } - if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, - ( struct sockaddr * ) &server, - uri->host, NULL ) ) != 0 ) - goto err; - - /* Attach to parent interface, mortalise self, and return */ - intf_plug_plug ( &http->xfer, xfer ); - ref_put ( &http->refcnt ); - return 0; - - err: - DBGC ( http, "HTTP %p could not create request: %s\n", - http, strerror ( rc ) ); - http_close ( http, rc ); - ref_put ( &http->refcnt ); - return rc; -} - /** * Initiate an HTTP connection * diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c new file mode 100644 index 00000000..d0ad952e --- /dev/null +++ b/src/net/tcp/httpcore.c @@ -0,0 +1,938 @@ +/* + * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * Hyper Text Transfer Protocol (HTTP) core functionality + * + */ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <byteswap.h> +#include <errno.h> +#include <assert.h> +#include <ipxe/uri.h> +#include <ipxe/refcnt.h> +#include <ipxe/iobuf.h> +#include <ipxe/xfer.h> +#include <ipxe/open.h> +#include <ipxe/socket.h> +#include <ipxe/tcpip.h> +#include <ipxe/process.h> +#include <ipxe/linebuf.h> +#include <ipxe/base64.h> +#include <ipxe/blockdev.h> +#include <ipxe/acpi.h> +#include <ipxe/http.h> + +/* Disambiguate the various error causes */ +#define EACCES_401 __einfo_error ( EINFO_EACCES_401 ) +#define EINFO_EACCES_401 \ + __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" ) +#define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER ) +#define EINFO_EIO_OTHER \ + __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" ) +#define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH ) +#define EINFO_EIO_CONTENT_LENGTH \ + __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" ) +#define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE ) +#define EINFO_EINVAL_RESPONSE \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" ) +#define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER ) +#define EINFO_EINVAL_HEADER \ + __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" ) +#define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH ) +#define EINFO_EINVAL_CONTENT_LENGTH \ + __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" ) +#define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH ) +#define EINFO_EINVAL_CHUNK_LENGTH \ + __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" ) +#define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 ) +#define EINFO_ENOENT_404 \ + __einfo_uniqify ( EINFO_ENOENT, 0x01, "HTTP 404 Not Found" ) +#define EPERM_403 __einfo_error ( EINFO_EPERM_403 ) +#define EINFO_EPERM_403 \ + __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" ) +#define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED ) +#define EINFO_EPROTO_UNSOLICITED \ + __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" ) + +/** Block size used for HTTP block device request */ +#define HTTP_BLKSIZE 512 + +/** HTTP flags */ +enum http_flags { + /** Request is waiting to be transmitted */ + HTTP_TX_PENDING = 0x0001, + /** Fetch header only */ + HTTP_HEAD_ONLY = 0x0002, + /** Keep connection alive */ + HTTP_KEEPALIVE = 0x0004, +}; + +/** HTTP receive state */ +enum http_rx_state { + HTTP_RX_RESPONSE = 0, + HTTP_RX_HEADER, + HTTP_RX_CHUNK_LEN, + HTTP_RX_DATA, + HTTP_RX_TRAILER, + HTTP_RX_IDLE, + HTTP_RX_DEAD, +}; + +/** + * An HTTP request + * + */ +struct http_request { + /** Reference count */ + struct refcnt refcnt; + /** Data transfer interface */ + struct interface xfer; + /** Partial transfer interface */ + struct interface partial; + + /** URI being fetched */ + struct uri *uri; + /** Transport layer interface */ + struct interface socket; + + /** Flags */ + unsigned int flags; + /** Starting offset of partial transfer (if applicable) */ + size_t partial_start; + /** Length of partial transfer (if applicable) */ + size_t partial_len; + + /** TX process */ + struct process process; + + /** RX state */ + enum http_rx_state rx_state; + /** Received length */ + size_t rx_len; + /** Length remaining (or 0 if unknown) */ + size_t remaining; + /** HTTP is using Transfer-Encoding: chunked */ + int chunked; + /** Current chunk length remaining (if applicable) */ + size_t chunk_remaining; + /** Line buffer for received header lines */ + struct line_buffer linebuf; + /** Receive data buffer (if applicable) */ + userptr_t rx_buffer; +}; + +/** + * Free HTTP request + * + * @v refcnt Reference counter + */ +static void http_free ( struct refcnt *refcnt ) { + struct http_request *http = + container_of ( refcnt, struct http_request, refcnt ); + + uri_put ( http->uri ); + empty_line_buffer ( &http->linebuf ); + free ( http ); +}; + +/** + * Close HTTP request + * + * @v http HTTP request + * @v rc Return status code + */ +static void http_close ( struct http_request *http, int rc ) { + + /* Prevent further processing of any current packet */ + http->rx_state = HTTP_RX_DEAD; + + /* If we had a Content-Length, and the received content length + * isn't correct, flag an error + */ + if ( http->remaining != 0 ) { + DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n", + http, http->rx_len, ( http->rx_len + http->remaining ) ); + if ( rc == 0 ) + rc = -EIO_CONTENT_LENGTH; + } + + /* Remove process */ + process_del ( &http->process ); + + /* Close all data transfer interfaces */ + intf_shutdown ( &http->socket, rc ); + intf_shutdown ( &http->partial, rc ); + intf_shutdown ( &http->xfer, rc ); +} + +/** + * Mark HTTP request as completed successfully + * + * @v http HTTP request + */ +static void http_done ( struct http_request *http ) { + + /* If we had a Content-Length, and the received content length + * isn't correct, force an error + */ + if ( http->remaining != 0 ) { + http_close ( http, -EIO_CONTENT_LENGTH ); + return; + } + + /* Enter idle state */ + http->rx_state = HTTP_RX_IDLE; + http->rx_len = 0; + assert ( http->remaining == 0 ); + assert ( http->chunked == 0 ); + assert ( http->chunk_remaining == 0 ); + + /* Close partial transfer interface */ + intf_restart ( &http->partial, 0 ); + + /* Close everything unless we are keeping the connection alive */ + if ( ! ( http->flags & HTTP_KEEPALIVE ) ) + http_close ( http, 0 ); +} + +/** + * Convert HTTP response code to return status code + * + * @v response HTTP response code + * @ret rc Return status code + */ +static int http_response_to_rc ( unsigned int response ) { + switch ( response ) { + case 200: + case 206: + case 301: + case 302: + case 303: + return 0; + case 404: + return -ENOENT_404; + case 403: + return -EPERM_403; + case 401: + return -EACCES_401; + default: + return -EIO_OTHER; + } +} + +/** + * Handle HTTP response + * + * @v http HTTP request + * @v response HTTP response + * @ret rc Return status code + */ +static int http_rx_response ( struct http_request *http, char *response ) { + char *spc; + unsigned int code; + int rc; + + DBGC ( http, "HTTP %p response \"%s\"\n", http, response ); + + /* Check response starts with "HTTP/" */ + if ( strncmp ( response, "HTTP/", 5 ) != 0 ) + return -EINVAL_RESPONSE; + + /* Locate and check response code */ + spc = strchr ( response, ' ' ); + if ( ! spc ) + return -EINVAL_RESPONSE; + code = strtoul ( spc, NULL, 10 ); + if ( ( rc = http_response_to_rc ( code ) ) != 0 ) + return rc; + + /* Move to received headers */ + http->rx_state = HTTP_RX_HEADER; + return 0; +} + +/** + * Handle HTTP Location header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_location ( struct http_request *http, const char *value ) { + int rc; + + /* Redirect to new location */ + DBGC ( http, "HTTP %p redirecting to %s\n", http, value ); + if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING, + value ) ) != 0 ) { + DBGC ( http, "HTTP %p could not redirect: %s\n", + http, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Handle HTTP Content-Length header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_content_length ( struct http_request *http, + const char *value ) { + struct block_device_capacity capacity; + size_t content_len; + char *endp; + + /* Parse content length */ + content_len = strtoul ( value, &endp, 10 ); + if ( *endp != '\0' ) { + DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n", + http, value ); + return -EINVAL_CONTENT_LENGTH; + } + + /* If we already have an expected content length, and this + * isn't it, then complain + */ + if ( http->remaining && ( http->remaining != content_len ) ) { + DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected " + "%zd)\n", http, content_len, http->remaining ); + return -EIO_CONTENT_LENGTH; + } + if ( ! ( http->flags & HTTP_HEAD_ONLY ) ) + http->remaining = content_len; + + /* Use seek() to notify recipient of filesize */ + xfer_seek ( &http->xfer, http->remaining ); + xfer_seek ( &http->xfer, 0 ); + + /* Report block device capacity if applicable */ + if ( http->flags & HTTP_HEAD_ONLY ) { + capacity.blocks = ( content_len / HTTP_BLKSIZE ); + capacity.blksize = HTTP_BLKSIZE; + capacity.max_count = -1U; + block_capacity ( &http->partial, &capacity ); + } + return 0; +} + +/** + * Handle HTTP Transfer-Encoding header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_transfer_encoding ( struct http_request *http, + const char *value ) { + + if ( strcmp ( value, "chunked" ) == 0 ) { + /* Mark connection as using chunked transfer encoding */ + http->chunked = 1; + } + + return 0; +} + +/** An HTTP header handler */ +struct http_header_handler { + /** Name (e.g. "Content-Length") */ + const char *header; + /** Handle received header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + * + * If an error is returned, the download will be aborted. + */ + int ( * rx ) ( struct http_request *http, const char *value ); +}; + +/** List of HTTP header handlers */ +static struct http_header_handler http_header_handlers[] = { + { + .header = "Location", + .rx = http_rx_location, + }, + { + .header = "Content-Length", + .rx = http_rx_content_length, + }, + { + .header = "Transfer-Encoding", + .rx = http_rx_transfer_encoding, + }, + { NULL, NULL } +}; + +/** + * Handle HTTP header + * + * @v http HTTP request + * @v header HTTP header + * @ret rc Return status code + */ +static int http_rx_header ( struct http_request *http, char *header ) { + struct http_header_handler *handler; + char *separator; + char *value; + int rc; + + /* An empty header line marks the end of this phase */ + if ( ! header[0] ) { + empty_line_buffer ( &http->linebuf ); + if ( ( http->rx_state == HTTP_RX_HEADER ) && + ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) { + DBGC ( http, "HTTP %p start of data\n", http ); + http->rx_state = ( http->chunked ? + HTTP_RX_CHUNK_LEN : HTTP_RX_DATA ); + return 0; + } else { + DBGC ( http, "HTTP %p end of trailer\n", http ); + http_done ( http ); + return 0; + } + } + + DBGC ( http, "HTTP %p header \"%s\"\n", http, header ); + + /* Split header at the ": " */ + separator = strstr ( header, ": " ); + if ( ! separator ) { + DBGC ( http, "HTTP %p malformed header\n", http ); + return -EINVAL_HEADER; + } + *separator = '\0'; + value = ( separator + 2 ); + + /* Hand off to header handler, if one exists */ + for ( handler = http_header_handlers ; handler->header ; handler++ ) { + if ( strcasecmp ( header, handler->header ) == 0 ) { + if ( ( rc = handler->rx ( http, value ) ) != 0 ) + return rc; + break; + } + } + return 0; +} + +/** + * Handle HTTP chunk length + * + * @v http HTTP request + * @v length HTTP chunk length + * @ret rc Return status code + */ +static int http_rx_chunk_len ( struct http_request *http, char *length ) { + char *endp; + + /* Skip blank lines between chunks */ + if ( length[0] == '\0' ) + return 0; + + /* Parse chunk length */ + http->chunk_remaining = strtoul ( length, &endp, 16 ); + if ( *endp != '\0' ) { + DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n", + http, length ); + return -EINVAL_CHUNK_LENGTH; + } + + /* Terminate chunked encoding if applicable */ + if ( http->chunk_remaining == 0 ) { + DBGC ( http, "HTTP %p end of chunks\n", http ); + http->chunked = 0; + http->rx_state = HTTP_RX_TRAILER; + return 0; + } + + /* Use seek() to notify recipient of new filesize */ + DBGC ( http, "HTTP %p start of chunk of length %zd\n", + http, http->chunk_remaining ); + xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) ); + xfer_seek ( &http->xfer, http->rx_len ); + + /* Start receiving data */ + http->rx_state = HTTP_RX_DATA; + + return 0; +} + +/** An HTTP line-based data handler */ +struct http_line_handler { + /** Handle line + * + * @v http HTTP request + * @v line Line to handle + * @ret rc Return status code + */ + int ( * rx ) ( struct http_request *http, char *line ); +}; + +/** List of HTTP line-based data handlers */ +static struct http_line_handler http_line_handlers[] = { + [HTTP_RX_RESPONSE] = { .rx = http_rx_response }, + [HTTP_RX_HEADER] = { .rx = http_rx_header }, + [HTTP_RX_CHUNK_LEN] = { .rx = http_rx_chunk_len }, + [HTTP_RX_TRAILER] = { .rx = http_rx_header }, +}; + +/** + * Handle new data arriving via HTTP connection + * + * @v http HTTP request + * @v iobuf I/O buffer + * @v meta Data transfer metadata + * @ret rc Return status code + */ +static int http_socket_deliver ( struct http_request *http, + struct io_buffer *iobuf, + struct xfer_metadata *meta __unused ) { + struct http_line_handler *lh; + char *line; + size_t data_len; + ssize_t line_len; + int rc = 0; + + while ( iobuf && iob_len ( iobuf ) ) { + + switch ( http->rx_state ) { + case HTTP_RX_IDLE: + /* Receiving any data in this state is an error */ + DBGC ( http, "HTTP %p received %zd bytes while %s\n", + http, iob_len ( iobuf ), + ( ( http->rx_state == HTTP_RX_IDLE ) ? + "idle" : "dead" ) ); + rc = -EPROTO_UNSOLICITED; + goto done; + case HTTP_RX_DEAD: + /* Do no further processing */ + goto done; + case HTTP_RX_DATA: + /* Pass received data to caller */ + data_len = iob_len ( iobuf ); + if ( http->chunk_remaining && + ( http->chunk_remaining < data_len ) ) { + data_len = http->chunk_remaining; + } + if ( http->remaining && + ( http->remaining < data_len ) ) { + data_len = http->remaining; + } + if ( http->rx_buffer != UNULL ) { + /* Copy to partial transfer buffer */ + copy_to_user ( http->rx_buffer, http->rx_len, + iobuf->data, data_len ); + iob_pull ( iobuf, data_len ); + } else if ( data_len < iob_len ( iobuf ) ) { + /* Deliver partial buffer as raw data */ + rc = xfer_deliver_raw ( &http->xfer, + iobuf->data, data_len ); + iob_pull ( iobuf, data_len ); + if ( rc != 0 ) + goto done; + } else { + /* Deliver whole I/O buffer */ + if ( ( rc = xfer_deliver_iob ( &http->xfer, + iob_disown ( iobuf ) ) ) != 0 ) + goto done; + } + http->rx_len += data_len; + if ( http->chunk_remaining ) { + http->chunk_remaining -= data_len; + if ( http->chunk_remaining == 0 ) + http->rx_state = HTTP_RX_CHUNK_LEN; + } + if ( http->remaining ) { + http->remaining -= data_len; + if ( ( http->remaining == 0 ) && + ( http->rx_state == HTTP_RX_DATA ) ) { + http_done ( http ); + } + } + break; + case HTTP_RX_RESPONSE: + case HTTP_RX_HEADER: + case HTTP_RX_CHUNK_LEN: + case HTTP_RX_TRAILER: + /* In the other phases, buffer and process a + * line at a time + */ + line_len = line_buffer ( &http->linebuf, iobuf->data, + iob_len ( iobuf ) ); + if ( line_len < 0 ) { + rc = line_len; + DBGC ( http, "HTTP %p could not buffer line: " + "%s\n", http, strerror ( rc ) ); + goto done; + } + iob_pull ( iobuf, line_len ); + line = buffered_line ( &http->linebuf ); + if ( line ) { + lh = &http_line_handlers[http->rx_state]; + if ( ( rc = lh->rx ( http, line ) ) != 0 ) + goto done; + } + break; + default: + assert ( 0 ); + break; + } + } + + done: + if ( rc ) + http_close ( http, rc ); + free_iob ( iobuf ); + return rc; +} + +/** + * Check HTTP socket flow control window + * + * @v http HTTP request + * @ret len Length of window + */ +static size_t http_socket_window ( struct http_request *http __unused ) { + + /* Window is always open. This is to prevent TCP from + * stalling if our parent window is not currently open. + */ + return ( ~( ( size_t ) 0 ) ); +} + +/** + * HTTP process + * + * @v http HTTP request + */ +static void http_step ( struct http_request *http ) { + const char *host = http->uri->host; + const char *user = http->uri->user; + const char *password = + ( http->uri->password ? http->uri->password : "" ); + size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ + + strlen ( password ) ) : 0 ); + size_t user_pw_base64_len = base64_encoded_len ( user_pw_len ); + int request_len = unparse_uri ( NULL, 0, http->uri, + URI_PATH_BIT | URI_QUERY_BIT ); + struct { + uint8_t user_pw[ user_pw_len + 1 /* NUL */ ]; + char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; + char request[ request_len + 1 /* NUL */ ]; + char range[48]; /* Enough for two 64-bit integers in decimal */ + } *dynamic; + int partial; + int rc; + + /* Do nothing if we have already transmitted the request */ + if ( ! ( http->flags & HTTP_TX_PENDING ) ) + return; + + /* Do nothing until socket is ready */ + if ( ! xfer_window ( &http->socket ) ) + return; + + /* Allocate dynamic storage */ + dynamic = malloc ( sizeof ( *dynamic ) ); + if ( ! dynamic ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Construct path?query request */ + unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri, + URI_PATH_BIT | URI_QUERY_BIT ); + + /* Construct authorisation, if applicable */ + if ( user ) { + /* Make "user:password" string from decoded fields */ + snprintf ( ( ( char * ) dynamic->user_pw ), + sizeof ( dynamic->user_pw ), "%s:%s", + user, password ); + + /* Base64-encode the "user:password" string */ + base64_encode ( dynamic->user_pw, user_pw_len, + dynamic->user_pw_base64 ); + } + + /* Force a HEAD request if we have nowhere to send any received data */ + if ( ( xfer_window ( &http->xfer ) == 0 ) && + ( http->rx_buffer == UNULL ) ) { + http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE ); + } + + /* Determine type of request */ + partial = ( http->partial_len != 0 ); + snprintf ( dynamic->range, sizeof ( dynamic->range ), + "%zd-%zd", http->partial_start, + ( http->partial_start + http->partial_len - 1 ) ); + + /* Mark request as transmitted */ + http->flags &= ~HTTP_TX_PENDING; + + /* Send GET request */ + if ( ( rc = xfer_printf ( &http->socket, + "%s %s%s HTTP/1.1\r\n" + "User-Agent: iPXE/" VERSION "\r\n" + "Host: %s%s%s\r\n" + "%s%s%s%s%s%s%s" + "\r\n", + ( ( http->flags & HTTP_HEAD_ONLY ) ? + "HEAD" : "GET" ), + ( http->uri->path ? "" : "/" ), + dynamic->request, host, + ( http->uri->port ? + ":" : "" ), + ( http->uri->port ? + http->uri->port : "" ), + ( ( http->flags & HTTP_KEEPALIVE ) ? + "Connection: Keep-Alive\r\n" : "" ), + ( partial ? "Range: bytes=" : "" ), + ( partial ? dynamic->range : "" ), + ( partial ? "\r\n" : "" ), + ( user ? + "Authorization: Basic " : "" ), + ( user ? dynamic->user_pw_base64 : "" ), + ( user ? "\r\n" : "" ) ) ) != 0 ) { + goto err_xfer; + } + + err_xfer: + free ( dynamic ); + err_alloc: + if ( rc != 0 ) + http_close ( http, rc ); +} + +/** + * Check HTTP data transfer flow control window + * + * @v http HTTP request + * @ret len Length of window + */ +static size_t http_xfer_window ( struct http_request *http ) { + + /* New block commands may be issued only when we are idle */ + return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 ); +} + +/** + * Initiate HTTP partial read + * + * @v http HTTP request + * @v partial Partial transfer interface + * @v offset Starting offset + * @v buffer Data buffer + * @v len Length + * @ret rc Return status code + */ +static int http_partial_read ( struct http_request *http, + struct interface *partial, + size_t offset, userptr_t buffer, size_t len ) { + + /* Sanity check */ + if ( http_xfer_window ( http ) == 0 ) + return -EBUSY; + + /* Initialise partial transfer parameters */ + http->rx_buffer = buffer; + http->partial_start = offset; + http->partial_len = len; + http->remaining = len; + + /* Schedule request */ + http->rx_state = HTTP_RX_RESPONSE; + http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE ); + if ( ! len ) + http->flags |= HTTP_HEAD_ONLY; + process_add ( &http->process ); + + /* Attach to parent interface and return */ + intf_plug_plug ( &http->partial, partial ); + + return 0; +} + +/** + * Issue HTTP block device read + * + * @v http HTTP request + * @v block Block data interface + * @v lba Starting logical block address + * @v count Number of blocks to transfer + * @v buffer Data buffer + * @v len Length of data buffer + * @ret rc Return status code + */ +static int http_block_read ( struct http_request *http, + struct interface *block, + uint64_t lba, unsigned int count, + userptr_t buffer, size_t len __unused ) { + + return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ), + buffer, ( count * HTTP_BLKSIZE ) ); +} + +/** + * Read HTTP block device capacity + * + * @v http HTTP request + * @v block Block data interface + * @ret rc Return status code + */ +static int http_block_read_capacity ( struct http_request *http, + struct interface *block ) { + + return http_partial_read ( http, block, 0, 0, 0 ); +} + +/** + * Describe HTTP device in an ACPI table + * + * @v http HTTP request + * @v acpi ACPI table + * @v len Length of ACPI table + * @ret rc Return status code + */ +static int http_acpi_describe ( struct http_request *http, + struct acpi_description_header *acpi, + size_t len ) { + + DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n", + http ); + ( void ) acpi; + ( void ) len; + return 0; +} + +/** HTTP socket interface operations */ +static struct interface_operation http_socket_operations[] = { + INTF_OP ( xfer_window, struct http_request *, http_socket_window ), + INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ), + INTF_OP ( xfer_window_changed, struct http_request *, http_step ), + INTF_OP ( intf_close, struct http_request *, http_close ), +}; + +/** HTTP socket interface descriptor */ +static struct interface_descriptor http_socket_desc = + INTF_DESC_PASSTHRU ( struct http_request, socket, + http_socket_operations, xfer ); + +/** HTTP partial transfer interface operations */ +static struct interface_operation http_partial_operations[] = { + INTF_OP ( intf_close, struct http_request *, http_close ), +}; + +/** HTTP partial transfer interface descriptor */ +static struct interface_descriptor http_partial_desc = + INTF_DESC ( struct http_request, partial, http_partial_operations ); + +/** HTTP data transfer interface operations */ +static struct interface_operation http_xfer_operations[] = { + INTF_OP ( xfer_window, struct http_request *, http_xfer_window ), + INTF_OP ( block_read, struct http_request *, http_block_read ), + INTF_OP ( block_read_capacity, struct http_request *, + http_block_read_capacity ), + INTF_OP ( intf_close, struct http_request *, http_close ), + INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ), +}; + +/** HTTP data transfer interface descriptor */ +static struct interface_descriptor http_xfer_desc = + INTF_DESC_PASSTHRU ( struct http_request, xfer, + http_xfer_operations, socket ); + +/** HTTP process descriptor */ +static struct process_descriptor http_process_desc = + PROC_DESC_ONCE ( struct http_request, process, http_step ); + +/** + * Initiate an HTTP connection, with optional filter + * + * @v xfer Data transfer interface + * @v uri Uniform Resource Identifier + * @v default_port Default port number + * @v filter Filter to apply to socket, or NULL + * @ret rc Return status code + */ +int http_open_filter ( struct interface *xfer, struct uri *uri, + unsigned int default_port, + int ( * filter ) ( struct interface *xfer, + const char *name, + struct interface **next ) ) { + struct http_request *http; + struct sockaddr_tcpip server; + struct interface *socket; + int rc; + + /* Sanity checks */ + if ( ! uri->host ) + return -EINVAL; + + /* Allocate and populate HTTP structure */ + http = zalloc ( sizeof ( *http ) ); + if ( ! http ) + return -ENOMEM; + ref_init ( &http->refcnt, http_free ); + intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt ); + intf_init ( &http->partial, &http_partial_desc, &http->refcnt ); + http->uri = uri_get ( uri ); + intf_init ( &http->socket, &http_socket_desc, &http->refcnt ); + process_init ( &http->process, &http_process_desc, &http->refcnt ); + http->flags = HTTP_TX_PENDING; + + /* Open socket */ + memset ( &server, 0, sizeof ( server ) ); + server.st_port = htons ( uri_port ( http->uri, default_port ) ); + socket = &http->socket; + if ( filter ) { + if ( ( rc = filter ( socket, uri->host, &socket ) ) != 0 ) + goto err; + } + if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, + ( struct sockaddr * ) &server, + uri->host, NULL ) ) != 0 ) + goto err; + + /* Attach to parent interface, mortalise self, and return */ + intf_plug_plug ( &http->xfer, xfer ); + ref_put ( &http->refcnt ); + return 0; + + err: + DBGC ( http, "HTTP %p could not create request: %s\n", + http, strerror ( rc ) ); + http_close ( http, rc ); + ref_put ( &http->refcnt ); + return rc; +} diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index fa1bb398..9eaf3cc5 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -570,20 +570,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 ); } @@ -801,13 +804,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 ); } @@ -1415,27 +1422,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 * @@ -1494,11 +1480,6 @@ static void iscsi_tx_step ( struct iscsi_session *iscsi ) { 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: diff --git a/src/net/tcp/syslogs.c b/src/net/tcp/syslogs.c new file mode 100644 index 00000000..e7480e56 --- /dev/null +++ b/src/net/tcp/syslogs.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Encrypted syslog protocol + * + */ + +#include <stdint.h> +#include <stdlib.h> +#include <byteswap.h> +#include <ipxe/xfer.h> +#include <ipxe/open.h> +#include <ipxe/tcpip.h> +#include <ipxe/dhcp.h> +#include <ipxe/settings.h> +#include <ipxe/console.h> +#include <ipxe/lineconsole.h> +#include <ipxe/tls.h> +#include <ipxe/syslog.h> +#include <config/console.h> + +/* Set default console usage if applicable */ +#if ! ( defined ( CONSOLE_SYSLOGS ) && CONSOLE_EXPLICIT ( CONSOLE_SYSLOGS ) ) +#undef CONSOLE_SYSLOGS +#define CONSOLE_SYSLOGS ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI ) +#endif + +struct console_driver syslogs_console __console_driver; + +/** The encrypted syslog server */ +static struct sockaddr_tcpip logserver = { + .st_family = AF_INET, + .st_port = htons ( SYSLOG_PORT ), +}; + +/** + * Handle encrypted syslog TLS interface close + * + * @v intf Interface + * @v rc Reason for close + */ +static void syslogs_close ( struct interface *intf __unused, int rc ) { + + DBG ( "SYSLOGS console disconnected: %s\n", strerror ( rc ) ); +} + +/** + * Handle encrypted syslog TLS interface window change + * + * @v intf Interface + */ +static void syslogs_window_changed ( struct interface *intf ) { + + /* Mark console as enabled when window first opens, indicating + * that TLS negotiation is complete. (Do not disable console + * when window closes again, since TCP will close the window + * whenever there is unACKed data.) + */ + if ( xfer_window ( intf ) ) { + if ( syslogs_console.disabled ) + DBG ( "SYSLOGS console connected\n" ); + syslogs_console.disabled = 0; + } +} + +/** Encrypted syslog TLS interface operations */ +static struct interface_operation syslogs_operations[] = { + INTF_OP ( xfer_window_changed, struct interface *, + syslogs_window_changed ), + INTF_OP ( intf_close, struct interface *, syslogs_close ), +}; + +/** Encrypted syslog TLS interface descriptor */ +static struct interface_descriptor syslogs_desc = + INTF_DESC_PURE ( syslogs_operations ); + +/** The encrypted syslog TLS interface */ +static struct interface syslogs = INTF_INIT ( syslogs_desc ); + +/****************************************************************************** + * + * Console driver + * + ****************************************************************************** + */ + +/** Encrypted syslog line buffer */ +static char syslogs_buffer[SYSLOG_BUFSIZE]; + +/** Encrypted syslog severity */ +static unsigned int syslogs_severity = SYSLOG_DEFAULT_SEVERITY; + +/** + * Handle ANSI set encrypted syslog priority (private sequence) + * + * @v count Parameter count + * @v params List of graphic rendition aspects + */ +static void syslogs_handle_priority ( unsigned int count __unused, + int params[] ) { + if ( params[0] >= 0 ) { + syslogs_severity = params[0]; + } else { + syslogs_severity = SYSLOG_DEFAULT_SEVERITY; + } +} + +/** Encrypted syslog ANSI escape sequence handlers */ +static struct ansiesc_handler syslogs_handlers[] = { + { ANSIESC_LOG_PRIORITY, syslogs_handle_priority }, + { 0, NULL } +}; + +/** Encrypted syslog line console */ +static struct line_console syslogs_line = { + .buffer = syslogs_buffer, + .len = sizeof ( syslogs_buffer ), + .ctx = { + .handlers = syslogs_handlers, + }, +}; + +/** Encrypted syslog recursion marker */ +static int syslogs_entered; + +/** + * Print a character to encrypted syslog console + * + * @v character Character to be printed + */ +static void syslogs_putchar ( int character ) { + int rc; + + /* Ignore if we are already mid-logging */ + if ( syslogs_entered ) + return; + + /* Fill line buffer */ + if ( line_putchar ( &syslogs_line, character ) == 0 ) + return; + + /* Guard against re-entry */ + syslogs_entered = 1; + + /* Send log message */ + if ( ( rc = xfer_printf ( &syslogs, "<%d>ipxe: %s\n", + SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY, + syslogs_severity ), + syslogs_buffer ) ) != 0 ) { + DBG ( "SYSLOGS could not send log message: %s\n", + strerror ( rc ) ); + } + + /* Clear re-entry flag */ + syslogs_entered = 0; +} + +/** Encrypted syslog console driver */ +struct console_driver syslogs_console __console_driver = { + .putchar = syslogs_putchar, + .disabled = 1, + .usage = CONSOLE_SYSLOGS, +}; + +/****************************************************************************** + * + * Settings + * + ****************************************************************************** + */ + +/** Encrypted syslog server setting */ +struct setting syslogs_setting __setting ( SETTING_MISC ) = { + .name = "syslogs", + .description = "Encrypted syslog server", + .tag = DHCP_EB_SYSLOGS_SERVER, + .type = &setting_type_string, +}; + +/** + * Apply encrypted syslog settings + * + * @ret rc Return status code + */ +static int apply_syslogs_settings ( void ) { + static char *old_server; + char *server; + struct interface *socket; + int len; + int rc; + + /* Fetch log server */ + len = fetch_string_setting_copy ( NULL, &syslogs_setting, &server ); + if ( len < 0 ) { + rc = len; + goto err_fetch_server; + } + + /* Do nothing unless log server has changed */ + if ( ( ( server == NULL ) && ( old_server == NULL ) ) || + ( ( server != NULL ) && ( old_server != NULL ) && + ( strcmp ( server, old_server ) == 0 ) ) ) { + rc = 0; + goto out_no_change; + } + free ( old_server ); + old_server = NULL; + + /* Reset encrypted syslog connection */ + syslogs_console.disabled = 1; + intf_restart ( &syslogs, 0 ); + + /* Do nothing unless we have a log server */ + if ( ! server ) { + DBG ( "SYSLOGS has no log server\n" ); + rc = 0; + goto out_no_server; + } + + /* Add TLS filter */ + if ( ( rc = add_tls ( &syslogs, server, &socket ) ) != 0 ) { + DBG ( "SYSLOGS cannot create TLS filter: %s\n", + strerror ( rc ) ); + goto err_add_tls; + } + + /* Connect to log server */ + if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, + (( struct sockaddr *) &logserver ), + server, NULL ) ) != 0 ) { + DBG ( "SYSLOGS cannot connect to log server: %s\n", + strerror ( rc ) ); + goto err_open_named_socket; + } + DBG ( "SYSLOGS using log server %s\n", server ); + + /* Record log server */ + old_server = server; + server = NULL; + + /* Success */ + rc = 0; + + err_open_named_socket: + err_add_tls: + out_no_server: + out_no_change: + free ( server ); + err_fetch_server: + return rc; +} + +/** Encrypted syslog settings applicator */ +struct settings_applicator syslogs_applicator __settings_applicator = { + .apply = apply_syslogs_settings, +}; diff --git a/src/net/tls.c b/src/net/tls.c index ace719c1..97e013d7 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -28,20 +28,30 @@ 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/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" ) + 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 +73,102 @@ 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 ( tls->client_finished && tls->server_finished ); +} + +/****************************************************************************** + * + * Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier + * + ****************************************************************************** + */ + +/** + * Initialise MD5+SHA1 algorithm + * + * @v ctx MD5+SHA1 context + */ +static void md5_sha1_init ( void *ctx ) { + struct md5_sha1_context *context = ctx; + + digest_init ( &md5_algorithm, context->md5 ); + digest_init ( &sha1_algorithm, context->sha1 ); +} + +/** + * Accumulate data with MD5+SHA1 algorithm + * + * @v ctx MD5+SHA1 context + * @v data Data + * @v len Length of data + */ +static void md5_sha1_update ( void *ctx, const void *data, size_t len ) { + struct md5_sha1_context *context = ctx; + + digest_update ( &md5_algorithm, context->md5, data, len ); + digest_update ( &sha1_algorithm, context->sha1, data, len ); +} + +/** + * Generate MD5+SHA1 digest + * + * @v ctx MD5+SHA1 context + * @v out Output buffer + */ +static void md5_sha1_final ( void *ctx, void *out ) { + struct md5_sha1_context *context = ctx; + struct md5_sha1_digest *digest = out; + + digest_final ( &md5_algorithm, context->md5, digest->md5 ); + digest_final ( &sha1_algorithm, context->sha1, digest->sha1 ); +} + +/** Hybrid MD5+SHA1 digest algorithm */ +static struct digest_algorithm md5_sha1_algorithm = { + .name = "md5+sha1", + .ctxsize = sizeof ( struct md5_sha1_context ), + .blocksize = 0, /* Not applicable */ + .digestsize = sizeof ( struct md5_sha1_digest ), + .init = md5_sha1_init, + .update = md5_sha1_update, + .final = md5_sha1_final, +}; + +/** RSA digestInfo prefix for MD5+SHA1 algorithm */ +struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix = { + .digest = &md5_sha1_algorithm, + .data = NULL, /* MD5+SHA1 signatures have no digestInfo */ + .len = 0, +}; + /****************************************************************************** * * Cleanup functions @@ -88,8 +190,8 @@ static void free_tls ( struct refcnt *refcnt ) { 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 ); + x509_chain_put ( tls->chain ); /* Free TLS structure itself */ free ( tls ); @@ -105,10 +207,11 @@ static void tls_close ( struct tls_session *tls, int rc ) { /* 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 +224,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 +349,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 +447,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 +477,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 +489,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 +501,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 +526,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 +597,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 +612,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 +629,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; } - memset ( dynamic, 0, total ); /* Assign storage */ cipherspec->dynamic = dynamic; @@ -456,10 +645,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 +659,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; } /* 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,10 +698,7 @@ 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; } @@ -536,6 +708,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 +778,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,26 +790,20 @@ 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 ); + struct digest_algorithm *digest = tls->handshake_digest; + uint8_t ctx[ digest->ctxsize ]; - 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 ); + memcpy ( ctx, tls->handshake_ctx, sizeof ( ctx ) ); + digest_final ( digest, ctx, out ); } /****************************************************************************** * - * TX state machine transitions + * Record handling * ****************************************************************************** */ @@ -596,53 +817,6 @@ static void tls_tx_resume ( struct tls_session *tls ) { process_add ( &tls->process ); } -/** - * Enter TX state machine active state - * - * @v tls TLS session - * @v state TX state - */ -static void tls_tx_start ( struct tls_session *tls, enum tls_tx_state state ) { - - /* Enter specified state */ - tls->tx_state = state; - - /* Resume state machine */ - tls_tx_resume ( tls ); -} - -/** - * Enter TX state machine idle state - * - * @v tls TLS session - */ -static void tls_tx_none ( struct tls_session *tls ) { - - /* Enter idle state */ - tls->tx_state = TLS_TX_NONE; -} - -/** - * Enter TX state machine data state - * - * @v tls TLS session - */ -static void tls_tx_data ( struct tls_session *tls ) { - - /* Enter data state */ - tls->tx_state = TLS_TX_DATA; - - /* Send notification of a window change */ - xfer_window_changed ( &tls->plainstream ); -} - -/****************************************************************************** - * - * Record handling - * - ****************************************************************************** - */ - /** * Transmit Handshake record * @@ -674,25 +848,123 @@ 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; + } __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 ) ); return tls_send_handshake ( tls, &hello, sizeof ( hello ) ); } +/** + * Transmit Certificate record + * + * @v tls TLS session + * @ret rc Return status code + */ +static int tls_send_certificate ( struct tls_session *tls ) { + int num_certificates = ( have_client_certificate() ? 1 : 0 ); + struct { + uint32_t type_length; + uint8_t length[3]; + struct { + uint8_t length[3]; + uint8_t data[ client_certificate.len ]; + } __attribute__ (( packed )) certificates[num_certificates]; + } __attribute__ (( packed )) *certificate; + struct x509_certificate *cert; + int rc; + + /* If we have a certificate to send, determine the applicable + * public-key algorithm and schedule transmission of + * CertificateVerify. + */ + if ( num_certificates ) { + + /* Parse certificate to determine public-key algorithm */ + if ( ( rc = x509_certificate ( client_certificate.data, + client_certificate.len, + &cert ) ) != 0 ) { + DBGC ( tls, "TLS %p could not parse client " + "certificate: %s\n", tls, strerror ( rc ) ); + return rc; + } + tls->verify_pubkey = cert->signature_algorithm->pubkey; + x509_put ( cert ); + cert = NULL; + + /* Schedule CertificateVerify transmission */ + tls->tx_pending |= TLS_TX_CERTIFICATE_VERIFY; + tls_tx_resume ( tls ); + } + + /* Allocate storage for Certificate record (which may be too + * large for the stack). + */ + certificate = zalloc ( sizeof ( *certificate ) ); + if ( ! certificate ) + return -ENOMEM; + + /* Populate record */ + certificate->type_length = + ( cpu_to_le32 ( TLS_CERTIFICATE ) | + htonl ( sizeof ( *certificate ) - + sizeof ( certificate->type_length ) ) ); + tls_set_uint24 ( certificate->length, + sizeof ( certificate->certificates ) ); + if ( num_certificates ) { + tls_set_uint24 ( certificate->certificates[0].length, + sizeof ( certificate->certificates[0].data ) ); + memcpy ( certificate->certificates[0].data, + client_certificate.data, + sizeof ( certificate->certificates[0].data ) ); + } + + /* Transmit record */ + rc = tls_send_handshake ( tls, certificate, sizeof ( *certificate ) ); + + /* Free record */ + free ( certificate ); + + return rc; +} + /** * Transmit Client Key Exchange record * @@ -700,39 +972,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 ) ); + 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 ); - /* 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 ) - 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; - return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) ); + /* Generate digest to be signed */ + tls_verify_handshake ( tls, digest_out ); + + /* Initialise public-key algorithm */ + if ( ( rc = pubkey_init ( pubkey, ctx, client_private_key.data, + client_private_key.len ) ) != 0 ) { + DBGC ( tls, "TLS %p could not initialise %s client private " + "key: %s\n", tls, pubkey->name, strerror ( rc ) ); + goto err_pubkey_init; + } + + /* TLSv1.2 and later use explicit algorithm identifiers */ + if ( tls->version >= TLS_VERSION_TLS_1_2 ) { + sig_hash = tls_signature_hash_algorithm ( pubkey, digest ); + if ( ! sig_hash ) { + DBGC ( tls, "TLS %p could not identify (%s,%s) " + "signature and hash algorithm\n", tls, + pubkey->name, digest->name ); + rc = -ENOTSUP; + goto err_sig_hash; + } + } + + /* Generate and transmit record */ + { + size_t max_len = pubkey_max_len ( pubkey, ctx ); + int use_sig_hash = ( ( sig_hash == NULL ) ? 0 : 1 ); + struct { + uint32_t type_length; + struct tls_signature_hash_id sig_hash[use_sig_hash]; + uint16_t signature_len; + uint8_t signature[max_len]; + } __attribute__ (( packed )) certificate_verify; + size_t unused; + int len; + + /* Sign digest */ + len = pubkey_sign ( pubkey, ctx, digest, digest_out, + certificate_verify.signature ); + if ( len < 0 ) { + rc = len; + DBGC ( tls, "TLS %p could not sign %s digest using %s " + "client private key: %s\n", tls, digest->name, + pubkey->name, strerror ( rc ) ); + goto err_pubkey_sign; + } + unused = ( max_len - len ); + + /* Construct Certificate Verify record */ + certificate_verify.type_length = + ( cpu_to_le32 ( TLS_CERTIFICATE_VERIFY ) | + htonl ( sizeof ( certificate_verify ) - + sizeof ( certificate_verify.type_length ) - + unused ) ); + if ( use_sig_hash ) { + memcpy ( &certificate_verify.sig_hash[0], + &sig_hash->code, + sizeof ( certificate_verify.sig_hash[0] ) ); + } + certificate_verify.signature_len = + htons ( sizeof ( certificate_verify.signature ) - + unused ); + + /* Transmit record */ + rc = tls_send_handshake ( tls, &certificate_verify, + ( sizeof ( certificate_verify ) - unused ) ); + } + + err_pubkey_sign: + err_sig_hash: + pubkey_final ( pubkey, ctx ); + err_pubkey_init: + return rc; } /** @@ -754,22 +1117,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 */ + tls->client_finished = 1; + + return 0; } /** @@ -781,7 +1155,7 @@ 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 ) ) { @@ -809,13 +1183,14 @@ 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 ) ) { @@ -849,36 +1224,54 @@ 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; } - /* 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 ) ); + tls, ( version >> 8 ), ( version & 0xff ) ); return -ENOTSUP; } + if ( version > tls->version ) { + DBGC ( tls, "TLS %p server attempted to illegally upgrade to " + "protocol version %d.%d\n", + tls, ( version >> 8 ), ( version & 0xff ) ); + return -EPROTO; + } + tls->version = version; + DBGC ( tls, "TLS %p using protocol version %d.%d\n", + tls, ( version >> 8 ), ( version & 0xff ) ); + + /* Use MD5+SHA1 digest algorithm for handshake verification + * for versions earlier than TLSv1.2. + */ + if ( tls->version < TLS_VERSION_TLS_1_2 ) { + tls->handshake_digest = &md5_sha1_algorithm; + tls->handshake_ctx = tls->handshake_md5_sha1_ctx; + } /* Copy out server random bytes */ memcpy ( &tls->server_random, &hello_a->random, @@ -896,6 +1289,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; + goto err_alloc_chain; + } + + /* Add certificates to chain */ + while ( data < end ) { + + /* Extract raw certificate data */ + certificate = data; + certificate_len = tls_uint24 ( certificate->length ); + next = ( certificate->data + certificate_len ); + if ( next > end ) { + DBGC ( tls, "TLS %p overlength certificate:\n", tls ); + DBGC_HDA ( tls, 0, data, ( end - data ) ); + rc = -EINVAL; + goto err_overlength; + } + + /* Add certificate to chain */ + if ( ( rc = x509_append_raw ( tls->chain, certificate->data, + certificate_len ) ) != 0 ) { + DBGC ( tls, "TLS %p could not append certificate: %s\n", + tls, strerror ( rc ) ); + DBGC_HDA ( tls, 0, data, ( end - data ) ); + goto err_parse; + } + cert = x509_last ( tls->chain ); + DBGC ( tls, "TLS %p found certificate %s\n", + tls, cert->subject.name ); + + /* Move to next certificate in list */ + data = next; + } + + return 0; + + err_parse: + err_overlength: + x509_chain_put ( tls->chain ); + tls->chain = NULL; + err_alloc_chain: + return rc; +} + /** * Receive new Certificate handshake record * @@ -905,19 +1369,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 */ @@ -928,30 +1386,35 @@ static int tls_new_certificate ( struct tls_session *tls, return -EINVAL; } - /* 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 ) { - return -EINVAL; + /* We can only send a single certificate, so there is no point + * in parsing the Certificate Request. + */ + + /* Schedule Certificate transmission */ + tls->tx_pending |= TLS_TX_CERTIFICATE; + tls_tx_resume ( tls ); + + return 0; } /** @@ -963,11 +1426,12 @@ 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 ) ) { @@ -977,16 +1441,13 @@ static int tls_new_server_hello_done ( struct tls_session *tls, return -EINVAL; } - /* 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_start ( tls, TLS_TX_CLIENT_KEY_EXCHANGE ); - return 0; } @@ -999,12 +1460,39 @@ 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 ) ]; - /* FIXME: Handle this properly */ - tls_tx_data ( tls ); - ( void ) data; - ( void ) len; + /* Sanity check */ + if ( end != ( data + len ) ) { + DBGC ( tls, "TLS %p received overlength Finished\n", tls ); + DBGC_HD ( tls, data, len ); + return -EINVAL; + } + + /* Verify data */ + tls_verify_handshake ( tls, digest_out ); + tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ), + verify_data, sizeof ( verify_data ), "server finished", + digest_out, sizeof ( digest_out ) ); + if ( memcmp ( verify_data, finished->verify_data, + sizeof ( verify_data ) ) != 0 ) { + DBGC ( tls, "TLS %p verification failed\n", tls ); + return -EPERM; + } + + /* Mark server as finished */ + tls->server_finished = 1; + + /* Send notification of a window change */ + xfer_window_changed ( &tls->plainstream ); return 0; } @@ -1018,12 +1506,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]; @@ -1047,6 +1535,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 ); @@ -1089,8 +1581,8 @@ static int tls_new_handshake ( struct tls_session *tls, * @v len Length of plaintext record * @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, + const void *data, size_t len ) { switch ( type ) { case TLS_TYPE_CHANGE_CIPHER: @@ -1100,6 +1592,8 @@ static int tls_new_record ( struct tls_session *tls, case TLS_TYPE_HANDSHAKE: return tls_new_handshake ( tls, data, len ); case TLS_TYPE_DATA: + if ( ! tls_ready ( tls ) ) + return -ENOTCONN; return xfer_deliver_raw ( &tls->plainstream, data, len ); default: /* RFC4346 says that we should just ignore unknown @@ -1132,7 +1626,7 @@ static void tls_hmac ( struct tls_session *tls __unused, struct tls_cipherspec *cipherspec, uint64_t seq, struct tls_header *tlshdr, const void *data, size_t len, void *hmac ) { - struct digest_algorithm *digest = cipherspec->digest; + struct digest_algorithm *digest = cipherspec->suite->digest; uint8_t digest_ctx[digest->ctxsize]; hmac_init ( digest, digest_ctx, cipherspec->mac_secret, @@ -1158,7 +1652,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; @@ -1193,9 +1687,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; @@ -1203,8 +1697,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 ) ); @@ -1220,7 +1714,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 ) ); @@ -1242,17 +1736,18 @@ 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 */ @@ -1260,7 +1755,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, 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 { @@ -1290,13 +1785,12 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, /* 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 ); @@ -1313,8 +1807,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 ); @@ -1342,7 +1835,7 @@ static int tls_split_stream ( struct tls_session *tls, size_t mac_len; /* Decompose stream-ciphered data */ - mac_len = tls->rx_cipherspec.digest->digestsize; + mac_len = tls->rx_cipherspec.suite->digest->digestsize; if ( plaintext_len < mac_len ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); @@ -1385,18 +1878,19 @@ static int tls_split_block ( struct tls_session *tls, size_t padding_len; unsigned int i; - /* Decompose block-ciphered data */ + /* Sanity check */ if ( plaintext_len < 1 ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); return -EINVAL; } - iv_len = tls->rx_cipherspec.cipher->blocksize; - /* FIXME: TLSv1.1 uses an explicit IV */ - iv_len = 0; + /* TLSv1.1 and later use an explicit IV */ + iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? + tls->rx_cipherspec.suite->cipher->blocksize : 0 ); - mac_len = tls->rx_cipherspec.digest->digestsize; + /* Decompose block-ciphered data */ + mac_len = tls->rx_cipherspec.suite->digest->digestsize; padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) ); if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); @@ -1435,15 +1929,17 @@ static int tls_split_block ( struct tls_session *tls, * @ret rc Return status code */ static int tls_new_ciphertext ( struct tls_session *tls, - struct tls_header *tlshdr, void *ciphertext ) { + struct tls_header *tlshdr, + const void *ciphertext ) { struct tls_header plaintext_tlshdr; struct tls_cipherspec *cipherspec = &tls->rx_cipherspec; + struct cipher_algorithm *cipher = cipherspec->suite->cipher; size_t record_len = ntohs ( tlshdr->length ); void *plaintext = NULL; void *data; size_t len; void *mac; - size_t mac_len = cipherspec->digest->digestsize; + size_t mac_len = cipherspec->suite->digest->digestsize; uint8_t verify_mac[mac_len]; int rc; @@ -1457,11 +1953,11 @@ static int tls_new_ciphertext ( struct tls_session *tls, } /* Decrypt the record */ - cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx, + cipher_decrypt ( cipher, cipherspec->cipher_ctx, ciphertext, plaintext, record_len ); /* Split record into content and MAC */ - if ( is_stream_cipher ( cipherspec->cipher ) ) { + if ( is_stream_cipher ( cipher ) ) { if ( ( rc = tls_split_stream ( tls, plaintext, record_len, &data, &len, &mac ) ) != 0 ) goto done; @@ -1512,7 +2008,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 ); @@ -1532,7 +2028,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; } @@ -1689,6 +2185,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 @@ -1708,29 +2277,40 @@ static void tls_tx_step ( struct tls_session *tls ) { 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_none ( tls ); - break; - case 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 ) ); + 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_start ( tls, TLS_TX_CHANGE_CIPHER ); - break; - case TLS_TX_CHANGE_CIPHER: + tls->tx_pending &= ~TLS_TX_CERTIFICATE; + } else if ( tls->tx_pending & TLS_TX_CLIENT_KEY_EXCHANGE ) { + /* Send Client Key Exchange */ + if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) { + DBGC ( tls, "TLS %p could not send Client Key " + "Exchange: %s\n", tls, strerror ( rc ) ); + goto err; + } + tls->tx_pending &= ~TLS_TX_CLIENT_KEY_EXCHANGE; + } else if ( tls->tx_pending & TLS_TX_CERTIFICATE_VERIFY ) { + /* Send Certificate Verify */ + if ( ( rc = tls_send_certificate_verify ( tls ) ) != 0 ) { + DBGC ( tls, "TLS %p could not send Certificate " + "Verify: %s\n", tls, strerror ( rc ) ); + goto err; + } + tls->tx_pending &= ~TLS_TX_CERTIFICATE_VERIFY; + } else if ( tls->tx_pending & TLS_TX_CHANGE_CIPHER ) { /* Send Change Cipher, and then change the cipher in use */ if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) { DBGC ( tls, "TLS %p could not send Change Cipher: " @@ -1745,24 +2325,21 @@ static void tls_tx_step ( struct tls_session *tls ) { goto err; } tls->tx_seq = 0; - tls_tx_start ( tls, 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_none ( tls ); - 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: @@ -1780,35 +2357,53 @@ static struct process_descriptor tls_process_desc = ****************************************************************************** */ -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 ); - process_init_stopped ( &tls->process, &tls_process_desc, &tls->refcnt ); - tls_tx_start ( tls, TLS_TX_CLIENT_HELLO ); + tls->client_random.gmt_unix_time = time ( NULL ); + if ( ( rc = tls_generate_random ( tls, &tls->client_random.random, + ( sizeof ( tls->client_random.random ) ) ) ) != 0 ) { + goto err_random; + } + tls->pre_master_secret.version = htons ( tls->version ); + if ( ( rc = tls_generate_random ( tls, &tls->pre_master_secret.random, + ( sizeof ( tls->pre_master_secret.random ) ) ) ) != 0 ) { + goto err_random; + } + digest_init ( &md5_sha1_algorithm, tls->handshake_md5_sha1_ctx ); + digest_init ( &sha256_algorithm, tls->handshake_sha256_ctx ); + tls->handshake_digest = &sha256_algorithm; + tls->handshake_ctx = tls->handshake_sha256_ctx; + tls->tx_pending = TLS_TX_CLIENT_HELLO; /* Attach to parent interface, mortalise self, and return */ intf_plug_plug ( &tls->plainstream, xfer ); *next = &tls->cipherstream; ref_put ( &tls->refcnt ); return 0; + + err_random: + ref_put ( &tls->refcnt ); + err_alloc: + return rc; } diff --git a/src/net/udp.c b/src/net/udp.c index 5f452535..20badb7f 100644 --- a/src/net/udp.c +++ b/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/src/net/udp/syslog.c b/src/net/udp/syslog.c index 6d9fc216..4a265314 100644 --- a/src/net/udp/syslog.c +++ b/src/net/udp/syslog.c @@ -32,11 +32,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 ), }; @@ -60,22 +68,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,46 +112,21 @@ 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 ) + /* Fill line buffer */ + if ( line_putchar ( &syslog_line, character ) == 0 ) return; - /* Ignore carriage return */ - if ( character == '\r' ) - 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_PRIORITY ( SYSLOG_DEFAULT_FACILITY, + syslog_severity ), syslog_buffer ) ) != 0 ) { DBG ( "SYSLOG could not send log message: %s\n", strerror ( rc ) ); @@ -136,6 +139,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, }; /****************************************************************************** @@ -166,11 +171,11 @@ static int apply_syslog_settings ( void ) { int 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 +186,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/src/net/udp/tftp.c b/src/net/udp/tftp.c index 7cd211e4..a2d6473c 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -1214,14 +1214,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/src/net/validator.c b/src/net/validator.c new file mode 100644 index 00000000..80fecea8 --- /dev/null +++ b/src/net/validator.c @@ -0,0 +1,451 @@ +/* + * 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/validator.h> + +/** @file + * + * Certificate validator + * + */ + +/** A certificate validator */ +struct validator { + /** Reference count */ + struct refcnt refcnt; + /** Job control interface */ + struct interface job; + /** Data transfer interface */ + struct interface xfer; + /** Process */ + struct process process; + /** X.509 certificate chain */ + struct x509_chain *chain; + /** Data buffer */ + struct xfer_buffer buffer; +}; + +/** + * Free certificate validator + * + * @v refcnt Reference count + */ +static void validator_free ( struct refcnt *refcnt ) { + struct validator *validator = + container_of ( refcnt, struct validator, refcnt ); + + DBGC2 ( validator, "VALIDATOR %p freed\n", validator ); + x509_chain_put ( validator->chain ); + xferbuf_done ( &validator->buffer ); + free ( validator ); +} + +/** + * Mark certificate validation as finished + * + * @v validator Certificate validator + * @v rc Reason for finishing + */ +static void validator_finished ( struct validator *validator, int rc ) { + + /* Remove process */ + process_del ( &validator->process ); + + /* Close all interfaces */ + intf_shutdown ( &validator->xfer, rc ); + intf_shutdown ( &validator->job, rc ); +} + +/**************************************************************************** + * + * Job control interface + * + */ + +/** Certificate validator job control interface operations */ +static struct interface_operation validator_job_operations[] = { + INTF_OP ( intf_close, struct validator *, validator_finished ), +}; + +/** Certificate validator job control interface descriptor */ +static struct interface_descriptor validator_job_desc = + INTF_DESC ( struct validator, job, validator_job_operations ); + +/**************************************************************************** + * + * Cross-signing certificates + * + */ + +/** Cross-signed certificate source setting */ +struct setting crosscert_setting __setting ( SETTING_CRYPTO ) = { + .name = "crosscert", + .description = "Cross-signed certificate source", + .tag = DHCP_EB_CROSS_CERT, + .type = &setting_type_string, +}; + +/** Default cross-signed certificate source */ +static const char crosscert_default[] = "http://ca.ipxe.org/auto"; + +/** + * Start download of cross-signing certificate + * + * @v validator Certificate validator + * @v issuer Required issuer + * @ret rc Return status code + */ +static int validator_start_download ( struct validator *validator, + const struct asn1_cursor *issuer ) { + const char *crosscert; + char *crosscert_copy; + char *uri_string; + size_t uri_string_len; + uint32_t crc; + int len; + int rc; + + /* Determine cross-signed certificate source */ + len = fetch_string_setting_copy ( NULL, &crosscert_setting, + &crosscert_copy ); + if ( len < 0 ) { + rc = len; + DBGC ( validator, "VALIDATOR %p could not fetch crosscert " + "setting: %s\n", validator, strerror ( rc ) ); + goto err_fetch_crosscert; + } + crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default ); + + /* Allocate URI string */ + uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */ + + base64_encoded_len ( issuer->len ) + 1 /* NUL */ ); + uri_string = zalloc ( uri_string_len ); + if ( ! uri_string ) { + rc = -ENOMEM; + goto err_alloc_uri_string; + } + + /* Generate CRC32 */ + crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len ); + + /* Generate URI string */ + len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=", + crosscert, crc ); + base64_encode ( issuer->data, issuer->len, ( uri_string + len ) ); + DBGC ( validator, "VALIDATOR %p downloading cross-signed certificate " + "from %s\n", validator, uri_string ); + + /* Open URI */ + if ( ( rc = xfer_open_uri_string ( &validator->xfer, + uri_string ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not open %s: %s\n", + validator, uri_string, strerror ( rc ) ); + goto err_open_uri_string; + } + + /* Success */ + rc = 0; + + err_open_uri_string: + free ( uri_string ); + err_alloc_uri_string: + free ( crosscert_copy ); + err_fetch_crosscert: + return rc; +} + +/** + * Append cross-signing certificates to certificate chain + * + * @v validator Certificate validator + * @v data Raw cross-signing certificate data + * @v len Length of raw data + * @ret rc Return status code + */ +static int validator_append ( struct validator *validator, + const void *data, size_t len ) { + struct asn1_cursor cursor; + struct x509_chain *certs; + struct x509_certificate *cert; + struct x509_certificate *last; + int rc; + + /* Allocate certificate list */ + certs = x509_alloc_chain(); + if ( ! certs ) { + rc = -ENOMEM; + goto err_alloc_certs; + } + + /* Initialise cursor */ + cursor.data = data; + cursor.len = len; + + /* Enter certificateSet */ + if ( ( rc = asn1_enter ( &cursor, ASN1_SET ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not enter " + "certificateSet: %s\n", validator, strerror ( rc ) ); + goto err_certificateset; + } + + /* Add each certificate to list */ + while ( cursor.len ) { + + /* Add certificate to chain */ + if ( ( rc = x509_append_raw ( certs, cursor.data, + cursor.len ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not append " + "certificate: %s\n", + validator, strerror ( rc) ); + DBGC_HDA ( validator, 0, cursor.data, cursor.len ); + return rc; + } + cert = x509_last ( certs ); + DBGC ( validator, "VALIDATOR %p found certificate %s\n", + validator, cert->subject.name ); + + /* Move to next certificate */ + asn1_skip_any ( &cursor ); + } + + /* Append certificates to chain */ + last = x509_last ( validator->chain ); + if ( ( rc = x509_auto_append ( validator->chain, certs ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not append " + "certificates: %s\n", validator, strerror ( rc ) ); + goto err_auto_append; + } + + /* Check that at least one certificate has been added */ + if ( last == x509_last ( validator->chain ) ) { + DBGC ( validator, "VALIDATOR %p failed to append any " + "applicable certificates\n", validator ); + rc = -EACCES; + goto err_no_progress; + } + + /* Drop reference to certificate list */ + x509_chain_put ( certs ); + + return 0; + + err_no_progress: + err_auto_append: + err_certificateset: + x509_chain_put ( certs ); + err_alloc_certs: + return rc; +} + +/**************************************************************************** + * + * Data transfer interface + * + */ + +/** + * Close data transfer interface + * + * @v validator Certificate validator + * @v rc Reason for close + */ +static void validator_xfer_close ( struct validator *validator, int rc ) { + + /* Close data transfer interface */ + intf_restart ( &validator->xfer, rc ); + + /* Check for errors */ + if ( rc != 0 ) { + DBGC ( validator, "VALIDATOR %p download failed: %s\n", + validator, strerror ( rc ) ); + goto err_download; + } + DBGC2 ( validator, "VALIDATOR %p download complete\n", validator ); + + /* Append downloaded certificates */ + if ( ( rc = validator_append ( validator, validator->buffer.data, + validator->buffer.len ) ) != 0 ) + goto err_append; + + /* Free downloaded data */ + xferbuf_done ( &validator->buffer ); + + /* Resume validation process */ + process_add ( &validator->process ); + + return; + + err_append: + err_download: + validator_finished ( validator, rc ); +} + +/** + * Receive data + * + * @v validator Certificate validator + * @v iobuf I/O buffer + * @v meta Data transfer metadata + * @ret rc Return status code + */ +static int validator_xfer_deliver ( struct validator *validator, + struct io_buffer *iobuf, + struct xfer_metadata *meta ) { + int rc; + + /* Add data to buffer */ + if ( ( rc = xferbuf_deliver ( &validator->buffer, iob_disown ( iobuf ), + meta ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not receive data: %s\n", + validator, strerror ( rc ) ); + validator_finished ( validator, rc ); + return rc; + } + + return 0; +} + +/** Certificate validator data transfer interface operations */ +static struct interface_operation validator_xfer_operations[] = { + INTF_OP ( xfer_deliver, struct validator *, validator_xfer_deliver ), + INTF_OP ( intf_close, struct validator *, validator_xfer_close ), +}; + +/** Certificate validator data transfer interface descriptor */ +static struct interface_descriptor validator_xfer_desc = + INTF_DESC ( struct validator, xfer, validator_xfer_operations ); + +/**************************************************************************** + * + * Validation process + * + */ + +/** + * Certificate validation process + * + * @v validator Certificate validator + */ +static void validator_step ( struct validator *validator ) { + struct x509_certificate *last = x509_last ( validator->chain ); + time_t now; + int rc; + + /* Try validating chain. Try even if the chain is incomplete, + * since certificates may already have been validated + * previously. + */ + now = time ( NULL ); + if ( ( rc = x509_validate_chain ( validator->chain, now, + NULL ) ) == 0 ) { + validator_finished ( validator, 0 ); + return; + } + + /* If chain ends with a self-issued certificate, then there is + * nothing more to do. + */ + if ( asn1_compare ( &last->issuer.raw, &last->subject.raw ) == 0 ) { + validator_finished ( validator, rc ); + return; + } + + /* Otherwise, try to download a suitable cross-signing + * certificate. + */ + if ( ( rc = validator_start_download ( validator, + &last->issuer.raw ) ) != 0 ) { + validator_finished ( validator, rc ); + return; + } +} + +/** Certificate validator process descriptor */ +static struct process_descriptor validator_process_desc = + PROC_DESC_ONCE ( struct validator, process, validator_step ); + +/**************************************************************************** + * + * Instantiator + * + */ + +/** + * Instantiate a certificate validator + * + * @v job Job control interface + * @v chain X.509 certificate chain + * @ret rc Return status code + */ +int create_validator ( struct interface *job, struct x509_chain *chain ) { + struct validator *validator; + int rc; + + /* Sanity check */ + if ( ! chain ) { + rc = -EINVAL; + goto err_sanity; + } + + /* Allocate and initialise structure */ + validator = zalloc ( sizeof ( *validator ) ); + if ( ! validator ) { + rc = -ENOMEM; + goto err_alloc; + } + ref_init ( &validator->refcnt, validator_free ); + intf_init ( &validator->job, &validator_job_desc, + &validator->refcnt ); + intf_init ( &validator->xfer, &validator_xfer_desc, + &validator->refcnt ); + process_init ( &validator->process, &validator_process_desc, + &validator->refcnt ); + validator->chain = x509_chain_get ( chain ); + + /* Attach parent interface, mortalise self, and return */ + intf_plug_plug ( &validator->job, job ); + ref_put ( &validator->refcnt ); + DBGC2 ( validator, "VALIDATOR %p validating X509 chain %p\n", + validator, validator->chain ); + return 0; + + validator_finished ( validator, rc ); + ref_put ( &validator->refcnt ); + err_alloc: + err_sanity: + return rc; +} diff --git a/src/tests/aes_cbc_test.c b/src/tests/aes_cbc_test.c new file mode 100644 index 00000000..371ec81b --- /dev/null +++ b/src/tests/aes_cbc_test.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * AES-in-CBC-mode tests + * + * These test vectors are provided by NIST as part of the + * Cryptographic Toolkit Examples, downloadable from: + * + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CBC.pdf + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <assert.h> +#include <string.h> +#include <ipxe/aes.h> +#include <ipxe/test.h> +#include "cbc_test.h" + +/** Define inline key */ +#define KEY(...) { __VA_ARGS__ } + +/** Define inline initialisation vector */ +#define IV(...) { __VA_ARGS__ } + +/** Define inline plaintext data */ +#define PLAINTEXT(...) { __VA_ARGS__ } + +/** Define inline ciphertext data */ +#define CIPHERTEXT(...) { __VA_ARGS__ } + +/** An AES-in-CBC-mode test */ +struct aes_cbc_test { + /** Key */ + const void *key; + /** Length of key */ + size_t key_len; + /** Initialisation vector */ + const void *iv; + /** Length of initialisation vector */ + size_t iv_len; + /** Plaintext */ + const void *plaintext; + /** Length of plaintext */ + size_t plaintext_len; + /** Ciphertext */ + const void *ciphertext; + /** Length of ciphertext */ + size_t ciphertext_len; +}; + +/** + * Define an AES-in-CBC-mode test + * + * @v name Test name + * @v key_array Key + * @v iv_array Initialisation vector + * @v plaintext_array Plaintext + * @v ciphertext_array Ciphertext + * @ret test AES-in-CBC-mode test + */ +#define AES_CBC_TEST( name, key_array, iv_array, plaintext_array, \ + ciphertext_array ) \ + static const uint8_t name ## _key [] = key_array; \ + static const uint8_t name ## _iv [] = iv_array; \ + static const uint8_t name ## _plaintext [] = plaintext_array; \ + static const uint8_t name ## _ciphertext [] = ciphertext_array; \ + static struct aes_cbc_test name = { \ + .key = name ## _key, \ + .key_len = sizeof ( name ## _key ), \ + .iv = name ## _iv, \ + .iv_len = sizeof ( name ## _iv ), \ + .plaintext = name ## _plaintext, \ + .plaintext_len = sizeof ( name ## _plaintext ), \ + .ciphertext = name ## _ciphertext, \ + .ciphertext_len = sizeof ( name ## _ciphertext ), \ + } + +/** + * Report AES-in-CBC-mode + * + * @v state HMAC_DRBG internal state + * @v test Instantiation test + */ +#define aes_cbc_ok( test ) do { \ + struct cipher_algorithm *cipher = &aes_cbc_algorithm; \ + \ + assert ( (test)->iv_len == cipher->blocksize ); \ + assert ( (test)->plaintext_len == (test)->ciphertext_len ); \ + cbc_encrypt_ok ( cipher, (test)->key, (test)->key_len, \ + (test)->iv, (test)->plaintext, \ + (test)->ciphertext, (test)->plaintext_len ); \ + cbc_decrypt_ok ( cipher, (test)->key, (test)->key_len, \ + (test)->iv, (test)->ciphertext, \ + (test)->plaintext, (test)->ciphertext_len ); \ + } while ( 0 ) + +/** CBC_AES128 */ +AES_CBC_TEST ( test_128, + KEY ( 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, + 0x88, 0x09, 0xcf, 0x4f, 0x3c ), + IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ), + PLAINTEXT ( 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ), + CIPHERTEXT ( 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, + 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, + 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ) ); + +/** CBC_AES256 */ +AES_CBC_TEST ( test_256, + KEY ( 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, + 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, + 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ), + IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ), + PLAINTEXT ( 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ), + CIPHERTEXT ( 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, + 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ) ); + +/** + * Perform AES-in-CBC-mode self-test + * + */ +static void aes_cbc_test_exec ( void ) { + + aes_cbc_ok ( &test_128 ); + aes_cbc_ok ( &test_256 ); +} + +/** AES-in-CBC-mode self-test */ +struct self_test aes_cbc_test __self_test = { + .name = "aes_cbc", + .exec = aes_cbc_test_exec, +}; diff --git a/src/tests/bigint_test.c b/src/tests/bigint_test.c new file mode 100644 index 00000000..4052131f --- /dev/null +++ b/src/tests/bigint_test.c @@ -0,0 +1,2436 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Big integer self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <assert.h> +#include <string.h> +#include <ipxe/bigint.h> +#include <ipxe/test.h> + +/** Define inline big integer */ +#define BIGINT(...) { __VA_ARGS__ } + +/* Provide global functions to allow inspection of generated assembly code */ + +void bigint_init_sample ( bigint_element_t *value0, unsigned int size, + const void *data, size_t len ) { + bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( void * ) value0 ); + + bigint_init ( value, data, len ); +} + +void bigint_done_sample ( const bigint_element_t *value0, unsigned int size, + void *out, size_t len ) { + const bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( const void * ) value0 ); + + bigint_done ( value, out, len ); +} + +void bigint_add_sample ( const bigint_element_t *addend0, + bigint_element_t *value0, unsigned int size ) { + const bigint_t ( size ) *addend __attribute__ (( may_alias )) + = ( ( const void * ) addend0 ); + bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( void * ) value0 ); + + bigint_add ( addend, value ); +} + +void bigint_subtract_sample ( const bigint_element_t *subtrahend0, + bigint_element_t *value0, unsigned int size ) { + const bigint_t ( size ) *subtrahend __attribute__ (( may_alias )) + = ( ( const void * ) subtrahend0 ); + bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( void * ) value0 ); + + bigint_subtract ( subtrahend, value ); +} + +void bigint_rol_sample ( bigint_element_t *value0, unsigned int size ) { + bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( void * ) value0 ); + + bigint_rol ( value ); +} + +void bigint_ror_sample ( bigint_element_t *value0, unsigned int size ) { + bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( void * ) value0 ); + + bigint_ror ( value ); +} + +int bigint_is_zero_sample ( const bigint_element_t *value0, + unsigned int size ) { + const bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( const void * ) value0 ); + + return bigint_is_zero ( value ); +} + +int bigint_is_geq_sample ( const bigint_element_t *value0, + const bigint_element_t *reference0, + unsigned int size ) { + const bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( const void * ) value0 ); + const bigint_t ( size ) *reference __attribute__ (( may_alias )) + = ( ( const void * ) reference0 ); + + return bigint_is_geq ( value, reference ); +} + +int bigint_bit_is_set_sample ( const bigint_element_t *value0, + unsigned int size, unsigned int bit ) { + const bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( const void * ) value0 ); + + return bigint_bit_is_set ( value, bit ); +} + +int bigint_max_set_bit_sample ( const bigint_element_t *value0, + unsigned int size ) { + const bigint_t ( size ) *value __attribute__ (( may_alias )) + = ( ( const void * ) value0 ); + + return bigint_max_set_bit ( value ); +} + +void bigint_grow_sample ( const bigint_element_t *source0, + unsigned int source_size, bigint_element_t *dest0, + unsigned int dest_size ) { + const bigint_t ( source_size ) *source __attribute__ (( may_alias )) + = ( ( const void * ) source0 ); + bigint_t ( dest_size ) *dest __attribute__ (( may_alias )) + = ( ( void * ) dest0 ); + + bigint_grow ( source, dest ); +} + +void bigint_shrink_sample ( const bigint_element_t *source0, + unsigned int source_size, bigint_element_t *dest0, + unsigned int dest_size ) { + const bigint_t ( source_size ) *source __attribute__ (( may_alias )) + = ( ( const void * ) source0 ); + bigint_t ( dest_size ) *dest __attribute__ (( may_alias )) + = ( ( void * ) dest0 ); + + bigint_shrink ( source, dest ); +} + +void bigint_multiply_sample ( const bigint_element_t *multiplicand0, + const bigint_element_t *multiplier0, + bigint_element_t *result0, + unsigned int size ) { + const bigint_t ( size ) *multiplicand __attribute__ (( may_alias )) + = ( ( const void * ) multiplicand0 ); + const bigint_t ( size ) *multiplier __attribute__ (( may_alias )) + = ( ( const void * ) multiplier0 ); + bigint_t ( size * 2 ) *result __attribute__ (( may_alias )) + = ( ( void * ) result0 ); + + bigint_multiply ( multiplicand, multiplier, result ); +} + +void bigint_mod_multiply_sample ( const bigint_element_t *multiplicand0, + const bigint_element_t *multiplier0, + const bigint_element_t *modulus0, + bigint_element_t *result0, + unsigned int size, + void *tmp ) { + const bigint_t ( size ) *multiplicand __attribute__ (( may_alias )) + = ( ( const void * ) multiplicand0 ); + const bigint_t ( size ) *multiplier __attribute__ (( may_alias )) + = ( ( const void * ) multiplier0 ); + const bigint_t ( size ) *modulus __attribute__ (( may_alias )) + = ( ( const void * ) modulus0 ); + bigint_t ( size ) *result __attribute__ (( may_alias )) + = ( ( void * ) result0 ); + + bigint_mod_multiply ( multiplicand, multiplier, modulus, result, tmp ); +} + +void bigint_mod_exp_sample ( const bigint_element_t *base0, + const bigint_element_t *modulus0, + const bigint_element_t *exponent0, + bigint_element_t *result0, + unsigned int size, unsigned int exponent_size, + void *tmp ) { + const bigint_t ( size ) *base __attribute__ (( may_alias )) + = ( ( const void * ) base0 ); + const bigint_t ( size ) *modulus __attribute__ (( may_alias )) + = ( ( const void * ) modulus0 ); + const bigint_t ( exponent_size ) *exponent __attribute__ (( may_alias )) + = ( ( const void * ) exponent0 ); + bigint_t ( size ) *result __attribute__ (( may_alias )) + = ( ( void * ) result0 ); + + bigint_mod_exp ( base, modulus, exponent, result, tmp ); +} + +/** + * Report result of big integer addition test + * + * @v addend Big integer to add + * @v value Big integer to be added to + * @v expected Big integer expected result + */ +#define bigint_add_ok( addend, value, expected ) do { \ + static const uint8_t addend_raw[] = addend; \ + static const uint8_t value_raw[] = value; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) addend_temp; \ + bigint_t ( size ) value_temp; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &addend_temp ) == \ + bigint_size ( &value_temp ) ); \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + bigint_init ( &addend_temp, addend_raw, \ + sizeof ( addend_raw ) ); \ + DBG ( "Add:\n" ); \ + DBG_HDA ( 0, &addend_temp, sizeof ( addend_temp ) ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_add ( &addend_temp, &value_temp ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer subtraction test + * + * @v subtrahend Big integer to subtract + * @v value Big integer to be subtracted from + * @v expected Big integer expected result + */ +#define bigint_subtract_ok( subtrahend, value, expected ) do { \ + static const uint8_t subtrahend_raw[] = subtrahend; \ + static const uint8_t value_raw[] = value; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) subtrahend_temp; \ + bigint_t ( size ) value_temp; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &subtrahend_temp ) == \ + bigint_size ( &value_temp ) ); \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + bigint_init ( &subtrahend_temp, subtrahend_raw, \ + sizeof ( subtrahend_raw ) ); \ + DBG ( "Subtract:\n" ); \ + DBG_HDA ( 0, &subtrahend_temp, sizeof ( subtrahend_temp ) ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_subtract ( &subtrahend_temp, &value_temp ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer left rotation test + * + * @v value Big integer + * @v expected Big integer expected result + */ +#define bigint_rol_ok( value, expected ) do { \ + static const uint8_t value_raw[] = value; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + {} /* Fix emacs alignment */ \ + \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + DBG ( "Rotate left:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_rol ( &value_temp ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer right rotation test + * + * @v value Big integer + * @v expected Big integer expected result + */ +#define bigint_ror_ok( value, expected ) do { \ + static const uint8_t value_raw[] = value; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + {} /* Fix emacs alignment */ \ + \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + DBG ( "Rotate right:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_ror ( &value_temp ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bigint_done ( &value_temp, result_raw, sizeof ( result_raw ) ); \ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer zero comparison test + * + * @v value Big integer + * @v expected Expected result + */ +#define bigint_is_zero_ok( value, expected ) do { \ + static const uint8_t value_raw[] = value; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + int is_zero; \ + {} /* Fix emacs alignment */ \ + \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + DBG ( "Zero comparison:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + is_zero = bigint_is_zero ( &value_temp ); \ + DBG ( "...is %szero\n", ( is_zero ? "" : "not " ) ); \ + ok ( ( !! is_zero ) == ( !! (expected) ) ); \ + } while ( 0 ) + +/** + * Report result of big integer greater-than-or-equal comparison test + * + * @v value Big integer + * @v reference Reference big integer + * @v expected Expected result + */ +#define bigint_is_geq_ok( value, reference, expected ) do { \ + static const uint8_t value_raw[] = value; \ + static const uint8_t reference_raw[] = reference; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + bigint_t ( size ) reference_temp; \ + int is_geq; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &reference_temp ) == \ + bigint_size ( &value_temp ) ); \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + bigint_init ( &reference_temp, reference_raw, \ + sizeof ( reference_raw ) ); \ + DBG ( "Greater-than-or-equal comparison:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + DBG_HDA ( 0, &reference_temp, sizeof ( reference_temp ) ); \ + is_geq = bigint_is_geq ( &value_temp, &reference_temp ); \ + DBG ( "...is %sgreater than or equal\n", \ + ( is_geq ? "" : "not " ) ); \ + ok ( ( !! is_geq ) == ( !! (expected) ) ); \ + } while ( 0 ) + +/** + * Report result of big integer bit-set test + * + * @v value Big integer + * @v bit Bit to test + * @v expected Expected result + */ +#define bigint_bit_is_set_ok( value, bit, expected ) do { \ + static const uint8_t value_raw[] = value; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + int bit_is_set; \ + {} /* Fix emacs alignment */ \ + \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + DBG ( "Bit set:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + bit_is_set = bigint_bit_is_set ( &value_temp, bit ); \ + DBG ( "...bit %d is %sset\n", bit, \ + ( bit_is_set ? "" : "not " ) ); \ + ok ( ( !! bit_is_set ) == ( !! (expected) ) ); \ + } while ( 0 ) + +/** + * Report result of big integer maximum set bit test + * + * @v value Big integer + * @v expected Expected result + */ +#define bigint_max_set_bit_ok( value, expected ) do { \ + static const uint8_t value_raw[] = value; \ + unsigned int size = \ + bigint_required_size ( sizeof ( value_raw ) ); \ + bigint_t ( size ) value_temp; \ + int max_set_bit; \ + {} /* Fix emacs alignment */ \ + \ + bigint_init ( &value_temp, value_raw, sizeof ( value_raw ) ); \ + DBG ( "Maximum set bit:\n" ); \ + DBG_HDA ( 0, &value_temp, sizeof ( value_temp ) ); \ + max_set_bit = bigint_max_set_bit ( &value_temp ); \ + DBG ( "...maximum set bit is bit %d\n", ( max_set_bit - 1 ) ); \ + ok ( max_set_bit == (expected) ); \ + } while ( 0 ) + +/** + * Report result of big integer multiplication test + * + * @v multiplicand Big integer to be multiplied + * @v multiplier Big integer to be multiplied + * @v expected Big integer expected result + */ +#define bigint_multiply_ok( multiplicand, multiplier, expected ) do { \ + static const uint8_t multiplicand_raw[] = multiplicand; \ + static const uint8_t multiplier_raw[] = multiplier; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( multiplicand_raw ) ); \ + bigint_t ( size ) multiplicand_temp; \ + bigint_t ( size ) multiplier_temp; \ + bigint_t ( size * 2 ) result_temp; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &multiplier_temp ) == \ + bigint_size ( &multiplicand_temp ) ); \ + assert ( bigint_size ( &result_temp ) == \ + ( 2 * bigint_size ( &multiplicand_temp ) ) ); \ + bigint_init ( &multiplicand_temp, multiplicand_raw, \ + sizeof ( multiplicand_raw ) ); \ + bigint_init ( &multiplier_temp, multiplier_raw, \ + sizeof ( multiplier_raw ) ); \ + DBG ( "Multiply:\n" ); \ + DBG_HDA ( 0, &multiplicand_temp, sizeof ( multiplicand_temp ) );\ + DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) ); \ + bigint_multiply ( &multiplicand_temp, &multiplier_temp, \ + &result_temp ); \ + DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \ + bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer modular multiplication test + * + * @v multiplicand Big integer to be multiplied + * @v multiplier Big integer to be multiplied + * @v modulus Big integer modulus + * @v expected Big integer expected result + */ +#define bigint_mod_multiply_ok( multiplicand, multiplier, modulus, \ + expected ) do { \ + static const uint8_t multiplicand_raw[] = multiplicand; \ + static const uint8_t multiplier_raw[] = multiplier; \ + static const uint8_t modulus_raw[] = modulus; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( multiplicand_raw ) ); \ + bigint_t ( size ) multiplicand_temp; \ + bigint_t ( size ) multiplier_temp; \ + bigint_t ( size ) modulus_temp; \ + bigint_t ( size ) result_temp; \ + size_t tmp_len = bigint_mod_multiply_tmp_len ( &modulus_temp ); \ + uint8_t tmp[tmp_len]; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &multiplier_temp ) == \ + bigint_size ( &multiplicand_temp ) ); \ + assert ( bigint_size ( &multiplier_temp ) == \ + bigint_size ( &modulus_temp ) ); \ + assert ( bigint_size ( &multiplier_temp ) == \ + bigint_size ( &result_temp ) ); \ + bigint_init ( &multiplicand_temp, multiplicand_raw, \ + sizeof ( multiplicand_raw ) ); \ + bigint_init ( &multiplier_temp, multiplier_raw, \ + sizeof ( multiplier_raw ) ); \ + bigint_init ( &modulus_temp, modulus_raw, \ + sizeof ( modulus_raw ) ); \ + DBG ( "Modular multiply:\n" ); \ + DBG_HDA ( 0, &multiplicand_temp, sizeof ( multiplicand_temp ) );\ + DBG_HDA ( 0, &multiplier_temp, sizeof ( multiplier_temp ) ); \ + DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) ); \ + bigint_mod_multiply ( &multiplicand_temp, &multiplier_temp, \ + &modulus_temp, &result_temp, tmp ); \ + DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \ + bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report result of big integer modular exponentiation test + * + * @v base Big integer base + * @v modulus Big integer modulus + * @v exponent Big integer exponent + * @v expected Big integer expected result + */ +#define bigint_mod_exp_ok( base, modulus, exponent, expected ) do { \ + static const uint8_t base_raw[] = base; \ + static const uint8_t modulus_raw[] = modulus; \ + static const uint8_t exponent_raw[] = exponent; \ + static const uint8_t expected_raw[] = expected; \ + uint8_t result_raw[ sizeof ( expected_raw ) ]; \ + unsigned int size = \ + bigint_required_size ( sizeof ( base_raw ) ); \ + unsigned int exponent_size = \ + bigint_required_size ( sizeof ( exponent_raw ) ); \ + bigint_t ( size ) base_temp; \ + bigint_t ( size ) modulus_temp; \ + bigint_t ( exponent_size ) exponent_temp; \ + bigint_t ( size ) result_temp; \ + size_t tmp_len = bigint_mod_exp_tmp_len ( &modulus_temp, \ + &exponent_temp ); \ + uint8_t tmp[tmp_len]; \ + {} /* Fix emacs alignment */ \ + \ + assert ( bigint_size ( &modulus_temp ) == \ + bigint_size ( &base_temp ) ); \ + assert ( bigint_size ( &modulus_temp ) == \ + bigint_size ( &result_temp ) ); \ + bigint_init ( &base_temp, base_raw, sizeof ( base_raw ) ); \ + bigint_init ( &modulus_temp, modulus_raw, \ + sizeof ( modulus_raw ) ); \ + bigint_init ( &exponent_temp, exponent_raw, \ + sizeof ( exponent_raw ) ); \ + DBG ( "Modular exponentiation:\n" ); \ + DBG_HDA ( 0, &base_temp, sizeof ( base_temp ) ); \ + DBG_HDA ( 0, &modulus_temp, sizeof ( modulus_temp ) ); \ + DBG_HDA ( 0, &exponent_temp, sizeof ( exponent_temp ) ); \ + bigint_mod_exp ( &base_temp, &modulus_temp, &exponent_temp, \ + &result_temp, tmp ); \ + DBG_HDA ( 0, &result_temp, sizeof ( result_temp ) ); \ + bigint_done ( &result_temp, result_raw, sizeof ( result_raw ) );\ + \ + ok ( memcmp ( result_raw, expected_raw, \ + sizeof ( result_raw ) ) == 0 ); \ + } while ( 0 ) + +/** + * Perform big integer self-tests + * + */ +static void bigint_test_exec ( void ) { + + bigint_add_ok ( BIGINT ( 0x8a ), + BIGINT ( 0x43 ), + BIGINT ( 0xcd ) ); + bigint_add_ok ( BIGINT ( 0xc5, 0x7b ), + BIGINT ( 0xd6, 0xb1 ), + BIGINT ( 0x9c, 0x2c ) ); + bigint_add_ok ( BIGINT ( 0xf9, 0xd9, 0xdc ), + BIGINT ( 0x6d, 0x4b, 0xca ), + BIGINT ( 0x67, 0x25, 0xa6 ) ); + bigint_add_ok ( BIGINT ( 0xdd, 0xc2, 0x20, 0x5f ), + BIGINT ( 0x80, 0x32, 0xc4, 0xb0 ), + BIGINT ( 0x5d, 0xf4, 0xe5, 0x0f ) ); + bigint_add_ok ( BIGINT ( 0x01, 0xed, 0x45, 0x4b, 0x41, 0xeb, 0x4c, + 0x2e, 0x53, 0x07, 0x15, 0x51, 0x56, 0x47, + 0x29, 0xfc, 0x9c, 0xbd, 0xbd, 0xfb, 0x1b, + 0xd1, 0x1d ), + BIGINT ( 0x73, 0xed, 0xfc, 0x35, 0x31, 0x22, 0xd7, + 0xb1, 0xea, 0x91, 0x5a, 0xe4, 0xba, 0xbc, + 0xa1, 0x38, 0x72, 0xae, 0x4b, 0x1c, 0xc1, + 0x05, 0xb3 ), + BIGINT ( 0x75, 0xdb, 0x41, 0x80, 0x73, 0x0e, 0x23, + 0xe0, 0x3d, 0x98, 0x70, 0x36, 0x11, 0x03, + 0xcb, 0x35, 0x0f, 0x6c, 0x09, 0x17, 0xdc, + 0xd6, 0xd0 ) ); + bigint_add_ok ( BIGINT ( 0x06, 0x8e, 0xd6, 0x18, 0xbb, 0x4b, 0x0c, + 0xc5, 0x85, 0xde, 0xee, 0x9b, 0x3f, 0x65, + 0x63, 0x86, 0xf5, 0x5a, 0x9f, 0xa2, 0xd7, + 0xb2, 0xc7, 0xb6, 0x1d, 0x28, 0x6c, 0x50, + 0x47, 0x10, 0x0a, 0x0e, 0x86, 0xcd, 0x2a, + 0x64, 0xdc, 0xe6, 0x9d, 0x96, 0xd8, 0xf4, + 0x56, 0x46, 0x6f, 0xbb, 0x7b, 0x64, 0x6f, + 0xdc, 0x2a, 0xd1, 0x3b, 0xcc, 0x03, 0x85, + 0x95, 0xf4, 0xe9, 0x68, 0x1f, 0x5c, 0xc5, + 0xbf, 0x97, 0x19, 0x12, 0x88, 0x2e, 0x88, + 0xb9, 0x34, 0xac, 0x74, 0x83, 0x2d, 0x8f, + 0xb3, 0x97, 0x53, 0x99, 0xf3, 0xb4, 0x8b, + 0x2d, 0x98, 0x69, 0x8d, 0x19, 0xf0, 0x40, + 0x66, 0x3f, 0x60, 0x78, 0x34, 0x7f, 0x9b, + 0xf7, 0x01, 0x74, 0x55, 0xca, 0x63, 0x25, + 0x7b, 0x86, 0xe9, 0x73, 0xfd, 0x5d, 0x77, + 0x32, 0x5e, 0x9e, 0x42, 0x53, 0xb6, 0x35, + 0x92, 0xb9, 0xd7, 0x1b, 0xf7, 0x16, 0x55, + 0xf6, 0xe2 ), + BIGINT ( 0x3f, 0x8f, 0x62, 0x21, 0x4a, 0x7a, 0xa2, + 0xef, 0xa8, 0x79, 0x9b, 0x73, 0xac, 0xde, + 0x72, 0xe4, 0xfc, 0x3c, 0xd3, 0xa9, 0x44, + 0x1a, 0x6a, 0x02, 0x76, 0xe3, 0x78, 0x4d, + 0x2e, 0x07, 0x9b, 0xb6, 0x3d, 0x5d, 0xc5, + 0xcd, 0x68, 0x23, 0x4b, 0x5f, 0x89, 0x0e, + 0xd7, 0xa7, 0xff, 0x18, 0x80, 0xdc, 0xfb, + 0x34, 0x45, 0xca, 0x4b, 0xdb, 0x8a, 0x19, + 0xcb, 0xc9, 0xe5, 0xa1, 0x63, 0xa2, 0x0d, + 0x56, 0xc4, 0xf9, 0x51, 0x1b, 0x88, 0x4e, + 0x36, 0xab, 0x15, 0x4d, 0x8f, 0xdc, 0x08, + 0xc4, 0x4d, 0x43, 0xc7, 0x2b, 0xc9, 0x5c, + 0x05, 0x26, 0xe3, 0x46, 0xf0, 0x64, 0xaa, + 0x02, 0xa4, 0xbe, 0x3a, 0xd1, 0xca, 0x07, + 0x6a, 0x6e, 0x62, 0xf4, 0x57, 0x71, 0x96, + 0xec, 0xf0, 0x0b, 0xac, 0xa4, 0x4a, 0xa3, + 0x6d, 0x01, 0xba, 0xbd, 0x62, 0xc0, 0x10, + 0x54, 0x33, 0x8a, 0x71, 0xef, 0xaa, 0x1c, + 0x25, 0x25 ), + BIGINT ( 0x46, 0x1e, 0x38, 0x3a, 0x05, 0xc5, 0xaf, + 0xb5, 0x2e, 0x58, 0x8a, 0x0e, 0xec, 0x43, + 0xd6, 0x6b, 0xf1, 0x97, 0x73, 0x4c, 0x1b, + 0xcd, 0x31, 0xb8, 0x94, 0x0b, 0xe4, 0x9d, + 0x75, 0x17, 0xa5, 0xc4, 0xc4, 0x2a, 0xf0, + 0x32, 0x45, 0x09, 0xe8, 0xf6, 0x62, 0x03, + 0x2d, 0xee, 0x6e, 0xd3, 0xfc, 0x41, 0x6b, + 0x10, 0x70, 0x9b, 0x87, 0xa7, 0x8d, 0x9f, + 0x61, 0xbe, 0xcf, 0x09, 0x82, 0xfe, 0xd3, + 0x16, 0x5c, 0x12, 0x63, 0xa3, 0xb6, 0xd6, + 0xef, 0xdf, 0xc1, 0xc2, 0x13, 0x09, 0x98, + 0x77, 0xe4, 0x97, 0x61, 0x1f, 0x7d, 0xe7, + 0x32, 0xbf, 0x4c, 0xd4, 0x0a, 0x54, 0xea, + 0x68, 0xe4, 0x1e, 0xb3, 0x06, 0x49, 0xa3, + 0x61, 0x6f, 0xd7, 0x4a, 0x21, 0xd4, 0xbc, + 0x68, 0x76, 0xf5, 0x20, 0xa1, 0xa8, 0x1a, + 0x9f, 0x60, 0x58, 0xff, 0xb6, 0x76, 0x45, + 0xe6, 0xed, 0x61, 0x8d, 0xe6, 0xc0, 0x72, + 0x1c, 0x07 ) ); + bigint_subtract_ok ( BIGINT ( 0x83 ), + BIGINT ( 0x50 ), + BIGINT ( 0xcd ) ); + bigint_subtract_ok ( BIGINT ( 0x2c, 0x7c ), + BIGINT ( 0x49, 0x0e ), + BIGINT ( 0x1c, 0x92 ) ); + bigint_subtract_ok ( BIGINT ( 0x9c, 0x30, 0xbf ), + BIGINT ( 0xde, 0x4e, 0x07 ), + BIGINT ( 0x42, 0x1d, 0x48 ) ); + bigint_subtract_ok ( BIGINT ( 0xbb, 0x77, 0x32, 0x5a ), + BIGINT ( 0x5a, 0xd5, 0xfe, 0x28 ), + BIGINT ( 0x9f, 0x5e, 0xcb, 0xce ) ); + bigint_subtract_ok ( BIGINT ( 0x7b, 0xaa, 0x16, 0xcf, 0x15, 0x87, + 0xe0, 0x4f, 0x2c, 0xa3, 0xec, 0x2f, + 0x46, 0xfb, 0x83, 0xc6, 0xe0, 0xee, + 0x57, 0xfa, 0x04, 0xce, 0xa6 ), + BIGINT ( 0x46, 0x55, 0xb6, 0x23, 0x63, 0xd0, + 0x55, 0xdb, 0x8f, 0xcc, 0x55, 0xa8, + 0x2f, 0x85, 0xc1, 0x9f, 0x2c, 0x13, + 0x10, 0x9e, 0x76, 0x3c, 0x11 ), + BIGINT ( 0xca, 0xab, 0x9f, 0x54, 0x4e, 0x48, + 0x75, 0x8c, 0x63, 0x28, 0x69, 0x78, + 0xe8, 0x8a, 0x3d, 0xd8, 0x4b, 0x24, + 0xb8, 0xa4, 0x71, 0x6d, 0x6b ) ); + bigint_subtract_ok ( BIGINT ( 0x5b, 0x06, 0x77, 0x7b, 0xfd, 0x34, + 0x5f, 0x0f, 0xd9, 0xbd, 0x8e, 0x5d, + 0xc8, 0x4a, 0x70, 0x95, 0x1b, 0xb6, + 0x48, 0xfb, 0x0e, 0x40, 0xce, 0x06, + 0x66, 0xcc, 0x29, 0xe9, 0x51, 0x59, + 0x59, 0xc9, 0x65, 0x07, 0x75, 0xb8, + 0xd4, 0xcb, 0x07, 0x68, 0x14, 0x48, + 0xc7, 0x1e, 0xfe, 0xb3, 0x4c, 0xf1, + 0x10, 0xf0, 0xc7, 0x82, 0x38, 0x4c, + 0xaf, 0x05, 0x6d, 0x91, 0xc5, 0x18, + 0xfd, 0x1e, 0x26, 0x1b, 0xef, 0x71, + 0x70, 0x2e, 0x06, 0x70, 0x8e, 0x54, + 0xfa, 0x2b, 0x4d, 0x96, 0x85, 0x10, + 0x03, 0x76, 0xe7, 0x17, 0x59, 0x86, + 0x6c, 0x8b, 0x24, 0x6e, 0xd9, 0x30, + 0xf3, 0xd2, 0x9b, 0x62, 0xdc, 0x23, + 0x54, 0x06, 0x51, 0xb1, 0x95, 0x58, + 0xec, 0x27, 0xf6, 0x19, 0xae, 0xf4, + 0x31, 0xec, 0x72, 0x53, 0xcd, 0x32, + 0xed, 0xf4, 0x25, 0x4a, 0x5b, 0x36, + 0xa2, 0xb4, 0xa0, 0x29, 0x0c, 0x6b, + 0x3f, 0xc2 ), + BIGINT ( 0x7a, 0xd4, 0x25, 0xf1, 0xb5, 0xf5, + 0x00, 0x96, 0x47, 0x5b, 0x4f, 0x9f, + 0x1f, 0x61, 0x69, 0xd9, 0x72, 0x47, + 0xde, 0xbd, 0x87, 0x5d, 0x50, 0x91, + 0x69, 0xd8, 0x35, 0xe0, 0x43, 0xd8, + 0xd5, 0x15, 0xf2, 0xcd, 0x01, 0x73, + 0x0d, 0x34, 0xf0, 0x34, 0x46, 0x76, + 0xc0, 0x55, 0x7b, 0x27, 0xf5, 0x7b, + 0x55, 0xe9, 0xd0, 0x29, 0x0b, 0x4b, + 0x9f, 0x07, 0xbf, 0x2c, 0x3f, 0xef, + 0x36, 0x34, 0xde, 0x29, 0x1d, 0x5d, + 0x84, 0x5a, 0x5d, 0xc1, 0x02, 0x4d, + 0x56, 0xf1, 0x47, 0x39, 0x37, 0xc9, + 0xb5, 0x5f, 0x73, 0xec, 0x7c, 0x3d, + 0xbd, 0xc0, 0xfd, 0x38, 0x6c, 0x91, + 0x88, 0x4a, 0x0f, 0xee, 0xa1, 0x80, + 0xf5, 0x6a, 0x7c, 0x8c, 0x02, 0xc3, + 0x5a, 0xb2, 0x15, 0xa6, 0x2f, 0x6b, + 0x5b, 0x78, 0xb5, 0xf3, 0xbd, 0xd0, + 0xc8, 0xbc, 0xb1, 0xbb, 0xe1, 0xce, + 0x22, 0x80, 0x34, 0x5a, 0x2a, 0x27, + 0x83, 0xdc ), + BIGINT ( 0x1f, 0xcd, 0xae, 0x75, 0xb8, 0xc0, + 0xa1, 0x86, 0x6d, 0x9d, 0xc1, 0x41, + 0x57, 0x16, 0xf9, 0x44, 0x56, 0x91, + 0x95, 0xc2, 0x79, 0x1c, 0x82, 0x8b, + 0x03, 0x0c, 0x0b, 0xf6, 0xf2, 0x7f, + 0x7b, 0x4c, 0x8d, 0xc5, 0x8b, 0xba, + 0x38, 0x69, 0xe8, 0xcc, 0x32, 0x2d, + 0xf9, 0x36, 0x7c, 0x74, 0xa8, 0x8a, + 0x44, 0xf9, 0x08, 0xa6, 0xd2, 0xfe, + 0xf0, 0x02, 0x51, 0x9a, 0x7a, 0xd6, + 0x39, 0x16, 0xb8, 0x0d, 0x2d, 0xec, + 0x14, 0x2c, 0x57, 0x50, 0x73, 0xf8, + 0x5c, 0xc5, 0xf9, 0xa2, 0xb2, 0xb9, + 0xb1, 0xe8, 0x8c, 0xd5, 0x22, 0xb7, + 0x51, 0x35, 0xd8, 0xc9, 0x93, 0x60, + 0x94, 0x77, 0x74, 0x8b, 0xc5, 0x5d, + 0xa1, 0x64, 0x2a, 0xda, 0x6d, 0x6a, + 0x6e, 0x8a, 0x1f, 0x8c, 0x80, 0x77, + 0x29, 0x8c, 0x43, 0x9f, 0xf0, 0x9d, + 0xda, 0xc8, 0x8c, 0x71, 0x86, 0x97, + 0x7f, 0xcb, 0x94, 0x31, 0x1d, 0xbc, + 0x44, 0x1a ) ); + bigint_rol_ok ( BIGINT ( 0xe0 ), + BIGINT ( 0xc0 ) ); + bigint_rol_ok ( BIGINT ( 0x43, 0x1d ), + BIGINT ( 0x86, 0x3a ) ); + bigint_rol_ok ( BIGINT ( 0xac, 0xed, 0x9b ), + BIGINT ( 0x59, 0xdb, 0x36 ) ); + bigint_rol_ok ( BIGINT ( 0x2c, 0xe8, 0x3a, 0x22 ), + BIGINT ( 0x59, 0xd0, 0x74, 0x44 ) ); + bigint_rol_ok ( BIGINT ( 0x4e, 0x88, 0x4a, 0x05, 0x5e, 0x10, 0xee, + 0x5b, 0xc6, 0x40, 0x0e, 0x03, 0xd7, 0x0d, + 0x28, 0xa5, 0x55, 0xb2, 0x50, 0xef, 0x69, + 0xd1, 0x1d ), + BIGINT ( 0x9d, 0x10, 0x94, 0x0a, 0xbc, 0x21, 0xdc, + 0xb7, 0x8c, 0x80, 0x1c, 0x07, 0xae, 0x1a, + 0x51, 0x4a, 0xab, 0x64, 0xa1, 0xde, 0xd3, + 0xa2, 0x3a ) ); + bigint_rol_ok ( BIGINT ( 0x07, 0x62, 0x78, 0x70, 0x2e, 0xd4, 0x41, + 0xaa, 0x9b, 0x50, 0xb1, 0x9a, 0x71, 0xf5, + 0x1c, 0x2f, 0xe7, 0x0d, 0xf1, 0x46, 0x57, + 0x04, 0x99, 0x78, 0x4e, 0x84, 0x78, 0xba, + 0x57, 0xea, 0xa5, 0x43, 0xf7, 0x02, 0xf0, + 0x7a, 0x22, 0x60, 0x65, 0x42, 0xf2, 0x33, + 0x7d, 0xe3, 0xa8, 0x1b, 0xc4, 0x14, 0xdb, + 0xee, 0x4a, 0xf1, 0xe1, 0x52, 0xd4, 0xda, + 0x23, 0xed, 0x13, 0x5d, 0xea, 0xcf, 0xf6, + 0x5e, 0x39, 0x84, 0xe2, 0xb3, 0xa2, 0x05, + 0xba, 0xd9, 0x49, 0x8e, 0x75, 0x1d, 0xdb, + 0xe6, 0xb1, 0x6e, 0xda, 0x0a, 0x83, 0xd0, + 0x6e, 0xcf, 0x7a, 0x66, 0xb7, 0x64, 0x84, + 0xf5, 0x09, 0x5a, 0xa8, 0x11, 0x93, 0xf3, + 0x4f, 0x02, 0x28, 0x00, 0x3a, 0xf0, 0xa9, + 0x08, 0x77, 0x04, 0xf5, 0x04, 0xcd, 0x6b, + 0x24, 0xbe, 0x0f, 0x6d, 0xe3, 0xb2, 0xd3, + 0x07, 0x68, 0xe9, 0x00, 0x59, 0xa0, 0xe4, + 0x9e, 0x5e ), + BIGINT ( 0x0e, 0xc4, 0xf0, 0xe0, 0x5d, 0xa8, 0x83, + 0x55, 0x36, 0xa1, 0x63, 0x34, 0xe3, 0xea, + 0x38, 0x5f, 0xce, 0x1b, 0xe2, 0x8c, 0xae, + 0x09, 0x32, 0xf0, 0x9d, 0x08, 0xf1, 0x74, + 0xaf, 0xd5, 0x4a, 0x87, 0xee, 0x05, 0xe0, + 0xf4, 0x44, 0xc0, 0xca, 0x85, 0xe4, 0x66, + 0xfb, 0xc7, 0x50, 0x37, 0x88, 0x29, 0xb7, + 0xdc, 0x95, 0xe3, 0xc2, 0xa5, 0xa9, 0xb4, + 0x47, 0xda, 0x26, 0xbb, 0xd5, 0x9f, 0xec, + 0xbc, 0x73, 0x09, 0xc5, 0x67, 0x44, 0x0b, + 0x75, 0xb2, 0x93, 0x1c, 0xea, 0x3b, 0xb7, + 0xcd, 0x62, 0xdd, 0xb4, 0x15, 0x07, 0xa0, + 0xdd, 0x9e, 0xf4, 0xcd, 0x6e, 0xc9, 0x09, + 0xea, 0x12, 0xb5, 0x50, 0x23, 0x27, 0xe6, + 0x9e, 0x04, 0x50, 0x00, 0x75, 0xe1, 0x52, + 0x10, 0xee, 0x09, 0xea, 0x09, 0x9a, 0xd6, + 0x49, 0x7c, 0x1e, 0xdb, 0xc7, 0x65, 0xa6, + 0x0e, 0xd1, 0xd2, 0x00, 0xb3, 0x41, 0xc9, + 0x3c, 0xbc ) ); + bigint_ror_ok ( BIGINT ( 0x8f ), + BIGINT ( 0x47 ) ); + bigint_ror_ok ( BIGINT ( 0xaa, 0x1d ), + BIGINT ( 0x55, 0x0e ) ); + bigint_ror_ok ( BIGINT ( 0xf0, 0xbd, 0x68 ), + BIGINT ( 0x78, 0x5e, 0xb4 ) ); + bigint_ror_ok ( BIGINT ( 0x33, 0xa0, 0x3d, 0x95 ), + BIGINT ( 0x19, 0xd0, 0x1e, 0xca ) ); + bigint_ror_ok ( BIGINT ( 0xa1, 0xf4, 0xb9, 0x64, 0x91, 0x99, 0xa1, + 0xf4, 0xae, 0xeb, 0x71, 0x97, 0x1b, 0x71, + 0x09, 0x38, 0x3f, 0x8f, 0xc5, 0x3a, 0xb9, + 0x75, 0x94 ), + BIGINT ( 0x50, 0xfa, 0x5c, 0xb2, 0x48, 0xcc, 0xd0, + 0xfa, 0x57, 0x75, 0xb8, 0xcb, 0x8d, 0xb8, + 0x84, 0x9c, 0x1f, 0xc7, 0xe2, 0x9d, 0x5c, + 0xba, 0xca ) ); + bigint_ror_ok ( BIGINT ( 0xc0, 0xb3, 0x78, 0x46, 0x69, 0x6e, 0x35, + 0x94, 0xed, 0x28, 0xdc, 0xfd, 0xf6, 0xdb, + 0x2d, 0x24, 0xcb, 0xa4, 0x6f, 0x0e, 0x58, + 0x89, 0x04, 0xec, 0xc8, 0x0c, 0x2d, 0xb3, + 0x58, 0xa7, 0x22, 0x6d, 0x93, 0xe0, 0xb8, + 0x48, 0x6a, 0x3f, 0x04, 0x7e, 0xbe, 0xb8, + 0xa7, 0x84, 0xf5, 0xc9, 0x2f, 0x60, 0x9e, + 0x7c, 0xbc, 0xaf, 0x28, 0x89, 0x2f, 0xaa, + 0xd1, 0x82, 0x77, 0xa4, 0xdf, 0xf3, 0x4a, + 0xc6, 0xed, 0xa3, 0x07, 0xb4, 0xa9, 0xfd, + 0xef, 0xf8, 0x20, 0xb9, 0xb3, 0xff, 0x35, + 0x27, 0xed, 0x02, 0xea, 0xec, 0x63, 0xc0, + 0x46, 0x97, 0xc0, 0x4c, 0xca, 0x89, 0xca, + 0x14, 0xe8, 0xe0, 0x02, 0x14, 0x44, 0x46, + 0xf3, 0x2f, 0xbc, 0x6a, 0x28, 0xa2, 0xbe, + 0x20, 0xc8, 0xaa, 0x0f, 0xd9, 0x51, 0x8e, + 0x8d, 0x51, 0x29, 0x61, 0xef, 0x48, 0xae, + 0x3e, 0xe5, 0x10, 0xbf, 0xda, 0x9b, 0x92, + 0xb3, 0x77 ), + BIGINT ( 0x60, 0x59, 0xbc, 0x23, 0x34, 0xb7, 0x1a, + 0xca, 0x76, 0x94, 0x6e, 0x7e, 0xfb, 0x6d, + 0x96, 0x92, 0x65, 0xd2, 0x37, 0x87, 0x2c, + 0x44, 0x82, 0x76, 0x64, 0x06, 0x16, 0xd9, + 0xac, 0x53, 0x91, 0x36, 0xc9, 0xf0, 0x5c, + 0x24, 0x35, 0x1f, 0x82, 0x3f, 0x5f, 0x5c, + 0x53, 0xc2, 0x7a, 0xe4, 0x97, 0xb0, 0x4f, + 0x3e, 0x5e, 0x57, 0x94, 0x44, 0x97, 0xd5, + 0x68, 0xc1, 0x3b, 0xd2, 0x6f, 0xf9, 0xa5, + 0x63, 0x76, 0xd1, 0x83, 0xda, 0x54, 0xfe, + 0xf7, 0xfc, 0x10, 0x5c, 0xd9, 0xff, 0x9a, + 0x93, 0xf6, 0x81, 0x75, 0x76, 0x31, 0xe0, + 0x23, 0x4b, 0xe0, 0x26, 0x65, 0x44, 0xe5, + 0x0a, 0x74, 0x70, 0x01, 0x0a, 0x22, 0x23, + 0x79, 0x97, 0xde, 0x35, 0x14, 0x51, 0x5f, + 0x10, 0x64, 0x55, 0x07, 0xec, 0xa8, 0xc7, + 0x46, 0xa8, 0x94, 0xb0, 0xf7, 0xa4, 0x57, + 0x1f, 0x72, 0x88, 0x5f, 0xed, 0x4d, 0xc9, + 0x59, 0xbb ) ); + bigint_is_zero_ok ( BIGINT ( 0x9b ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0x5a, 0x9d ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0x5f, 0x80, 0x78 ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xa0, 0x52, 0x47, 0x2e ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0x18, 0x08, 0x49, 0xdb, 0x7b, 0x5c, + 0xe7, 0x41, 0x07, 0xdf, 0xed, 0xf9, + 0xd3, 0x92, 0x0d, 0x75, 0xa6, 0xb0, + 0x14, 0xfa, 0xdd, 0xfd, 0x82 ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0x04, 0x04, 0xb5, 0xf5, 0x01, 0xae, + 0x2b, 0x91, 0xa7, 0xc1, 0x49, 0x97, + 0x3f, 0x45, 0x53, 0x52, 0xb8, 0x52, + 0xf1, 0x62, 0xa5, 0x21, 0x18, 0xd4, + 0xb0, 0xb4, 0x8a, 0x17, 0x0e, 0xe8, + 0xeb, 0xaa, 0x28, 0xae, 0x3d, 0x8e, + 0xe3, 0x6c, 0xd0, 0x01, 0x0c, 0x54, + 0xca, 0x23, 0xbb, 0x06, 0xcd, 0x7a, + 0x61, 0x89, 0x38, 0x34, 0x6e, 0xc7, + 0xc2, 0xee, 0xb1, 0x80, 0x61, 0x0e, + 0xc6, 0x8d, 0x65, 0xa0, 0xeb, 0x34, + 0xe9, 0x63, 0x09, 0x4c, 0x20, 0xac, + 0x42, 0xe3, 0x35, 0xa2, 0x3e, 0x3b, + 0x2e, 0x18, 0x70, 0x45, 0x7c, 0xab, + 0x42, 0xcc, 0xe0, 0x9e, 0x7c, 0x42, + 0xd1, 0xda, 0x6c, 0x51, 0x10, 0x1e, + 0x0e, 0x3f, 0xe5, 0xd6, 0xd8, 0x56, + 0x08, 0xb2, 0x3b, 0x15, 0xc4, 0x7c, + 0x0c, 0x7e, 0xaf, 0x7b, 0x9d, 0xd6, + 0x2b, 0xc0, 0x2f, 0xa2, 0xa3, 0xa3, + 0x77, 0x58, 0x1b, 0xe9, 0xa8, 0x9a, + 0x23, 0x7f ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0x00, 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ), + 1 ); + bigint_is_zero_ok ( BIGINT ( 0xff ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xff, 0xff ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff ), + 0 ); + bigint_is_zero_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xa2 ), + BIGINT ( 0x58 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x58 ), + BIGINT ( 0xa2 ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xa2 ), + BIGINT ( 0xa2 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x61, 0x29 ), + BIGINT ( 0x87, 0xac ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0x87, 0xac ), + BIGINT ( 0x61, 0x29 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x61, 0x29 ), + BIGINT ( 0x61, 0x29 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0xe6, 0x63, 0x14 ), + BIGINT ( 0xb7, 0x2b, 0x76 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0xb7, 0x2b, 0x76 ), + BIGINT ( 0xe6, 0x63, 0x14 ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xe6, 0x63, 0x14 ), + BIGINT ( 0xe6, 0x63, 0x14 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ), + BIGINT ( 0xb5, 0xf9, 0x9b, 0x90 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0xb5, 0xf9, 0x9b, 0x90 ), + BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ), + BIGINT ( 0xe7, 0x4f, 0xd4, 0x80 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12, + 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d, + 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b, + 0x60, 0x98 ), + BIGINT ( 0x77, 0xbc, 0x3b, 0x1b, 0x57, 0x43, 0x3b, + 0x8c, 0x82, 0xda, 0xb5, 0xc7, 0x18, 0x09, + 0xb3, 0x59, 0x0e, 0x53, 0x2a, 0xb9, 0xd8, + 0xa2, 0xb4 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x77, 0xbc, 0x3b, 0x1b, 0x57, 0x43, 0x3b, + 0x8c, 0x82, 0xda, 0xb5, 0xc7, 0x18, 0x09, + 0xb3, 0x59, 0x0e, 0x53, 0x2a, 0xb9, 0xd8, + 0xa2, 0xb4 ), + BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12, + 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d, + 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b, + 0x60, 0x98 ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12, + 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d, + 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b, + 0x60, 0x98 ), + BIGINT ( 0xe6, 0x2c, 0x7c, 0x24, 0x78, 0x8f, 0x12, + 0x20, 0xde, 0xd3, 0x6b, 0xc9, 0x97, 0x2d, + 0x66, 0x74, 0xe5, 0xb6, 0xf7, 0x8f, 0x2b, + 0x60, 0x98 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4, + 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3, + 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40, + 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63, + 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f, + 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85, + 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce, + 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b, + 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73, + 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3, + 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76, + 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0, + 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1, + 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa, + 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13, + 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83, + 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3, + 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a, + 0x27, 0x96 ), + BIGINT ( 0xd4, 0x6b, 0x0a, 0x2e, 0x9f, 0xde, 0x4b, + 0x64, 0xfa, 0x6b, 0x37, 0x73, 0x66, 0x06, + 0xee, 0x04, 0xef, 0xe6, 0x3c, 0x7d, 0x57, + 0x22, 0x7f, 0x1f, 0x62, 0x1c, 0x7e, 0x20, + 0xda, 0x97, 0xd0, 0x27, 0x23, 0xf6, 0x77, + 0x5b, 0x49, 0x97, 0xe1, 0x65, 0x91, 0x13, + 0x93, 0xd6, 0x12, 0xc3, 0x66, 0x91, 0x76, + 0xe8, 0x47, 0x4c, 0x6a, 0x1b, 0xa2, 0x02, + 0xf8, 0x94, 0xaa, 0xe0, 0x1b, 0x0b, 0x17, + 0x86, 0x5e, 0xf5, 0x17, 0x23, 0xf5, 0x17, + 0x91, 0x6b, 0xd7, 0x2f, 0x5a, 0xfe, 0x8a, + 0x63, 0x28, 0x31, 0x1e, 0x09, 0x60, 0x29, + 0x5d, 0x55, 0xd8, 0x79, 0xeb, 0x78, 0x36, + 0x44, 0x69, 0xa4, 0x76, 0xa5, 0x35, 0x30, + 0xca, 0xc9, 0xf9, 0x62, 0xd7, 0x82, 0x13, + 0x56, 0xd0, 0x58, 0xfe, 0x16, 0x4b, 0xfb, + 0xa8, 0x4c, 0xb3, 0xd7, 0xcf, 0x5f, 0x93, + 0x9d, 0xc4, 0x11, 0xb4, 0xdd, 0xf8, 0x8f, + 0xe1, 0x11 ), + 0 ); + bigint_is_geq_ok ( BIGINT ( 0xd4, 0x6b, 0x0a, 0x2e, 0x9f, 0xde, 0x4b, + 0x64, 0xfa, 0x6b, 0x37, 0x73, 0x66, 0x06, + 0xee, 0x04, 0xef, 0xe6, 0x3c, 0x7d, 0x57, + 0x22, 0x7f, 0x1f, 0x62, 0x1c, 0x7e, 0x20, + 0xda, 0x97, 0xd0, 0x27, 0x23, 0xf6, 0x77, + 0x5b, 0x49, 0x97, 0xe1, 0x65, 0x91, 0x13, + 0x93, 0xd6, 0x12, 0xc3, 0x66, 0x91, 0x76, + 0xe8, 0x47, 0x4c, 0x6a, 0x1b, 0xa2, 0x02, + 0xf8, 0x94, 0xaa, 0xe0, 0x1b, 0x0b, 0x17, + 0x86, 0x5e, 0xf5, 0x17, 0x23, 0xf5, 0x17, + 0x91, 0x6b, 0xd7, 0x2f, 0x5a, 0xfe, 0x8a, + 0x63, 0x28, 0x31, 0x1e, 0x09, 0x60, 0x29, + 0x5d, 0x55, 0xd8, 0x79, 0xeb, 0x78, 0x36, + 0x44, 0x69, 0xa4, 0x76, 0xa5, 0x35, 0x30, + 0xca, 0xc9, 0xf9, 0x62, 0xd7, 0x82, 0x13, + 0x56, 0xd0, 0x58, 0xfe, 0x16, 0x4b, 0xfb, + 0xa8, 0x4c, 0xb3, 0xd7, 0xcf, 0x5f, 0x93, + 0x9d, 0xc4, 0x11, 0xb4, 0xdd, 0xf8, 0x8f, + 0xe1, 0x11 ), + BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4, + 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3, + 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40, + 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63, + 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f, + 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85, + 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce, + 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b, + 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73, + 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3, + 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76, + 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0, + 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1, + 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa, + 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13, + 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83, + 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3, + 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a, + 0x27, 0x96 ), + 1 ); + bigint_is_geq_ok ( BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4, + 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3, + 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40, + 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63, + 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f, + 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85, + 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce, + 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b, + 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73, + 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3, + 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76, + 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0, + 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1, + 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa, + 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13, + 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83, + 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3, + 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a, + 0x27, 0x96 ), + BIGINT ( 0x2a, 0x98, 0xfd, 0x87, 0x5d, 0x9f, 0xb4, + 0x8b, 0x5c, 0xcd, 0x5f, 0xcd, 0x53, 0xb3, + 0xd1, 0x81, 0x6a, 0x9c, 0x93, 0x66, 0x40, + 0xa7, 0x64, 0xe0, 0x8c, 0xec, 0x96, 0x63, + 0x4d, 0x29, 0xfa, 0xb1, 0x5d, 0x93, 0x2f, + 0xf9, 0x36, 0xea, 0x3b, 0xc1, 0xaf, 0x85, + 0xcb, 0xde, 0x2d, 0xc8, 0x48, 0x33, 0xce, + 0x7b, 0xa4, 0xa4, 0xda, 0x0f, 0xaa, 0x1b, + 0xcb, 0xed, 0xbe, 0x3a, 0xa5, 0xbb, 0x73, + 0x28, 0x04, 0xc6, 0x2a, 0xfb, 0x3a, 0xc3, + 0xae, 0x42, 0x1f, 0x53, 0x6c, 0xb2, 0x76, + 0xb7, 0xe2, 0x88, 0xcb, 0x88, 0xcf, 0xf0, + 0x52, 0x81, 0xd3, 0xb2, 0x1f, 0x56, 0xe1, + 0xe1, 0x47, 0x93, 0x6f, 0x2b, 0x49, 0xaa, + 0x50, 0x99, 0x7a, 0xc4, 0x56, 0xb7, 0x13, + 0x80, 0xf4, 0x73, 0x88, 0xc7, 0x39, 0x83, + 0x67, 0xc7, 0xcc, 0xb2, 0x28, 0x7a, 0xd3, + 0xdc, 0x48, 0xea, 0x62, 0x0d, 0xf5, 0x5a, + 0x27, 0x96 ), + 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0x37 ), + 0, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0xe6, 0xcb ), + 0, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0xd9, 0x0c, 0x5b ), + 0, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0x8b, 0x56, 0x89, 0xaf ), + 0, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0x25, 0xfc, 0xaf, 0xeb, 0x81, 0xc3, + 0xb8, 0x2f, 0xbb, 0xe3, 0x07, 0xb2, + 0xe2, 0x2a, 0xe2, 0x2d, 0xb4, 0x4d, + 0x6d, 0xec, 0x51, 0xa0, 0x2f ), + 0, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0x25, 0xfc, 0xaf, 0xeb, 0x81, 0xc3, + 0xb8, 0x2f, 0xbb, 0xe3, 0x07, 0xb2, + 0xe2, 0x2a, 0xe2, 0x2d, 0xb4, 0x4d, + 0x6d, 0xec, 0x51, 0xa0, 0x2f ), + 45, 0 ); + bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31, + 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09, + 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85, + 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06, + 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1, + 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d, + 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25, + 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e, + 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f, + 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7, + 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59, + 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65, + 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60, + 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09, + 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2, + 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5, + 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a, + 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2, + 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11, + 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b, + 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4, + 0xcb, 0xe0 ), + 0, 0 ); + bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31, + 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09, + 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85, + 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06, + 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1, + 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d, + 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25, + 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e, + 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f, + 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7, + 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59, + 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65, + 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60, + 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09, + 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2, + 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5, + 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a, + 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2, + 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11, + 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b, + 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4, + 0xcb, 0xe0 ), + 45, 1 ); + bigint_bit_is_set_ok ( BIGINT ( 0x88, 0x04, 0xec, 0xe6, 0xfb, 0x31, + 0x87, 0x43, 0xb2, 0x04, 0x9e, 0x09, + 0xba, 0x3e, 0x6d, 0x64, 0x1a, 0x85, + 0xb6, 0x46, 0x7d, 0x71, 0x3c, 0x06, + 0xd6, 0x40, 0x52, 0x39, 0x95, 0xa1, + 0x06, 0xff, 0x6a, 0x5c, 0xa3, 0x6d, + 0x4a, 0xc9, 0x77, 0x87, 0x75, 0x25, + 0x57, 0x65, 0x72, 0x73, 0x64, 0x7e, + 0xe9, 0x16, 0x17, 0xf3, 0x65, 0x3f, + 0xd5, 0xcc, 0xd7, 0xa2, 0xee, 0xe7, + 0x8d, 0x48, 0xd5, 0x7e, 0xdd, 0x59, + 0x4b, 0xf0, 0x96, 0x8b, 0x21, 0x65, + 0x04, 0x66, 0xc5, 0xff, 0x3e, 0x60, + 0xba, 0x28, 0x38, 0x7d, 0x9c, 0x09, + 0xd1, 0x8e, 0xac, 0x73, 0x8e, 0xf2, + 0x1e, 0xdf, 0x83, 0x6e, 0x54, 0xd5, + 0x34, 0xc1, 0xc6, 0xf9, 0x62, 0x2a, + 0x7d, 0xec, 0x47, 0xf2, 0xfc, 0xa2, + 0x10, 0x0a, 0x67, 0x1b, 0xc6, 0x11, + 0x9d, 0x68, 0x25, 0x8b, 0xb5, 0x9b, + 0x83, 0xf8, 0xa2, 0x11, 0xf5, 0xd4, + 0xcb, 0xe0 ), + 1013, 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0x3a ), + 6 ); + bigint_max_set_bit_ok ( BIGINT ( 0x03 ), + 2 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff ), + 8 ); + bigint_max_set_bit_ok ( BIGINT ( 0x20, 0x30 ), + 14 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x10 ), + 5 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff ), + 16 ); + bigint_max_set_bit_ok ( BIGINT ( 0x06, 0xdb, 0x7a ), + 19 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff ), + 24 ); + bigint_max_set_bit_ok ( BIGINT ( 0xee, 0xcb, 0x7b, 0xfd ), + 32 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x01, 0xdd ), + 9 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ), + 32 ); + bigint_max_set_bit_ok ( BIGINT ( 0x32, 0x39, 0x96, 0x52, 0x10, 0x67, + 0x7e, 0x32, 0xfc, 0x4e, 0x56, 0xc3, + 0x68, 0x18, 0x76, 0x1a, 0xac, 0x0e, + 0x93, 0xee, 0x55, 0xc5, 0x6e ), + 182 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc8, 0xe6, 0x59 ), + 24 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff ), + 184 ); + bigint_max_set_bit_ok ( BIGINT ( 0xcd, 0xb3, 0x22, 0x30, 0xdd, 0xa7, + 0xff, 0x37, 0xbf, 0xe3, 0x38, 0xf7, + 0xe1, 0x41, 0x73, 0xea, 0x3a, 0xfc, + 0x78, 0x9e, 0xfb, 0x4f, 0x85, 0xdc, + 0x1c, 0x40, 0x89, 0x6e, 0xda, 0xf9, + 0x9d, 0x6d, 0x12, 0x97, 0xb1, 0x80, + 0x2a, 0xeb, 0x91, 0xce, 0x3b, 0x83, + 0xb8, 0xa5, 0x3d, 0xce, 0x46, 0x56, + 0xb7, 0xd1, 0x28, 0xbc, 0x93, 0x4e, + 0x8c, 0x29, 0x6d, 0x2c, 0xcc, 0x58, + 0x49, 0x2f, 0x37, 0xa0, 0x08, 0x37, + 0x86, 0xdd, 0x38, 0x21, 0xa7, 0x57, + 0x37, 0xe3, 0xc5, 0xcc, 0x50, 0x11, + 0x1a, 0xe4, 0xea, 0xe7, 0x4d, 0x3c, + 0x37, 0x65, 0x78, 0xd1, 0xf6, 0xc3, + 0x94, 0x46, 0xd4, 0x0e, 0xd3, 0x9a, + 0x21, 0x8b, 0xa6, 0x54, 0xc0, 0xd2, + 0x88, 0x07, 0x24, 0xbf, 0x7d, 0x31, + 0xfd, 0x15, 0xa8, 0x92, 0x65, 0xe1, + 0x8d, 0xed, 0x70, 0x7b, 0x68, 0x0f, + 0xcc, 0x13, 0xb9, 0xb2, 0xdd, 0x3c, + 0x6a, 0x52 ), + 1024 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0xd9, + 0x91, 0x18, 0x6e, 0xd3, 0xff, 0x9b, + 0xdf, 0xf1, 0x9c, 0x7b, 0xf0, 0xa0, + 0xb9, 0xf5 ), + 127 ); + bigint_max_set_bit_ok ( BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ), + 0 ); + bigint_max_set_bit_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff ), + 1024 ); + bigint_multiply_ok ( BIGINT ( 0xf0 ), + BIGINT ( 0xeb ), + BIGINT ( 0xdc, 0x50 ) ); + bigint_multiply_ok ( BIGINT ( 0xd7, 0x16 ), + BIGINT ( 0x88, 0xfb ), + BIGINT ( 0x73, 0x16, 0x92, 0x92 ) ); + bigint_multiply_ok ( BIGINT ( 0xfe, 0xed, 0x1d ), + BIGINT ( 0x69, 0x9c, 0x03 ), + BIGINT ( 0x69, 0x2a, 0x9c, 0x5f, 0x73, 0x57 ) ); + bigint_multiply_ok ( BIGINT ( 0x96, 0xe9, 0x6f, 0x81 ), + BIGINT ( 0x67, 0x3c, 0x5a, 0x16 ), + BIGINT ( 0x3c, 0xdb, 0x7f, 0xae, 0x12, 0x7e, + 0xef, 0x16 ) ); + bigint_multiply_ok ( BIGINT ( 0xe8, 0x08, 0x0b, 0xe9, 0x29, 0x36, + 0xea, 0x51, 0x1d, 0x75, 0x1a, 0xd5, + 0xba, 0xc6, 0xa0, 0xf3, 0x48, 0x5c, + 0xdf, 0x42, 0xdf, 0x28, 0x38 ), + BIGINT ( 0x22, 0x07, 0x41, 0x54, 0x4e, 0xf9, + 0x90, 0xa8, 0xaf, 0xba, 0xf6, 0xb0, + 0x35, 0x7e, 0x98, 0xef, 0x2c, 0x31, + 0xc9, 0xa7, 0x25, 0x74, 0x8d ), + BIGINT ( 0x1e, 0xd7, 0xa5, 0x03, 0xc0, 0x18, + 0x2e, 0x29, 0xb1, 0x3e, 0x96, 0x71, + 0x90, 0xa5, 0x6d, 0x43, 0x58, 0xf7, + 0x22, 0x80, 0x0b, 0x21, 0xc6, 0x70, + 0x90, 0x1c, 0xa8, 0x85, 0x87, 0xaf, + 0xd7, 0xdd, 0x27, 0x69, 0xaf, 0x20, + 0xa0, 0x2d, 0x43, 0x5d, 0xda, 0xba, + 0x4b, 0x3a, 0x86, 0xd8 ) ); + bigint_multiply_ok ( BIGINT ( 0xa2, 0x0f, 0xc6, 0x08, 0x0a, 0x01, + 0x19, 0x42, 0x0e, 0xaa, 0x5c, 0xae, + 0x4f, 0x4e, 0xb0, 0xad, 0xb2, 0xe8, + 0xee, 0xd5, 0x65, 0xec, 0x5a, 0xda, + 0xc0, 0xba, 0x78, 0xa8, 0x0f, 0x15, + 0x39, 0xd7, 0x7a, 0x10, 0xc2, 0xa7, + 0xec, 0x44, 0xac, 0xad, 0x39, 0x04, + 0x2e, 0x66, 0x54, 0x70, 0x57, 0xee, + 0xf6, 0x97, 0x19, 0x71, 0x16, 0xf9, + 0xbb, 0x2e, 0x84, 0x09, 0x6e, 0x9a, + 0x3b, 0x16, 0xb2, 0x65, 0x74, 0x50, + 0x19, 0xd1, 0xe9, 0x95, 0xa0, 0x7b, + 0x33, 0xb5, 0xac, 0x7c, 0x9e, 0xd4, + 0x68, 0x0d, 0xc9, 0xe4, 0x03, 0x86, + 0x1a, 0xa3, 0x42, 0x33, 0x28, 0x14, + 0x12, 0x7d, 0x5a, 0xd9, 0x30, 0x18, + 0x0a, 0xf4, 0x0c, 0x96, 0x58, 0xc9, + 0xb5, 0x37, 0xdb, 0x49, 0xdc, 0x01, + 0x4a, 0xcb, 0x6d, 0x87, 0x52, 0xf6, + 0xae, 0xa7, 0x71, 0x31, 0x9a, 0x1a, + 0xe2, 0x1c, 0x87, 0x51, 0xc9, 0xeb, + 0x70, 0x71 ), + BIGINT ( 0x7c, 0xdd, 0x2f, 0x5d, 0x27, 0xfe, + 0xca, 0x70, 0x96, 0xc3, 0xb1, 0x1f, + 0xac, 0xa9, 0x3a, 0xdc, 0xcd, 0xbc, + 0x58, 0xb4, 0xde, 0xe7, 0xe5, 0x34, + 0x1a, 0xc0, 0xb9, 0x46, 0xf7, 0x52, + 0x76, 0x23, 0xe8, 0xe9, 0x92, 0xa1, + 0x86, 0x3c, 0x6f, 0xf1, 0x22, 0xf4, + 0x72, 0xb1, 0xde, 0xd3, 0x8f, 0x11, + 0x9e, 0x52, 0xe5, 0x81, 0x54, 0xe9, + 0xa7, 0x72, 0x3f, 0x3e, 0xa0, 0x80, + 0xbb, 0xae, 0x0e, 0x30, 0x6a, 0x11, + 0x91, 0x11, 0x3b, 0x3f, 0x44, 0x1f, + 0x8d, 0x4d, 0xea, 0xdd, 0x09, 0x95, + 0x9d, 0x02, 0xa6, 0x6d, 0x3b, 0x08, + 0x40, 0x8d, 0xb4, 0x4b, 0x05, 0x74, + 0x8c, 0x1f, 0xaa, 0x61, 0x6f, 0x0e, + 0xcc, 0xcf, 0xe0, 0x81, 0x03, 0xe4, + 0x9b, 0x11, 0xd9, 0xab, 0xf3, 0x24, + 0xe2, 0x3b, 0xe0, 0x05, 0x60, 0x65, + 0x16, 0xc6, 0x2e, 0x83, 0xa0, 0x98, + 0x8e, 0x11, 0x05, 0x00, 0xe4, 0x3f, + 0x7e, 0x65 ), + BIGINT ( 0x4f, 0x0b, 0xa9, 0x85, 0xb8, 0x31, + 0x48, 0xea, 0x11, 0x44, 0xaf, 0x2d, + 0xed, 0x1a, 0x76, 0x45, 0xac, 0x87, + 0x0c, 0xf3, 0xd7, 0xc4, 0x8e, 0x5c, + 0xd7, 0xdf, 0x28, 0x74, 0xa6, 0x40, + 0xe4, 0x6b, 0x5b, 0x19, 0x36, 0x37, + 0x9c, 0xcd, 0x43, 0x76, 0x15, 0x00, + 0x5d, 0x23, 0xa2, 0x8a, 0x53, 0x25, + 0xbf, 0x18, 0xda, 0xe6, 0x09, 0xdf, + 0xaa, 0xeb, 0x9a, 0x82, 0x01, 0x14, + 0x2b, 0x20, 0x2b, 0xb6, 0x22, 0x62, + 0x6b, 0xcc, 0xd4, 0xc9, 0x02, 0x67, + 0x95, 0x43, 0x75, 0x4e, 0x97, 0x4e, + 0xec, 0x04, 0xde, 0x29, 0x0a, 0xef, + 0xf7, 0xc1, 0x72, 0x8c, 0x64, 0x38, + 0x16, 0x47, 0x9f, 0x16, 0x0c, 0xa5, + 0x79, 0x6b, 0xea, 0x2e, 0x4c, 0x3d, + 0x0c, 0xe6, 0x57, 0x51, 0x65, 0xa5, + 0x3b, 0xca, 0xae, 0x54, 0x0c, 0x67, + 0xf8, 0x23, 0x00, 0xc9, 0x8d, 0xe6, + 0x16, 0x91, 0x19, 0xb3, 0x5b, 0x68, + 0x7b, 0xf2, 0xe2, 0x5d, 0x69, 0x48, + 0x3f, 0x2b, 0xa0, 0x4f, 0x7c, 0x3c, + 0x26, 0xf9, 0xd9, 0xfd, 0x3d, 0x5d, + 0xd6, 0x05, 0x00, 0xd8, 0xdf, 0x5a, + 0x56, 0x8f, 0x16, 0x68, 0x4f, 0x15, + 0x19, 0x9d, 0xd7, 0x11, 0x51, 0x7d, + 0x73, 0x5c, 0xd4, 0xd5, 0xb4, 0xc7, + 0x42, 0xe3, 0xee, 0xf1, 0x67, 0xd6, + 0x69, 0x72, 0x04, 0x4b, 0x88, 0x3d, + 0x05, 0xd8, 0x1e, 0x50, 0xcb, 0xce, + 0x39, 0x19, 0x42, 0xb6, 0xa7, 0xf3, + 0xba, 0x78, 0x90, 0xd2, 0x09, 0x05, + 0x87, 0xf8, 0xc0, 0x9c, 0x47, 0xff, + 0xbf, 0xaa, 0x21, 0x8d, 0x81, 0x86, + 0xcd, 0x58, 0xdf, 0x30, 0xf1, 0xd1, + 0x60, 0x53, 0x85, 0x40, 0xbf, 0x14, + 0x3e, 0xdc, 0x9e, 0x9e, 0xc4, 0xc7, + 0x48, 0xa0, 0x83, 0xe0, 0x99, 0x8b, + 0x43, 0xf8, 0x52, 0x8a, 0x15, 0x88, + 0x89, 0x83, 0x7d, 0x71, 0xbb, 0x62, + 0x12, 0x7a, 0x23, 0x85, 0x3a, 0xbb, + 0xdb, 0x09, 0xfa, 0x95 ) ); + bigint_multiply_ok ( BIGINT ( 0xff ), + BIGINT ( 0xff ), + BIGINT ( 0xfe, 0x01 ) ); + bigint_multiply_ok ( BIGINT ( 0xff, 0xff ), + BIGINT ( 0xff, 0xff ), + BIGINT ( 0xff, 0xfe, 0x00, 0x01 ) ); + bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xfe, 0x00, 0x00, 0x01 ) ); + bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x01 ) ); + bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ) ); + bigint_multiply_ok ( BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff ), + BIGINT ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ) ); + bigint_mod_multiply_ok ( BIGINT ( 0x37 ), + BIGINT ( 0x67 ), + BIGINT ( 0x3f ), + BIGINT ( 0x3a ) ); + bigint_mod_multiply_ok ( BIGINT ( 0x45, 0x94 ), + BIGINT ( 0xbd, 0xd2 ), + BIGINT ( 0xca, 0xc7 ), + BIGINT ( 0xac, 0xc1 ) ); + bigint_mod_multiply_ok ( BIGINT ( 0x8e, 0xcd, 0x74 ), + BIGINT ( 0xe2, 0xf1, 0xea ), + BIGINT ( 0x59, 0x51, 0x53 ), + BIGINT ( 0x22, 0xdd, 0x1c ) ); + bigint_mod_multiply_ok ( BIGINT ( 0xc2, 0xa8, 0x40, 0x6f ), + BIGINT ( 0x29, 0xd7, 0xf4, 0x77 ), + BIGINT ( 0xbb, 0xbd, 0xdb, 0x3d ), + BIGINT ( 0x8f, 0x39, 0xd0, 0x47 ) ); + bigint_mod_multiply_ok ( BIGINT ( 0x2e, 0xcb, 0x74, 0x7c, 0x64, 0x60, + 0xb3, 0x44, 0xf3, 0x23, 0x49, 0x4a, + 0xc6, 0xb6, 0xbf, 0xea, 0x80, 0xd8, + 0x34, 0xc5, 0x54, 0x22, 0x09 ), + BIGINT ( 0x61, 0x2c, 0x5a, 0xc5, 0xde, 0x07, + 0x65, 0x8e, 0xab, 0x88, 0x1a, 0x2e, + 0x7a, 0x95, 0x17, 0xe3, 0x3b, 0x17, + 0xe4, 0x21, 0xb0, 0xb4, 0x57 ), + BIGINT ( 0x8e, 0x46, 0xa5, 0x87, 0x7b, 0x7f, + 0xc4, 0xd7, 0x31, 0xb1, 0x94, 0xe7, + 0xe7, 0x1c, 0x7e, 0x7a, 0xc2, 0x6c, + 0xce, 0xcb, 0xc8, 0x5d, 0x70 ), + BIGINT ( 0x1e, 0xd1, 0x5b, 0x3d, 0x1d, 0x17, + 0x7c, 0x31, 0x95, 0x13, 0x1b, 0xd8, + 0xee, 0x0a, 0xb0, 0xe1, 0x5b, 0x13, + 0xad, 0x83, 0xe9, 0xf8, 0x7f ) ); + bigint_mod_multiply_ok ( BIGINT ( 0x56, 0x37, 0xab, 0x07, 0x8b, 0x25, + 0xa7, 0xc2, 0x50, 0x30, 0x43, 0xfc, + 0x63, 0x8b, 0xdf, 0x84, 0x68, 0x85, + 0xca, 0xce, 0x44, 0x5c, 0xb1, 0x14, + 0xa4, 0xb5, 0xba, 0x43, 0xe0, 0x31, + 0x45, 0x6b, 0x82, 0xa9, 0x0b, 0x9e, + 0x3a, 0xb0, 0x39, 0x09, 0x2a, 0x68, + 0x2e, 0x0f, 0x09, 0x54, 0x47, 0x04, + 0xdb, 0xcf, 0x4a, 0x3a, 0x2d, 0x7b, + 0x7d, 0x50, 0xa4, 0xc5, 0xeb, 0x13, + 0xdd, 0x49, 0x61, 0x7d, 0x18, 0xa1, + 0x0d, 0x6b, 0x58, 0xba, 0x9f, 0x7c, + 0x81, 0x34, 0x9e, 0xf9, 0x9c, 0x9e, + 0x28, 0xa8, 0x1c, 0x15, 0x16, 0x20, + 0x3c, 0x0a, 0xb1, 0x11, 0x06, 0x93, + 0xbc, 0xd8, 0x4e, 0x49, 0xae, 0x7b, + 0xb4, 0x02, 0x8b, 0x1c, 0x5b, 0x18, + 0xb4, 0xac, 0x7f, 0xdd, 0x70, 0xef, + 0x87, 0xac, 0x1b, 0xac, 0x25, 0xa3, + 0xc9, 0xa7, 0x3a, 0xc5, 0x76, 0x68, + 0x09, 0x1f, 0xa1, 0x48, 0x53, 0xb6, + 0x13, 0xac ), + BIGINT ( 0xef, 0x5c, 0x1f, 0x1a, 0x44, 0x64, + 0x66, 0xcf, 0xdd, 0x3f, 0x0b, 0x27, + 0x81, 0xa7, 0x91, 0x7a, 0x35, 0x7b, + 0x0f, 0x46, 0x5e, 0xca, 0xbf, 0xf8, + 0x50, 0x5e, 0x99, 0x7c, 0xc6, 0x64, + 0x43, 0x00, 0x9f, 0xb2, 0xda, 0xfa, + 0x42, 0x15, 0x9c, 0xa3, 0xd6, 0xc8, + 0x64, 0xa7, 0x65, 0x4a, 0x98, 0xf7, + 0xb3, 0x96, 0x5f, 0x42, 0xf9, 0x73, + 0xe1, 0x75, 0xc3, 0xc4, 0x0b, 0x5d, + 0x5f, 0xf3, 0x04, 0x8a, 0xee, 0x59, + 0xa6, 0x1b, 0x06, 0x38, 0x0b, 0xa2, + 0x9f, 0xb4, 0x4f, 0x6d, 0x50, 0x5e, + 0x37, 0x37, 0x21, 0x83, 0x9d, 0xa3, + 0x12, 0x16, 0x4d, 0xab, 0x36, 0x51, + 0x21, 0xb1, 0x74, 0x66, 0x40, 0x9a, + 0xd3, 0x72, 0xcc, 0x18, 0x40, 0x53, + 0x89, 0xff, 0xd7, 0x00, 0x8d, 0x7e, + 0x93, 0x81, 0xdb, 0x29, 0xb6, 0xd7, + 0x23, 0x2b, 0x67, 0x2f, 0x11, 0x98, + 0x49, 0x87, 0x2f, 0x46, 0xb7, 0x33, + 0x6d, 0x12 ), + BIGINT ( 0x67, 0x7a, 0x17, 0x6a, 0xd2, 0xf8, + 0x49, 0xfb, 0x7c, 0x95, 0x25, 0x54, + 0xf0, 0xab, 0x5b, 0xb3, 0x0e, 0x01, + 0xab, 0xd3, 0x65, 0x6f, 0x7e, 0x18, + 0x05, 0xed, 0x9b, 0xc4, 0x90, 0x6c, + 0xd0, 0x6d, 0x94, 0x79, 0x28, 0xd6, + 0x24, 0x77, 0x9a, 0x08, 0xd2, 0x2f, + 0x7c, 0x2d, 0xa0, 0x0c, 0x14, 0xbe, + 0x7b, 0xee, 0x9e, 0x48, 0x88, 0x3c, + 0x8f, 0x9f, 0xb9, 0x7a, 0xcb, 0x98, + 0x76, 0x61, 0x0d, 0xee, 0xa2, 0x42, + 0x67, 0x1b, 0x2c, 0x42, 0x8f, 0x41, + 0xcc, 0x78, 0xba, 0xba, 0xaa, 0xa2, + 0x92, 0xb0, 0x6e, 0x0c, 0x4e, 0xe1, + 0xa5, 0x13, 0x7d, 0x8a, 0x8f, 0x81, + 0x95, 0x8a, 0xdf, 0x57, 0x93, 0x88, + 0x27, 0x4f, 0x1a, 0x59, 0xa4, 0x74, + 0x22, 0xa9, 0x78, 0xe5, 0xed, 0xb1, + 0x09, 0x26, 0x59, 0xde, 0x88, 0x21, + 0x8d, 0xa2, 0xa8, 0x58, 0x10, 0x7b, + 0x65, 0x96, 0xbf, 0x69, 0x3b, 0xc5, + 0x55, 0xf8 ), + BIGINT ( 0x15, 0xf7, 0x00, 0xeb, 0xc7, 0x5a, + 0x6f, 0xf0, 0x50, 0xf3, 0x21, 0x8a, + 0x8e, 0xa6, 0xf6, 0x67, 0x56, 0x7d, + 0x07, 0x45, 0x89, 0xdb, 0xd7, 0x7e, + 0x9e, 0x28, 0x7f, 0xfb, 0xed, 0xca, + 0x2c, 0xbf, 0x47, 0x77, 0x99, 0x95, + 0xf3, 0xd6, 0x9d, 0xc5, 0x57, 0x81, + 0x7f, 0x97, 0xf2, 0x6b, 0x24, 0xee, + 0xce, 0xc5, 0x9b, 0xe6, 0x42, 0x2d, + 0x37, 0xb7, 0xeb, 0x3d, 0xb5, 0xf7, + 0x1e, 0x86, 0xc2, 0x40, 0x44, 0xc9, + 0x85, 0x5a, 0x1a, 0xc0, 0xac, 0x9e, + 0x78, 0x69, 0x00, 0x7b, 0x93, 0x65, + 0xd7, 0x7f, 0x0c, 0xd6, 0xba, 0x4f, + 0x06, 0x00, 0x61, 0x05, 0xb2, 0x44, + 0xb4, 0xe7, 0xbb, 0x3b, 0x96, 0xb0, + 0x6d, 0xe8, 0x43, 0xd2, 0x03, 0xb7, + 0x0a, 0xc4, 0x6d, 0x30, 0xd8, 0xd5, + 0xe6, 0x54, 0x65, 0xdd, 0xa9, 0x1b, + 0x50, 0xc0, 0xb9, 0x95, 0xb0, 0x7d, + 0x7c, 0xca, 0x63, 0xf8, 0x72, 0xbe, + 0x3b, 0x00 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xcd ), + BIGINT ( 0xbb ), + BIGINT ( 0x25 ), + BIGINT ( 0xab ) ); + bigint_mod_exp_ok ( BIGINT ( 0xc4 ), + BIGINT ( 0xe9 ), + BIGINT ( 0x02, 0x4c ), + BIGINT ( 0x7e ) ); + bigint_mod_exp_ok ( BIGINT ( 0xcb ), + BIGINT ( 0xde ), + BIGINT ( 0xbd, 0x73, 0xbf ), + BIGINT ( 0x17 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x17 ), + BIGINT ( 0xb9 ), + BIGINT ( 0x39, 0x68, 0xba, 0x7d ), + BIGINT ( 0x17 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x2e ), + BIGINT ( 0xb7 ), + BIGINT ( 0x39, 0x07, 0x1b, 0x49, 0x5b, 0xea, + 0xf2, 0x61, 0x75, 0x94, 0x60, 0x86, + 0x73, 0xd0, 0xeb, 0x11, 0x08, 0x19, + 0x90, 0x19, 0xe0, 0xed, 0x2a ), + BIGINT ( 0x19 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x59 ), + BIGINT ( 0xce ), + BIGINT ( 0xdf, 0xbc, 0x0d, 0x0c, 0x09, 0xeb, + 0xf8, 0xcf, 0xdb, 0xb6, 0x00, 0xa3, + 0x9e, 0xc3, 0x6c, 0x8d, 0xf1, 0xc3, + 0x03, 0x36, 0xaa, 0xd4, 0x22, 0x7c, + 0x20, 0x7b, 0xa9, 0x9a, 0x01, 0xe4, + 0xf2, 0x50, 0x42, 0x29, 0x68, 0x7a, + 0xa6, 0x2c, 0xdf, 0xb6, 0x51, 0xa9, + 0x73, 0x10, 0x98, 0x37, 0x69, 0xb3, + 0x21, 0x49, 0x6d, 0xcc, 0x80, 0xfa, + 0x7e, 0x12, 0xe4, 0x9c, 0xc2, 0xbb, + 0xe3, 0xa3, 0x10, 0x3f, 0xba, 0x99, + 0x22, 0x79, 0x71, 0x39, 0x96, 0x7b, + 0x1a, 0x89, 0xdc, 0xda, 0x43, 0x52, + 0x50, 0x7b, 0xe3, 0x8c, 0xd3, 0xc0, + 0xf5, 0x7d, 0xfc, 0x80, 0x71, 0x6e, + 0xaf, 0x5c, 0xd0, 0x14, 0xc0, 0x60, + 0x24, 0xa8, 0x9a, 0x8a, 0x54, 0x4a, + 0x6f, 0x42, 0x7a, 0x14, 0x14, 0x25, + 0xd5, 0x22, 0x08, 0x8f, 0xd9, 0xdb, + 0xd4, 0x0f, 0x14, 0xf4, 0x3b, 0x26, + 0x0e, 0xb6, 0x72, 0xd7, 0x03, 0xd5, + 0xf0, 0x0e ), + BIGINT ( 0xa9 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x7f, 0x30 ), + BIGINT ( 0x73, 0x74 ), + BIGINT ( 0x75 ), + BIGINT ( 0x4b, 0xe8 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x04, 0x6c ), + BIGINT ( 0x99, 0x04 ), + BIGINT ( 0x33, 0xd2 ), + BIGINT ( 0x86, 0x74 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xca, 0x88 ), + BIGINT ( 0xdc, 0x60 ), + BIGINT ( 0x7e, 0x76, 0x79 ), + BIGINT ( 0x42, 0x40 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x68, 0x97 ), + BIGINT ( 0x52, 0x8b ), + BIGINT ( 0x4f, 0x7f, 0xe7, 0xda ), + BIGINT ( 0x22, 0x77 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xbd, 0x14 ), + BIGINT ( 0x9e, 0xfc ), + BIGINT ( 0x23, 0xf7, 0xd0, 0xa1, 0x9e, 0x9b, + 0x05, 0xd2, 0x44, 0x24, 0x4f, 0x3f, + 0x83, 0xcc, 0x49, 0x70, 0xa5, 0x0d, + 0xfc, 0xa7, 0x43, 0xf3, 0x3e ), + BIGINT ( 0x1a, 0xc8 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x46, 0x3e ), + BIGINT ( 0xb8, 0xde ), + BIGINT ( 0xa9, 0xc0, 0xdc, 0x45, 0x65, 0x0d, + 0xa5, 0x56, 0x70, 0x4c, 0xf1, 0xda, + 0xab, 0x64, 0xc2, 0x04, 0xf6, 0x32, + 0x20, 0x68, 0x31, 0x5f, 0x9a, 0x00, + 0x0f, 0x7b, 0x24, 0x33, 0xdf, 0xaf, + 0xfe, 0x03, 0x1e, 0x4a, 0xa1, 0xf8, + 0x45, 0x8d, 0x5a, 0x7d, 0x12, 0x58, + 0x00, 0x6d, 0xba, 0x79, 0x9f, 0xe1, + 0xa1, 0xfc, 0x1f, 0xb9, 0xf3, 0xa7, + 0x07, 0xf5, 0xfe, 0xd6, 0xa1, 0xba, + 0xda, 0x63, 0xef, 0x39, 0x8e, 0xb7, + 0x48, 0xa8, 0x81, 0x86, 0xb1, 0x22, + 0x14, 0x9f, 0x9e, 0xac, 0x69, 0xf7, + 0xae, 0x1f, 0xf2, 0x99, 0x41, 0xb7, + 0x37, 0xa7, 0xbc, 0x42, 0xf2, 0x45, + 0x43, 0xf2, 0x2a, 0xef, 0xc2, 0x83, + 0xd5, 0x32, 0x6e, 0xfa, 0x49, 0x1c, + 0x94, 0x9c, 0xc2, 0xc5, 0xad, 0x28, + 0x53, 0x1c, 0x11, 0xc4, 0x1c, 0x78, + 0x8f, 0x13, 0xdc, 0xb3, 0x2a, 0x63, + 0xfd, 0x1f, 0x89, 0x9b, 0x0c, 0x31, + 0x92, 0x73 ), + BIGINT ( 0x7b, 0x8a ) ); + bigint_mod_exp_ok ( BIGINT ( 0xf3, 0xc3, 0xab ), + BIGINT ( 0xd0, 0x7e, 0xd0 ), + BIGINT ( 0xf6 ), + BIGINT ( 0x1f, 0xb3, 0x09 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x13, 0xec, 0xf6 ), + BIGINT ( 0x87, 0x1a, 0x9a ), + BIGINT ( 0x03, 0xf3 ), + BIGINT ( 0x15, 0xe9, 0x8e ) ); + bigint_mod_exp_ok ( BIGINT ( 0x5a, 0x96, 0xe5 ), + BIGINT ( 0x56, 0x4a, 0xd1 ), + BIGINT ( 0x89, 0x62, 0x8e ), + BIGINT ( 0x34, 0xb8, 0xaa ) ); + bigint_mod_exp_ok ( BIGINT ( 0x84, 0x7c, 0xbd ), + BIGINT ( 0x3c, 0x80, 0x0a ), + BIGINT ( 0x5e, 0x52, 0x9d, 0xba ), + BIGINT ( 0x04, 0xcb, 0x4f ) ); + bigint_mod_exp_ok ( BIGINT ( 0x50, 0x01, 0x51 ), + BIGINT ( 0x02, 0xe6, 0x96 ), + BIGINT ( 0x34, 0x0c, 0x7e, 0xbf, 0x27, 0x23, + 0x46, 0x92, 0x1c, 0xca, 0x91, 0xab, + 0x50, 0x2c, 0x3a, 0x64, 0xc8, 0x4a, + 0x75, 0xd6, 0xe2, 0xde, 0x31 ), + BIGINT ( 0x02, 0x16, 0x05 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x5e, 0x47, 0xd8 ), + BIGINT ( 0x26, 0xd1, 0xb6 ), + BIGINT ( 0x49, 0x61, 0x84, 0x7a, 0xa9, 0xfb, + 0x93, 0x45, 0xe4, 0xfa, 0x53, 0x60, + 0x73, 0x98, 0x5a, 0x17, 0xe7, 0x77, + 0x2d, 0xcd, 0x97, 0xf4, 0xc0, 0x34, + 0x46, 0xfa, 0xbd, 0x21, 0xdf, 0xa5, + 0xa0, 0x12, 0x38, 0x7c, 0xbd, 0xd9, + 0xcd, 0xbc, 0xde, 0x29, 0xa5, 0x13, + 0xa8, 0xf0, 0xf6, 0x88, 0xc6, 0x31, + 0xed, 0x90, 0x19, 0x11, 0x7d, 0xe1, + 0x0e, 0x81, 0x98, 0x8e, 0x98, 0x86, + 0xde, 0x2a, 0x4c, 0xad, 0xff, 0x57, + 0x12, 0xbc, 0x4b, 0xaf, 0x21, 0xde, + 0xca, 0x3a, 0x25, 0xd7, 0x98, 0xe3, + 0x25, 0xbc, 0x17, 0x74, 0x0b, 0x9c, + 0x53, 0xe1, 0x1a, 0xec, 0x9a, 0x5a, + 0xdc, 0x68, 0xdf, 0xad, 0xd6, 0x71, + 0x6b, 0x5b, 0x8b, 0x85, 0xbb, 0xe5, + 0xd5, 0x14, 0x4c, 0x30, 0x27, 0x68, + 0xd1, 0xf7, 0x58, 0x34, 0x4c, 0xe1, + 0x71, 0xde, 0x7b, 0x8d, 0xa2, 0xe6, + 0x0a, 0x44, 0x22, 0x26, 0x5a, 0x70, + 0xbb, 0x68 ), + BIGINT ( 0x18, 0x36, 0x96 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xc7, 0x4a, 0xf0, 0x48 ), + BIGINT ( 0x5d, 0x27, 0x07, 0x54 ), + BIGINT ( 0x4a ), + BIGINT ( 0x48, 0x68, 0x7b, 0xe0 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xb4, 0x89, 0xc9, 0x5b ), + BIGINT ( 0x7c, 0xd7, 0xc7, 0xff ), + BIGINT ( 0xc6, 0x9c ), + BIGINT ( 0x0b, 0x2d, 0xf8, 0xf7 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xea, 0x72, 0x43, 0xfe ), + BIGINT ( 0xfc, 0x57, 0x2d, 0x47 ), + BIGINT ( 0x60, 0x01, 0x2c ), + BIGINT ( 0x12, 0x01, 0xe3, 0xf5 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x81, 0x7f, 0x27, 0x94 ), + BIGINT ( 0x17, 0x21, 0x67, 0xab ), + BIGINT ( 0x50, 0x19, 0x12, 0x52 ), + BIGINT ( 0x05, 0x17, 0x6b, 0x13 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x38, 0xab, 0xd4, 0xec ), + BIGINT ( 0x0c, 0x2a, 0x56, 0x38 ), + BIGINT ( 0x2f, 0x85, 0x85, 0x57, 0xf6, 0xde, + 0x24, 0xb4, 0x28, 0x3c, 0x5a, 0x3c, + 0x0b, 0x12, 0x85, 0x85, 0x85, 0x98, + 0x46, 0x5b, 0x9c, 0x52, 0x3a ), + BIGINT ( 0x02, 0xe6, 0x6a, 0x70 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xa6, 0x35, 0xc0, 0x6f ), + BIGINT ( 0x23, 0xac, 0x78, 0x72 ), + BIGINT ( 0x6a, 0x07, 0x80, 0xbf, 0x1b, 0xa5, + 0xf8, 0x0b, 0x90, 0x06, 0xa4, 0xa5, + 0x44, 0x13, 0xba, 0x4b, 0xb3, 0xce, + 0x9f, 0x55, 0x42, 0x56, 0xc3, 0x30, + 0x82, 0x85, 0x5a, 0x3b, 0xae, 0x88, + 0x92, 0x4e, 0x3c, 0x37, 0xf6, 0x80, + 0x4c, 0x03, 0x3c, 0x1e, 0x2c, 0x17, + 0xef, 0x9d, 0xd7, 0x6f, 0xdc, 0xbb, + 0x42, 0x42, 0xa1, 0x7f, 0x97, 0x66, + 0xcd, 0xc8, 0x8a, 0x7c, 0xc6, 0x70, + 0x61, 0x54, 0x82, 0xd0, 0xd0, 0x8b, + 0xd5, 0x4f, 0x57, 0x7b, 0x8e, 0xab, + 0xdc, 0xbf, 0x8e, 0x85, 0x94, 0x83, + 0x8a, 0xb3, 0x72, 0x69, 0x2d, 0x51, + 0xdd, 0x86, 0x1e, 0x58, 0xb8, 0x00, + 0xe2, 0x5e, 0xa7, 0xef, 0x6a, 0x6a, + 0xb0, 0x10, 0x3d, 0x53, 0xfe, 0x23, + 0x51, 0xc0, 0x51, 0xed, 0x1f, 0x02, + 0x4b, 0x73, 0x17, 0x59, 0xfa, 0xb9, + 0xa8, 0x05, 0xa7, 0x79, 0xc3, 0xc9, + 0x4c, 0x2d, 0x58, 0x59, 0x10, 0x99, + 0x71, 0xe6 ), + BIGINT ( 0x01, 0x63, 0xd0, 0x07 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xff, 0x2a, 0x37, 0x04, 0xd4, 0x08, + 0x9f, 0xf5, 0xac, 0x29, 0x7f, 0x4b, + 0x93, 0x86, 0x02, 0x26, 0xac, 0x29, + 0xa8, 0xf9, 0x77, 0x91, 0x20 ), + BIGINT ( 0x2c, 0xb2, 0xe2, 0x1f, 0x4b, 0x97, + 0xaa, 0x3b, 0xd1, 0x36, 0xb0, 0x40, + 0x8b, 0x1c, 0x19, 0xa2, 0xea, 0xc8, + 0xc6, 0x4e, 0x2a, 0x66, 0x50 ), + BIGINT ( 0x97 ), + BIGINT ( 0x04, 0x22, 0x44, 0xe2, 0x14, 0x54, + 0x6c, 0x5a, 0xba, 0x1b, 0x39, 0xb7, + 0xaa, 0x06, 0xcf, 0x2b, 0xc8, 0x7e, + 0xc0, 0xe0, 0x70, 0xf2, 0x90 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xcd, 0xf3, 0xf7, 0x50, 0x13, 0x39, + 0x13, 0x4a, 0x56, 0xc5, 0xb8, 0xa6, + 0x42, 0x2d, 0x40, 0x5e, 0x07, 0xf2, + 0x92, 0x2a, 0x51, 0x87, 0x20 ), + BIGINT ( 0x93, 0x1a, 0x28, 0xbb, 0x69, 0x4f, + 0x31, 0x01, 0xe0, 0x88, 0x8a, 0x4c, + 0x4f, 0x9b, 0xda, 0xf6, 0x4e, 0xf3, + 0x11, 0xe7, 0x35, 0xa1, 0xfb ), + BIGINT ( 0x66, 0x69 ), + BIGINT ( 0x7a, 0x5a, 0x9b, 0x84, 0x72, 0x8f, + 0x57, 0x31, 0xb4, 0x34, 0x70, 0x18, + 0x77, 0xa6, 0x43, 0xa9, 0x51, 0x69, + 0x07, 0x3e, 0xf6, 0x68, 0x82 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xdd, 0x4c, 0x85, 0xcb, 0x3f, 0x45, + 0x61, 0xe0, 0x58, 0x1e, 0xad, 0xd3, + 0x6b, 0xef, 0x82, 0x53, 0x4a, 0x16, + 0x1a, 0xf0, 0x09, 0x82, 0x74 ), + BIGINT ( 0xd2, 0xa2, 0x73, 0x89, 0x0c, 0x56, + 0xe4, 0x31, 0xdf, 0x70, 0x3c, 0x40, + 0x0d, 0x36, 0xfc, 0x4a, 0xf3, 0xa2, + 0x8f, 0x9a, 0x9d, 0xaa, 0xb0 ), + BIGINT ( 0xbc, 0xca, 0x45 ), + BIGINT ( 0x9f, 0x5f, 0x7c, 0xac, 0x5e, 0xc7, + 0xf2, 0xc5, 0x72, 0x3d, 0xff, 0x29, + 0xd2, 0x25, 0xa9, 0x64, 0x5b, 0xbe, + 0x63, 0x63, 0xc6, 0x84, 0x20 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xf8, 0xc9, 0xb9, 0x3d, 0xe1, 0xff, + 0xa6, 0x8e, 0xb0, 0xd2, 0xa9, 0xa9, + 0xc1, 0x5c, 0xc5, 0x94, 0x90, 0xb9, + 0xca, 0x2f, 0x1a, 0xbd, 0x21 ), + BIGINT ( 0xa7, 0xf4, 0xb0, 0x3c, 0xf4, 0x2b, + 0x9d, 0x40, 0x5f, 0xfd, 0x2e, 0x28, + 0xa9, 0x23, 0x01, 0xaf, 0x0b, 0x73, + 0xaa, 0xcf, 0x14, 0xdc, 0xd8 ), + BIGINT ( 0x31, 0xe2, 0xe8, 0xf0 ), + BIGINT ( 0x53, 0x30, 0xc6, 0x10, 0x12, 0x7c, + 0xb3, 0x91, 0x15, 0x5f, 0x01, 0x62, + 0xec, 0x1f, 0x15, 0x61, 0x3b, 0x9a, + 0x76, 0x22, 0xf8, 0x31, 0xb1 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xff, 0x8c, 0x04, 0x74, 0x3e, 0x93, + 0xfd, 0xce, 0xd5, 0x7f, 0xc5, 0x58, + 0xce, 0x00, 0x53, 0x44, 0x02, 0xf4, + 0xfd, 0x01, 0xc3, 0xb0, 0x3c ), + BIGINT ( 0x2f, 0xbe, 0xb3, 0x2d, 0xd6, 0x59, + 0x69, 0x44, 0xc0, 0xd4, 0x27, 0x9c, + 0xff, 0x53, 0x9e, 0x66, 0x2c, 0x01, + 0x3a, 0x96, 0x5d, 0x75, 0xc1 ), + BIGINT ( 0x47, 0x3e, 0xb2, 0x81, 0x51, 0x9a, + 0xdf, 0x75, 0xba, 0xa5, 0x19, 0xc1, + 0xc7, 0xcc, 0xae, 0x82, 0x9c, 0x3e, + 0xfd, 0x7f, 0xb0, 0xd7, 0x00 ), + BIGINT ( 0x09, 0x9c, 0xd0, 0x49, 0x1d, 0x88, + 0xd8, 0x08, 0x45, 0x61, 0x71, 0xa1, + 0xb5, 0xab, 0xa9, 0x5b, 0xa8, 0xf1, + 0xc6, 0x53, 0x68, 0x8f, 0x3e ) ); + bigint_mod_exp_ok ( BIGINT ( 0xd8, 0x78, 0xad, 0x80, 0x81, 0xf1, + 0x84, 0x23, 0x82, 0x5d, 0x49, 0x46, + 0x75, 0xfd, 0xd1, 0x49, 0x53, 0x10, + 0x4d, 0x10, 0xab, 0x0f, 0xf0 ), + BIGINT ( 0x78, 0x3d, 0x09, 0x1b, 0xea, 0xa4, + 0xb9, 0x13, 0xf8, 0xb5, 0xb5, 0x5e, + 0x69, 0xa4, 0xe1, 0xfd, 0x88, 0x58, + 0x26, 0xb3, 0x76, 0xa2, 0x38 ), + BIGINT ( 0x3b, 0x12, 0xe0, 0x8e, 0xa2, 0x2f, + 0x2a, 0x2b, 0xb1, 0x78, 0xf9, 0xf6, + 0x93, 0x4d, 0x52, 0x82, 0x29, 0x2d, + 0xe4, 0x36, 0x92, 0x49, 0xc1, 0x25, + 0x6e, 0x26, 0xe6, 0x6e, 0xc2, 0x4d, + 0xea, 0x13, 0x86, 0x85, 0x71, 0x4d, + 0x85, 0x70, 0xf9, 0x2b, 0xa0, 0x0f, + 0x96, 0xe5, 0x63, 0x7a, 0xb4, 0x25, + 0x53, 0x1a, 0xd8, 0x30, 0x36, 0xba, + 0x6e, 0x2e, 0xce, 0x2d, 0x8f, 0x32, + 0xe9, 0xdc, 0x91, 0x9e, 0xd4, 0xf1, + 0x3b, 0x40, 0xc9, 0xf4, 0x97, 0x74, + 0x5e, 0x69, 0xcd, 0x34, 0x4a, 0x18, + 0x65, 0xe5, 0x07, 0xb5, 0x9e, 0x2a, + 0xc4, 0xeb, 0xb6, 0x96, 0x7b, 0x99, + 0x0c, 0xe4, 0xb3, 0x85, 0xff, 0x17, + 0x72, 0x5d, 0xf6, 0x30, 0xb4, 0xff, + 0x98, 0xe6, 0xf6, 0x31, 0x24, 0x82, + 0x91, 0xa6, 0x18, 0x6d, 0x0b, 0x84, + 0x6f, 0x5f, 0x64, 0xa3, 0xdf, 0x92, + 0x06, 0x16, 0xe3, 0x7c, 0x08, 0x61, + 0x77, 0xce ), + BIGINT ( 0x17, 0xc9, 0xc5, 0x38, 0x4c, 0x15, + 0x0f, 0x4e, 0xc2, 0x90, 0x3b, 0x46, + 0x7b, 0x2f, 0x95, 0x82, 0xfe, 0x51, + 0x95, 0x2b, 0xff, 0xd5, 0x28 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x69, 0xa3, 0x7e, 0x24, 0xdf, 0x9e, + 0x0b, 0x3e, 0x3f, 0x43, 0x06, 0x0e, + 0x1d, 0x57, 0x74, 0xe0, 0xa0, 0x5b, + 0x82, 0xca, 0xb0, 0x33, 0x8b, 0xe4, + 0x39, 0x27, 0x41, 0xd4, 0x2e, 0x30, + 0x3a, 0x0e, 0x62, 0x6f, 0xfa, 0xb4, + 0x02, 0x88, 0x70, 0x35, 0xa6, 0xea, + 0x7d, 0xb2, 0x87, 0xc3, 0xa5, 0x50, + 0x49, 0x38, 0xa4, 0x68, 0xa9, 0xe4, + 0xa6, 0xcc, 0xd7, 0x13, 0xb1, 0xd9, + 0x1c, 0x6a, 0x9a, 0xb8, 0x6c, 0x9b, + 0xff, 0xcd, 0x2c, 0xb3, 0xbd, 0xe2, + 0xfd, 0x1f, 0x08, 0xdd, 0xc6, 0xee, + 0x18, 0x0c, 0xa5, 0xcd, 0x09, 0x19, + 0x51, 0x51, 0xa5, 0x6f, 0x93, 0x1b, + 0x34, 0xfd, 0x8f, 0xd9, 0x87, 0xed, + 0x15, 0x7e, 0x36, 0x60, 0xdd, 0x1b, + 0xf4, 0xcc, 0xc4, 0x4c, 0x19, 0x2b, + 0xd6, 0x1e, 0xec, 0x51, 0xe9, 0x27, + 0xe9, 0xbd, 0x6a, 0x3f, 0x91, 0x45, + 0xc3, 0x6d, 0x40, 0x7e, 0x6c, 0x56, + 0x05, 0x5a ), + BIGINT ( 0x5c, 0x96, 0x05, 0x81, 0x94, 0x45, + 0xcf, 0x47, 0x5f, 0x1b, 0xb0, 0xf9, + 0xef, 0x13, 0x8f, 0xcc, 0x71, 0xfd, + 0x50, 0xf1, 0xe7, 0x62, 0x6e, 0xfa, + 0x48, 0x66, 0x1c, 0xf7, 0xef, 0x09, + 0x12, 0xa2, 0xfd, 0x17, 0xb7, 0x6a, + 0x3b, 0xed, 0xf7, 0x86, 0xd2, 0xbe, + 0x95, 0x90, 0xc6, 0x00, 0x14, 0x8d, + 0xe3, 0x27, 0xbe, 0x03, 0x7c, 0x9e, + 0x6b, 0x51, 0x31, 0x8d, 0x18, 0xc4, + 0x16, 0xd2, 0x84, 0x63, 0x9b, 0xe9, + 0xa4, 0xf8, 0xff, 0x70, 0x4d, 0xeb, + 0x6f, 0x4a, 0xb7, 0x5b, 0x54, 0xf1, + 0xb5, 0xbe, 0x78, 0xb6, 0xfd, 0x8b, + 0xe1, 0x39, 0x62, 0x85, 0x9b, 0xde, + 0x30, 0xa8, 0xe4, 0x37, 0x52, 0x57, + 0x39, 0x79, 0xdb, 0x0b, 0x19, 0x6b, + 0xc9, 0x17, 0xfd, 0x8c, 0x2c, 0xaa, + 0xa4, 0xf1, 0x04, 0xd1, 0xd3, 0x2f, + 0xbb, 0x3a, 0x36, 0x82, 0x31, 0xa4, + 0x40, 0xd4, 0x87, 0x46, 0xe3, 0x6e, + 0xd0, 0x17 ), + BIGINT ( 0x93 ), + BIGINT ( 0x0d, 0x39, 0x92, 0x57, 0xaa, 0x6d, + 0xfc, 0x3b, 0x10, 0x18, 0x6d, 0x59, + 0xbe, 0x31, 0x8f, 0xee, 0xf9, 0x82, + 0x84, 0xe0, 0xdf, 0xa5, 0x00, 0x28, + 0xd1, 0x64, 0x6b, 0x4b, 0x43, 0x3b, + 0x76, 0x3e, 0x6b, 0xc4, 0xe4, 0xf5, + 0x0b, 0x59, 0x5a, 0xe4, 0x53, 0x5e, + 0x02, 0xd4, 0xde, 0x72, 0xd3, 0xa3, + 0x58, 0x66, 0xa7, 0xdd, 0x2b, 0x0b, + 0xa4, 0x83, 0xd0, 0xd9, 0xef, 0x29, + 0x3d, 0x2f, 0x97, 0xff, 0x9a, 0xc7, + 0xf6, 0x8a, 0x8d, 0x59, 0xef, 0x87, + 0xd1, 0xe6, 0xba, 0x4d, 0x99, 0xd9, + 0x5f, 0x5e, 0x7a, 0x7e, 0x67, 0x22, + 0x5b, 0x77, 0x83, 0xa2, 0x02, 0xfd, + 0xb2, 0xe4, 0xf6, 0x20, 0x4c, 0x12, + 0x20, 0xa7, 0xda, 0x5b, 0x3b, 0x8c, + 0xa2, 0xca, 0xda, 0x20, 0xaa, 0x27, + 0xe6, 0x54, 0x3e, 0xa8, 0x6f, 0x64, + 0x9d, 0xa7, 0x0d, 0x57, 0x1b, 0x21, + 0xff, 0xd2, 0xe2, 0xb2, 0x0a, 0x4f, + 0xb7, 0x0e ) ); + bigint_mod_exp_ok ( BIGINT ( 0x06, 0xcf, 0x54, 0xf2, 0x0d, 0x62, + 0x33, 0xdd, 0xe7, 0x4d, 0x7f, 0x2f, + 0x8e, 0x52, 0x73, 0xf4, 0x73, 0x68, + 0x4b, 0x13, 0x6e, 0x58, 0x6b, 0x4a, + 0xb8, 0x4c, 0xef, 0x73, 0xfe, 0x5f, + 0xf6, 0xd0, 0xbb, 0x82, 0x17, 0x3f, + 0x9d, 0x91, 0xf8, 0xa3, 0xb8, 0x79, + 0xef, 0x41, 0x38, 0xc1, 0xef, 0xc9, + 0xc6, 0xcf, 0x2a, 0xc3, 0xaa, 0x75, + 0x17, 0xda, 0xbc, 0x76, 0x29, 0x61, + 0x6d, 0x05, 0x79, 0x0b, 0x44, 0xb1, + 0x54, 0x75, 0xb7, 0xd9, 0xf6, 0xa8, + 0xbd, 0xf7, 0x85, 0xe0, 0xe7, 0x90, + 0x62, 0xce, 0x79, 0xfb, 0xc5, 0x23, + 0xa5, 0x09, 0xc0, 0xc4, 0x4d, 0xe7, + 0x9c, 0x49, 0x8f, 0x82, 0xf1, 0x31, + 0x34, 0x85, 0xdd, 0x3b, 0xbe, 0xe9, + 0x93, 0x19, 0x03, 0x75, 0x3f, 0xc4, + 0xa4, 0x0f, 0x52, 0x53, 0xc1, 0xcd, + 0x08, 0xb0, 0x05, 0x0c, 0xa2, 0x0c, + 0x3a, 0x72, 0xb2, 0x3c, 0xdb, 0x4f, + 0xac, 0xc6 ), + BIGINT ( 0xe4, 0x40, 0xd8, 0x30, 0x00, 0xcf, + 0x4c, 0xfd, 0xda, 0xae, 0x90, 0xd3, + 0x5b, 0xc7, 0x20, 0xcc, 0x2b, 0xe2, + 0x0a, 0x39, 0x1e, 0xde, 0xef, 0x98, + 0x16, 0x3b, 0x9d, 0x36, 0x63, 0x0d, + 0x46, 0xed, 0x23, 0x6e, 0x38, 0xa8, + 0x15, 0xb5, 0xb1, 0xaf, 0x47, 0xb1, + 0xec, 0xaa, 0x8b, 0x57, 0xd6, 0xca, + 0x39, 0x2f, 0x62, 0xbd, 0xd5, 0xf8, + 0x98, 0x98, 0x5d, 0xfe, 0x14, 0xd6, + 0xdc, 0xe5, 0x98, 0x60, 0x5b, 0x16, + 0x92, 0xcb, 0xed, 0xb6, 0x9c, 0x5c, + 0x82, 0x40, 0x6b, 0xaa, 0x48, 0x7a, + 0xd4, 0xfe, 0xa3, 0xe7, 0x30, 0xf1, + 0x7c, 0xfb, 0x94, 0x2e, 0xeb, 0xb6, + 0x71, 0xe4, 0x33, 0x63, 0xc3, 0xb0, + 0x94, 0x6d, 0xee, 0xa5, 0x15, 0x3f, + 0x28, 0xf1, 0xfa, 0xdc, 0xf2, 0x13, + 0x0f, 0xc7, 0xd9, 0xe0, 0xbf, 0x1b, + 0x49, 0xee, 0x21, 0x8e, 0x26, 0xc9, + 0x28, 0x21, 0x86, 0x1d, 0x46, 0x33, + 0xd4, 0x69 ), + BIGINT ( 0xd9, 0x87 ), + BIGINT ( 0xdf, 0xff, 0xcc, 0xb7, 0xfe, 0x19, + 0x02, 0x92, 0x9d, 0xab, 0x33, 0xd2, + 0x21, 0xbc, 0xd3, 0xc4, 0x31, 0xad, + 0x4b, 0xb3, 0x16, 0x50, 0x96, 0xd9, + 0xdc, 0x88, 0x74, 0x60, 0xde, 0xdf, + 0xb7, 0x83, 0xdb, 0x22, 0xef, 0xcb, + 0xcb, 0xdb, 0x4c, 0xfb, 0x94, 0x4c, + 0x3f, 0xf5, 0xf5, 0x99, 0x85, 0x21, + 0x1a, 0x2b, 0xec, 0x90, 0x2d, 0xb4, + 0x20, 0x3c, 0x27, 0x9f, 0xe5, 0xb1, + 0x5c, 0x92, 0xfa, 0xb0, 0xa9, 0x8e, + 0x2c, 0x21, 0x8e, 0x8d, 0xe5, 0x55, + 0x84, 0x02, 0xa5, 0x15, 0x5c, 0x53, + 0x1f, 0x40, 0x81, 0x0a, 0x10, 0xde, + 0x21, 0x41, 0xa9, 0x97, 0xf8, 0x6f, + 0xbf, 0x42, 0x58, 0x9e, 0xc6, 0xdd, + 0x10, 0x33, 0x3f, 0xad, 0xe6, 0x8e, + 0x57, 0x27, 0x37, 0x20, 0xa4, 0x86, + 0xef, 0x39, 0x7b, 0x6f, 0x78, 0x77, + 0xab, 0xa0, 0x62, 0xe1, 0xfd, 0x9c, + 0xbe, 0xfa, 0x98, 0x2e, 0x29, 0xe3, + 0xeb, 0x52 ) ); + bigint_mod_exp_ok ( BIGINT ( 0x00, 0x91, 0xb3, 0x87, 0xe6, 0x01, + 0x57, 0xe9, 0x68, 0xa4, 0xf4, 0x9b, + 0xea, 0x6a, 0x8a, 0x9e, 0x1a, 0x8b, + 0xd3, 0x85, 0x9d, 0xba, 0x85, 0xab, + 0xd8, 0xcd, 0x25, 0x56, 0x8e, 0x85, + 0x8a, 0x8e, 0x48, 0x9e, 0xb4, 0x90, + 0xc8, 0x2e, 0x07, 0x78, 0x80, 0x49, + 0xa0, 0xb7, 0x95, 0x6a, 0xd8, 0xad, + 0xb5, 0xda, 0x5d, 0xe6, 0x11, 0x87, + 0xb8, 0x33, 0x8f, 0xa8, 0x6f, 0x4e, + 0xc6, 0xc3, 0x0d, 0xf5, 0xa9, 0x4e, + 0xb2, 0x42, 0x53, 0x81, 0xcd, 0x33, + 0x83, 0x49, 0xab, 0x0d, 0x0e, 0xf5, + 0x2c, 0xcd, 0x84, 0x58, 0xf3, 0x30, + 0xa3, 0x6e, 0x3c, 0x3a, 0xc6, 0x77, + 0x43, 0xb0, 0xe7, 0x4b, 0x66, 0x30, + 0xe9, 0x48, 0x0b, 0x0d, 0x86, 0x3f, + 0xd8, 0xe2, 0xb5, 0x88, 0xc1, 0x44, + 0xb2, 0x6b, 0xb0, 0x7a, 0x35, 0x3b, + 0x56, 0x83, 0xb1, 0xac, 0x9e, 0xeb, + 0x9b, 0x08, 0x43, 0xac, 0x0a, 0x3a, + 0x31, 0x69 ), + BIGINT ( 0x96, 0x6f, 0xb0, 0xa7, 0x02, 0xb5, + 0xd9, 0x19, 0xbe, 0x4b, 0x27, 0x65, + 0x5b, 0x96, 0xd4, 0x0b, 0x49, 0x70, + 0xf0, 0x09, 0x8e, 0xf2, 0x04, 0x85, + 0x93, 0xe9, 0x2e, 0x09, 0x31, 0x76, + 0x8b, 0xbb, 0xe9, 0xe1, 0x2b, 0x4f, + 0xed, 0x83, 0xa6, 0x87, 0xa3, 0x07, + 0x0a, 0x3d, 0x1c, 0x65, 0x14, 0x5a, + 0xd5, 0xc0, 0x5d, 0x3c, 0x31, 0x9a, + 0x83, 0xad, 0xca, 0x6a, 0x93, 0x0d, + 0x1a, 0x67, 0x4e, 0x68, 0x06, 0x64, + 0x53, 0x2e, 0x15, 0xd9, 0xdd, 0x5e, + 0xcb, 0xb7, 0x2e, 0xef, 0xd3, 0xbb, + 0x5f, 0xaf, 0xef, 0x9e, 0xf2, 0x7b, + 0x69, 0x15, 0xb0, 0x18, 0x6c, 0x67, + 0x10, 0xda, 0x33, 0x07, 0x48, 0x97, + 0x31, 0xb3, 0x3d, 0x3d, 0xc9, 0x2e, + 0x0b, 0x68, 0x91, 0x3f, 0x6a, 0x3b, + 0x1a, 0xdf, 0xa8, 0x69, 0x46, 0x1c, + 0xb2, 0x69, 0x08, 0x0b, 0x02, 0x1b, + 0x03, 0x64, 0xae, 0xb6, 0x2d, 0xc6, + 0xc4, 0x0a ), + BIGINT ( 0x6d, 0x3f, 0xdd ), + BIGINT ( 0x40, 0x6e, 0x9d, 0x3e, 0xeb, 0xa4, + 0xb1, 0x8d, 0xb7, 0xb4, 0x0f, 0x5b, + 0x12, 0xad, 0x27, 0x9e, 0xbd, 0xe7, + 0xe5, 0x9d, 0xec, 0xb4, 0xac, 0x23, + 0x5f, 0xa9, 0xec, 0x9c, 0xd1, 0x6a, + 0xbe, 0x99, 0xba, 0xb3, 0x66, 0x0e, + 0x17, 0xaa, 0x13, 0xa2, 0x2e, 0x01, + 0x28, 0xb1, 0x6c, 0xba, 0xad, 0x68, + 0x48, 0xf0, 0xf3, 0x4c, 0x08, 0x9f, + 0xd1, 0x9c, 0xb7, 0x75, 0xc5, 0xb6, + 0x5a, 0x05, 0xb0, 0x14, 0xd4, 0x61, + 0xea, 0x18, 0x9f, 0xe6, 0xe5, 0xe3, + 0xd4, 0xff, 0x35, 0x43, 0x0b, 0xb8, + 0xf6, 0xe9, 0x19, 0x7a, 0x88, 0xa7, + 0x4d, 0x01, 0x92, 0x05, 0xd2, 0x6e, + 0xa3, 0xc1, 0xb6, 0x66, 0x75, 0xb1, + 0x00, 0x0d, 0x42, 0x37, 0xcc, 0xca, + 0xc0, 0x8d, 0xc8, 0x7e, 0x5c, 0xc9, + 0x53, 0x81, 0x2f, 0xc4, 0x61, 0xb6, + 0x96, 0x3b, 0xa5, 0x04, 0x14, 0x1b, + 0xa7, 0x77, 0xa1, 0xbc, 0x73, 0x1d, + 0xad, 0xed ) ); + bigint_mod_exp_ok ( BIGINT ( 0x45, 0xfb, 0xf3, 0xdc, 0x31, 0xe5, + 0x56, 0x7a, 0xee, 0x15, 0xfb, 0x16, + 0xee, 0x6e, 0x90, 0x3e, 0xa3, 0x89, + 0xc2, 0x6d, 0x9b, 0x06, 0x65, 0xd0, + 0xcd, 0xa2, 0xcc, 0x01, 0x60, 0x0d, + 0xd1, 0xdd, 0x68, 0x14, 0xc2, 0xcd, + 0xd8, 0x79, 0x75, 0xad, 0x0a, 0x9f, + 0x39, 0x5f, 0x52, 0x4b, 0x58, 0x31, + 0x48, 0xbb, 0x2a, 0xcc, 0xe0, 0x42, + 0x18, 0x32, 0xdc, 0x63, 0x14, 0x11, + 0x4e, 0xab, 0x96, 0x29, 0xc5, 0x06, + 0x79, 0xe5, 0x06, 0xf7, 0x59, 0xdb, + 0x1e, 0x51, 0xfd, 0xc4, 0x48, 0x3a, + 0x4c, 0x7f, 0xd0, 0xe2, 0x36, 0x86, + 0xc1, 0x8b, 0xc5, 0x86, 0x52, 0xe0, + 0xdb, 0x92, 0x5f, 0x0e, 0x19, 0xb1, + 0xa3, 0x23, 0xdd, 0xf0, 0x78, 0xcc, + 0x81, 0x3f, 0x4a, 0xe6, 0xb0, 0x32, + 0xd1, 0x5c, 0x5e, 0x3a, 0xb0, 0xd8, + 0xe2, 0x04, 0xc0, 0x30, 0x85, 0x1d, + 0x5e, 0x28, 0xee, 0xd9, 0xb3, 0x83, + 0x9f, 0xe2 ), + BIGINT ( 0xb3, 0x2c, 0x2e, 0xc5, 0xba, 0xf8, + 0x41, 0x98, 0x79, 0x7e, 0xaa, 0x0c, + 0x2a, 0x8f, 0xd9, 0x56, 0x55, 0xaa, + 0x74, 0x60, 0x74, 0xd1, 0x49, 0x2c, + 0x6f, 0x0a, 0x4e, 0xf8, 0x3f, 0x1b, + 0x73, 0x4c, 0xe0, 0x17, 0x37, 0x06, + 0x76, 0x73, 0xd5, 0x2d, 0x4d, 0x3f, + 0xb0, 0x15, 0x7e, 0x98, 0xd0, 0xdf, + 0xf0, 0x33, 0x78, 0xe2, 0xe6, 0xec, + 0x21, 0x22, 0xad, 0xd5, 0xab, 0x2d, + 0x0d, 0x59, 0x95, 0x05, 0x34, 0x1f, + 0x51, 0xf5, 0xec, 0x93, 0x05, 0x15, + 0x37, 0xcf, 0x93, 0x03, 0xd7, 0xf6, + 0x35, 0x23, 0x8f, 0x33, 0xf6, 0xba, + 0x42, 0xc8, 0x52, 0x94, 0xd3, 0x33, + 0x3e, 0x39, 0x01, 0xd1, 0x55, 0x3f, + 0x48, 0x84, 0xe9, 0xbc, 0x0b, 0x0f, + 0xc9, 0x69, 0x41, 0x2c, 0x5f, 0x34, + 0xd0, 0xe6, 0x15, 0x50, 0x06, 0x64, + 0x5b, 0x8b, 0x71, 0x22, 0xb3, 0x3e, + 0x09, 0x9c, 0x76, 0x13, 0x9b, 0x29, + 0x57, 0x94 ), + BIGINT ( 0xca, 0x94, 0xf7, 0xca ), + BIGINT ( 0x83, 0x68, 0xb9, 0xe7, 0x91, 0xf3, + 0x3b, 0x5a, 0x0b, 0xb6, 0x1e, 0x2f, + 0x3f, 0x5f, 0xdc, 0x96, 0x5b, 0x7f, + 0x8d, 0xc5, 0x8e, 0xda, 0x6e, 0x21, + 0xe3, 0x20, 0xea, 0x37, 0x39, 0x3b, + 0xb4, 0xd7, 0xf6, 0xba, 0x61, 0xfe, + 0xdc, 0x7e, 0x82, 0x9a, 0x38, 0x7b, + 0xd5, 0xb1, 0x11, 0x98, 0xc4, 0x88, + 0x0b, 0x01, 0x7d, 0x81, 0xc9, 0x64, + 0x23, 0xc3, 0x3e, 0xf3, 0x67, 0x95, + 0x78, 0xca, 0xda, 0x52, 0xaf, 0x72, + 0x25, 0xd9, 0xf0, 0x27, 0xd3, 0x1c, + 0xfb, 0xad, 0xa1, 0xa7, 0x06, 0x2f, + 0xaa, 0x2f, 0x86, 0x5c, 0x8b, 0x30, + 0xe1, 0xda, 0x5a, 0x36, 0xf9, 0xfd, + 0xbf, 0xfe, 0x0d, 0x03, 0xf8, 0x9c, + 0x6b, 0x9b, 0xe5, 0x70, 0x6d, 0x75, + 0xd7, 0x54, 0x28, 0x43, 0x34, 0x69, + 0x98, 0x11, 0x29, 0xee, 0x50, 0x06, + 0xa4, 0xc4, 0x11, 0x6d, 0x60, 0x8c, + 0xcd, 0xd1, 0x88, 0xe9, 0x6b, 0xbb, + 0xc1, 0xd4 ) ); + bigint_mod_exp_ok ( BIGINT ( 0xa1, 0x01, 0x7e, 0xb4, 0x0e, 0x66, + 0xa5, 0x07, 0x8b, 0x10, 0x84, 0x0d, + 0x30, 0x0a, 0xa4, 0x2d, 0x10, 0x2c, + 0xd4, 0x9a, 0x27, 0xf1, 0x02, 0x8c, + 0x38, 0x18, 0x7f, 0x7f, 0x95, 0x65, + 0xf1, 0xa9, 0x3b, 0x7d, 0x1f, 0x4f, + 0x88, 0xb0, 0x65, 0x62, 0x63, 0x63, + 0xaa, 0x82, 0xfc, 0x83, 0x3a, 0x3a, + 0x46, 0x59, 0x6a, 0x89, 0xec, 0xa9, + 0xb0, 0x4c, 0x5e, 0xbe, 0x46, 0x98, + 0xd0, 0xd4, 0xb7, 0xe3, 0x1b, 0x30, + 0x0b, 0xfb, 0xbb, 0x4f, 0x0b, 0xd3, + 0xe4, 0xa0, 0x80, 0x54, 0xcb, 0x52, + 0x0a, 0xe8, 0x03, 0x75, 0x8e, 0x96, + 0xa4, 0x21, 0xaa, 0xbd, 0x7a, 0xfd, + 0xfa, 0xf8, 0xaf, 0x42, 0xf6, 0x61, + 0xd2, 0x93, 0xce, 0x66, 0x67, 0xe9, + 0x02, 0xda, 0x81, 0x0b, 0xb0, 0x1e, + 0x9e, 0x27, 0x57, 0x98, 0x18, 0x88, + 0x35, 0x49, 0xc0, 0x88, 0x88, 0x59, + 0xae, 0x2f, 0x66, 0x59, 0x31, 0x87, + 0x88, 0xda ), + BIGINT ( 0xfe, 0x21, 0x7c, 0xf4, 0xbe, 0xae, + 0x65, 0xda, 0x89, 0xd2, 0x26, 0xd6, + 0x9c, 0x65, 0xc6, 0xb6, 0xb4, 0x0a, + 0x84, 0x11, 0xe1, 0xe8, 0xba, 0xd8, + 0x16, 0xcf, 0x60, 0x6c, 0x83, 0xa5, + 0x4a, 0xbf, 0xa2, 0x24, 0x0b, 0x66, + 0xda, 0xe2, 0x4e, 0x2d, 0xe5, 0x9e, + 0xbf, 0xad, 0x5c, 0xa3, 0x1e, 0x5c, + 0xbd, 0xe2, 0x5b, 0x46, 0xcf, 0xcc, + 0xd5, 0xc9, 0x13, 0x95, 0xc3, 0xdb, + 0x64, 0xbf, 0xeb, 0x31, 0xa9, 0x8a, + 0x3b, 0xd2, 0x5d, 0x3b, 0x2e, 0xdc, + 0x0c, 0xca, 0xab, 0xde, 0x92, 0xae, + 0x45, 0x35, 0x96, 0xb0, 0xb7, 0xb9, + 0xe6, 0xfe, 0x28, 0x0d, 0x10, 0x72, + 0x53, 0x8e, 0x21, 0xc0, 0x33, 0x79, + 0x01, 0x43, 0x8d, 0x77, 0xc4, 0xaa, + 0xcf, 0x7f, 0xc3, 0xd1, 0xf5, 0xfd, + 0x79, 0x81, 0xf6, 0x2e, 0xb7, 0xeb, + 0x55, 0x5f, 0x74, 0xf0, 0x3a, 0xb9, + 0x57, 0x07, 0x09, 0x97, 0xa5, 0x4c, + 0x4a, 0x85 ), + BIGINT ( 0xd9, 0xb7, 0xb2, 0xd6, 0xeb, 0xf3, + 0x66, 0xbe, 0x15, 0x64, 0xad, 0x2e, + 0x9e, 0xc6, 0xaf, 0x5e, 0xaf, 0x40, + 0x1e, 0x90, 0x82, 0x2f, 0x98 ), + BIGINT ( 0x12, 0x48, 0x31, 0x7f, 0x09, 0xbb, + 0x8f, 0xd9, 0x02, 0x7e, 0x4a, 0xd0, + 0x2f, 0x42, 0x7c, 0x17, 0x6e, 0x83, + 0x74, 0x21, 0x95, 0x47, 0x7d, 0x93, + 0x4a, 0xce, 0x34, 0x7c, 0xde, 0xc7, + 0x8f, 0xf6, 0x28, 0x97, 0xba, 0x81, + 0x9b, 0xcc, 0x54, 0x14, 0x7f, 0xd3, + 0x93, 0x66, 0x41, 0x8c, 0x0e, 0x47, + 0xee, 0xc5, 0x5e, 0xd6, 0x5f, 0x01, + 0x62, 0x97, 0xf1, 0x2b, 0xee, 0x60, + 0x5e, 0x82, 0x2c, 0x7b, 0x0a, 0xf2, + 0xc3, 0x23, 0xbf, 0xb9, 0x83, 0xf7, + 0x97, 0xf5, 0xca, 0x58, 0xd7, 0xf0, + 0x87, 0x7b, 0xcb, 0x87, 0x69, 0x42, + 0xbc, 0x05, 0xc4, 0xad, 0xbd, 0x82, + 0xcf, 0x44, 0x16, 0x4f, 0x46, 0xe0, + 0xde, 0x2f, 0xfa, 0x77, 0xec, 0xa4, + 0x23, 0x7d, 0x47, 0x3e, 0x94, 0x19, + 0x8b, 0xb8, 0x84, 0x81, 0x80, 0x6c, + 0x1e, 0x31, 0xa3, 0x6d, 0x14, 0x94, + 0x57, 0x28, 0x99, 0x08, 0x0a, 0xa7, + 0x98, 0x4b ) ); + bigint_mod_exp_ok ( BIGINT ( 0xda, 0x52, 0xfd, 0x44, 0x5d, 0x11, + 0x60, 0x6c, 0xec, 0x87, 0xbf, 0x19, + 0xb8, 0x46, 0xaa, 0x41, 0xfc, 0x10, + 0xae, 0x47, 0xd6, 0x72, 0x42, 0x57, + 0xc3, 0x05, 0xca, 0xe3, 0x59, 0x94, + 0x82, 0x7c, 0xa1, 0xe0, 0xd2, 0x6b, + 0x77, 0x71, 0x42, 0xa1, 0xf7, 0x84, + 0xae, 0xf4, 0x6f, 0x44, 0x0d, 0x88, + 0xa2, 0xc5, 0x45, 0x9b, 0x49, 0x36, + 0xd4, 0x20, 0x3a, 0x7c, 0x92, 0xdb, + 0x65, 0xd9, 0x20, 0xd6, 0x71, 0x22, + 0x90, 0x70, 0xbf, 0xf3, 0x17, 0xe8, + 0x2c, 0x10, 0xe9, 0x4c, 0x02, 0x69, + 0x37, 0xa2, 0x91, 0x04, 0x46, 0x11, + 0xdc, 0xab, 0x5b, 0x1e, 0x3e, 0x31, + 0xd8, 0x69, 0xf8, 0x48, 0x84, 0x1f, + 0x56, 0x46, 0xf1, 0xc0, 0x14, 0x3f, + 0xcc, 0x5d, 0xe2, 0xf7, 0x8b, 0xa4, + 0x9e, 0x94, 0x32, 0xaa, 0x3c, 0x5e, + 0x21, 0x70, 0x00, 0x24, 0x2a, 0x1b, + 0xec, 0x25, 0xb1, 0xb6, 0x83, 0x36, + 0x5a, 0x95 ), + BIGINT ( 0x5e, 0xdc, 0x71, 0x1f, 0x5b, 0x55, + 0xaa, 0xda, 0x56, 0xf5, 0x93, 0x9b, + 0xe8, 0xfc, 0x6a, 0x80, 0xe1, 0xe3, + 0x93, 0xe4, 0xc0, 0x58, 0x6f, 0x22, + 0xce, 0x9d, 0x6f, 0x84, 0x4c, 0xd4, + 0x12, 0x44, 0x57, 0x25, 0xca, 0xe5, + 0x2b, 0x7c, 0x35, 0x88, 0xc7, 0x38, + 0x25, 0x20, 0x9b, 0x57, 0xf2, 0xf2, + 0x6c, 0x28, 0x47, 0x9c, 0x3f, 0x91, + 0x1e, 0x3f, 0xe9, 0xeb, 0x50, 0xd6, + 0xa7, 0x22, 0x88, 0x6c, 0x71, 0xe5, + 0x62, 0x2a, 0xb7, 0xce, 0xbe, 0xf7, + 0x1a, 0x8c, 0x52, 0xa6, 0xff, 0xb8, + 0x34, 0x83, 0x7e, 0x04, 0xa8, 0x9c, + 0xa8, 0xa7, 0xd1, 0x05, 0x8e, 0x13, + 0x03, 0xe0, 0x49, 0xd8, 0x4a, 0xc4, + 0x4d, 0x38, 0x21, 0x5b, 0x62, 0xc2, + 0x38, 0x23, 0x7c, 0x9e, 0xf1, 0xe9, + 0xb6, 0x9a, 0x75, 0x42, 0x14, 0x99, + 0x63, 0x36, 0x13, 0x4c, 0x2d, 0x3a, + 0x77, 0xd4, 0x74, 0xb7, 0x30, 0xb2, + 0x00, 0x0f ), + BIGINT ( 0xe3, 0xe5, 0x3b, 0xb5, 0x92, 0x5a, + 0xc6, 0xfa, 0x8f, 0xe8, 0x00, 0xb9, + 0x5c, 0xa0, 0xb6, 0x3e, 0x5e, 0x14, + 0x12, 0xa9, 0xdd, 0x2a, 0x3d, 0x4d, + 0xa3, 0x91, 0x6a, 0x56, 0x99, 0xc2, + 0x6c, 0x8e, 0xda, 0xb0, 0x5a, 0x2a, + 0x37, 0x55, 0x8b, 0xd3, 0x9b, 0xb6, + 0x1d, 0x49, 0x7d, 0x81, 0x76, 0x1c, + 0x2e, 0xb9, 0x92, 0x6d, 0xfa, 0x54, + 0x53, 0xfc, 0x74, 0x9b, 0x6b, 0x63, + 0x95, 0x1a, 0x89, 0xcc, 0xbd, 0x36, + 0xc5, 0x31, 0x7f, 0xf5, 0x31, 0x69, + 0x40, 0xd5, 0x7b, 0x94, 0x5d, 0xa9, + 0xd1, 0x34, 0x95, 0xa1, 0x8b, 0xa5, + 0xb5, 0x83, 0xda, 0xb5, 0x9d, 0x5b, + 0x74, 0x41, 0xad, 0x81, 0x45, 0x40, + 0x9b, 0xc3, 0xe8, 0xfe, 0x47, 0xdc, + 0xb0, 0xc3, 0x34, 0x5d, 0xf6, 0x3c, + 0x1d, 0x07, 0x76, 0xd9, 0x25, 0xca, + 0xa2, 0x39, 0x6c, 0xa8, 0xae, 0x30, + 0x4a, 0xde, 0xfb, 0xeb, 0x19, 0x80, + 0x5e, 0x49 ), + BIGINT ( 0x4b, 0x0e, 0x74, 0xb8, 0xa7, 0x92, + 0x74, 0xd9, 0x50, 0xf6, 0x1b, 0x67, + 0x76, 0x76, 0x56, 0x6c, 0x09, 0x9c, + 0x01, 0xda, 0xaf, 0xa3, 0xca, 0xb2, + 0x12, 0x85, 0x52, 0x24, 0xe9, 0x7e, + 0x2b, 0xf2, 0x6e, 0xe9, 0x1a, 0x10, + 0x5d, 0xa0, 0x25, 0x46, 0x8f, 0x2a, + 0x95, 0x62, 0x50, 0xb6, 0x66, 0x43, + 0x37, 0x8b, 0xcb, 0x05, 0xf8, 0x61, + 0x59, 0xf9, 0xdd, 0xd2, 0x68, 0x72, + 0xfa, 0x88, 0x13, 0x36, 0xd8, 0x24, + 0x73, 0xec, 0x47, 0x44, 0xdd, 0x45, + 0x8a, 0x59, 0xd2, 0xbd, 0x43, 0xe3, + 0x05, 0x16, 0xd5, 0x9b, 0x1c, 0x8a, + 0x4b, 0x07, 0xda, 0x58, 0x0d, 0x4a, + 0x4e, 0xe7, 0x15, 0xfc, 0xbd, 0x95, + 0xf7, 0x18, 0xa5, 0xa7, 0x93, 0xff, + 0xf8, 0x1f, 0xd4, 0x6b, 0x07, 0xc6, + 0x5d, 0x90, 0x73, 0x57, 0x57, 0x37, + 0xfa, 0x83, 0xd4, 0x7c, 0xe9, 0x77, + 0x46, 0x91, 0x3a, 0x50, 0x0d, 0x6a, + 0x25, 0xd0 ) ); +} + +/** Big integer self-test */ +struct self_test bigint_test __self_test = { + .name = "bigint", + .exec = bigint_test_exec, +}; diff --git a/src/tests/byteswap_test.c b/src/tests/byteswap_test.c new file mode 100644 index 00000000..9bfe2659 --- /dev/null +++ b/src/tests/byteswap_test.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Byte-order swapping test functions + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <assert.h> +#include <byteswap.h> +#include <ipxe/test.h> + +/* Provide global functions to allow inspection of generated assembly code */ + +uint16_t test_bswap16 ( uint16_t x ) { + return __bswap_16 ( x ); +} + +uint32_t test_bswap32 ( uint32_t x ) { + return __bswap_32 ( x ); +} + +uint64_t test_bswap64 ( uint64_t x ) { + return __bswap_64 ( x ); +} + +void test_bswap16s ( uint16_t *x ) { + __bswap_16s ( x ); +} + +void test_bswap32s ( uint32_t *x ) { + __bswap_32s ( x ); +} + +void test_bswap64s ( uint64_t *x ) { + __bswap_64s ( x ); +} + +/** + * Perform byte-order swapping + * + */ +static void byteswap_test_exec ( void ) { + uint16_t test16; + uint32_t test32; + uint64_t test64; + + ok ( test_bswap16 ( 0x1234 ) == 0x3412 ); + ok ( test_bswap32 ( 0x12345678UL ) == 0x78563412UL ); + ok ( test_bswap64 ( 0x123456789abcdef0ULL ) == 0xf0debc9a78563412ULL ); + + test16 = 0xabcd; + test_bswap16s ( &test16 ); + ok ( test16 == 0xcdab ); + + test32 = 0xabcdef01UL; + test_bswap32s ( &test32 ); + ok ( test32 == 0x01efcdabUL ); + + test64 = 0xabcdef0123456789ULL; + test_bswap64s ( &test64 ); + ok ( test64 == 0x8967452301efcdabULL ); +} + +/** Byte-order swapping self-test */ +struct self_test byteswap_test __self_test = { + .name = "byteswap", + .exec = byteswap_test_exec, +}; diff --git a/src/tests/cbc_test.c b/src/tests/cbc_test.c new file mode 100644 index 00000000..ebff3268 --- /dev/null +++ b/src/tests/cbc_test.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * CBC self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <string.h> +#include <assert.h> +#include <ipxe/crypto.h> +#include "cbc_test.h" + +/** + * Test CBC encryption + * + * @v cipher Cipher algorithm + * @v key Key + * @v key_len Length of key + * @v iv Initialisation vector + * @v plaintext Plaintext data + * @v expected_ciphertext Expected ciphertext data + * @v len Length of data + * @ret ok Ciphertext is as expected + */ +int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, + size_t key_len, const void *iv, const void *plaintext, + const void *expected_ciphertext, size_t len ) { + uint8_t ctx[ cipher->ctxsize ]; + uint8_t ciphertext[ len ]; + int rc; + + /* Initialise cipher */ + rc = cipher_setkey ( cipher, ctx, key, key_len ); + assert ( rc == 0 ); + cipher_setiv ( cipher, ctx, iv ); + + /* Perform encryption */ + cipher_encrypt ( cipher, ctx, plaintext, ciphertext, len ); + + /* Verify result */ + return ( memcmp ( ciphertext, expected_ciphertext, len ) == 0 ); +} + +/** + * Test CBC decryption + * + * @v cipher Cipher algorithm + * @v key Key + * @v key_len Length of key + * @v iv Initialisation vector + * @v ciphertext Ciphertext data + * @v expected_plaintext Expected plaintext data + * @v len Length of data + * @ret ok Plaintext is as expected + */ +int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, + size_t key_len, const void *iv, const void *ciphertext, + const void *expected_plaintext, size_t len ) { + uint8_t ctx[ cipher->ctxsize ]; + uint8_t plaintext[ len ]; + int rc; + + /* Initialise cipher */ + rc = cipher_setkey ( cipher, ctx, key, key_len ); + assert ( rc == 0 ); + cipher_setiv ( cipher, ctx, iv ); + + /* Perform encryption */ + cipher_decrypt ( cipher, ctx, ciphertext, plaintext, len ); + + /* Verify result */ + return ( memcmp ( plaintext, expected_plaintext, len ) == 0 ); +} diff --git a/src/tests/cbc_test.h b/src/tests/cbc_test.h new file mode 100644 index 00000000..40356cc3 --- /dev/null +++ b/src/tests/cbc_test.h @@ -0,0 +1,53 @@ +#ifndef _CBC_TEST_H +#define _CBC_TEST_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/crypto.h> +#include <ipxe/test.h> + +extern int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, + size_t key_len, const void *iv, + const void *plaintext, + const void *expected_ciphertext, size_t len ); +extern int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, + size_t key_len, const void *iv, + const void *ciphertext, + const void *expected_plaintext, size_t len ); + +/** + * Report CBC encryption test result + * + * @v cipher Cipher algorithm + * @v key Key + * @v key_len Length of key + * @v iv Initialisation vector + * @v plaintext Plaintext data + * @v expected_ciphertext Expected ciphertext data + * @v len Length of data + */ +#define cbc_encrypt_ok( cipher, key, key_len, iv, plaintext, \ + expected_ciphertext, len ) do { \ + ok ( cbc_test_encrypt ( cipher, key, key_len, iv, plaintext, \ + expected_ciphertext, len ) ); \ + } while ( 0 ) + +/** + * Report CBC decryption test result + * + * @v cipher Cipher algorithm + * @v key Key + * @v key_len Length of key + * @v iv Initialisation vector + * @v ciphertext Ciphertext data + * @v expected_plaintext Expected plaintext data + * @v len Length of data + */ +#define cbc_decrypt_ok( cipher, key, key_len, iv, ciphertext, \ + expected_plaintext, len ) do { \ + ok ( cbc_test_decrypt ( cipher, key, key_len, iv, ciphertext, \ + expected_plaintext, len ) ); \ + } while ( 0 ) + +#endif /* _CBC_TEST_H */ diff --git a/src/tests/cms_test.c b/src/tests/cms_test.c new file mode 100644 index 00000000..9de0228b --- /dev/null +++ b/src/tests/cms_test.c @@ -0,0 +1,1437 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * CMS self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <string.h> +#include <ipxe/sha256.h> +#include <ipxe/x509.h> +#include <ipxe/uaccess.h> +#include <ipxe/cms.h> +#include <ipxe/test.h> + +/** Fingerprint algorithm used for X.509 test certificates */ +#define cms_test_algorithm sha256_algorithm + +/** CMS test code blob */ +struct cms_test_code { + /** Data */ + const void *data; + /** Length of data */ + size_t len; +}; + +/** CMS test signature */ +struct cms_test_signature { + /** Data */ + const void *data; + /** Length of data */ + size_t len; + + /** Parsed signature */ + struct cms_signature *sig; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define inline fingerprint data */ +#define FINGERPRINT(...) { __VA_ARGS__ } + +/** Define a test code blob */ +#define SIGNED_CODE( name, DATA ) \ + static const uint8_t name ## _data[] = DATA; \ + static struct cms_test_code name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + } + +/** Define a test signature */ +#define SIGNATURE( name, DATA ) \ + static const uint8_t name ## _data[] = DATA; \ + static struct cms_test_signature name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + } + +/** Code that has been signed */ +SIGNED_CODE ( test_code, + DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63, + 0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x20, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x6f, 0x20, 0x61, + 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, + 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73, 0x68, + 0x65, 0x6c, 0x6c, 0x0a ) ); + +/** Code that has not been signed */ +SIGNED_CODE ( bad_code, + DATA ( 0x23, 0x21, 0x69, 0x70, 0x78, 0x65, 0x0a, 0x0a, 0x65, 0x63, + 0x68, 0x6f, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6c, 0x69, 0x63, 0x69, 0x6f, + 0x75, 0x73, 0x20, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x2e, 0x20, 0x20, 0x44, 0x6f, 0x20, + 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79, + 0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x21, 0x0a, 0x73, + 0x68, 0x65, 0x6c, 0x6c, 0x0a ) ); + +/** Valid signature */ +SIGNATURE ( codesigned_sig, + DATA ( 0x30, 0x82, 0x0c, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x32, 0x30, + 0x82, 0x0c, 0x2e, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x0a, 0xd8, 0x30, 0x82, 0x02, 0xac, 0x30, 0x82, + 0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, + 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, + 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30, + 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, + 0x02, 0x81, 0x81, 0x00, 0xc3, 0x3a, 0xdb, 0x7b, 0x17, 0x24, + 0x47, 0xb9, 0xb9, 0x17, 0x02, 0x17, 0xa8, 0xce, 0x21, 0x97, + 0x92, 0x2f, 0x65, 0x53, 0x3b, 0x7e, 0x5c, 0x7d, 0x13, 0xab, + 0x46, 0xe8, 0x4a, 0x44, 0x6c, 0x5d, 0x8f, 0xa2, 0x0c, 0x1d, + 0x69, 0xc1, 0x66, 0x48, 0xc4, 0x1a, 0xc9, 0x32, 0xe5, 0x97, + 0x92, 0xb7, 0x11, 0xa7, 0x1f, 0x21, 0xac, 0x96, 0xcb, 0x85, + 0x10, 0xcc, 0x23, 0x20, 0x51, 0xdd, 0xaf, 0xbe, 0xf5, 0x23, + 0x12, 0x0b, 0x03, 0xe9, 0xf9, 0x61, 0x86, 0x64, 0x82, 0xa4, + 0xfd, 0x53, 0x24, 0xdf, 0xc2, 0x96, 0x2e, 0x28, 0xbb, 0x94, + 0xfb, 0x2c, 0xaf, 0x9e, 0x07, 0x79, 0x96, 0x48, 0x24, 0xf0, + 0x9d, 0xb3, 0x11, 0x3d, 0x4c, 0x2e, 0xd8, 0xc9, 0xf9, 0x69, + 0xca, 0xdb, 0x16, 0xbd, 0x4c, 0xc5, 0xce, 0x28, 0x18, 0xdc, + 0x88, 0x1b, 0x31, 0x0d, 0x10, 0x6b, 0x5b, 0x10, 0xe9, 0xcc, + 0xfe, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x24, 0x30, + 0x22, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x22, 0x20, 0xe4, 0xc5, 0x0a, 0xef, + 0xae, 0xab, 0xbd, 0xab, 0x96, 0x56, 0x2c, 0x30, 0xeb, 0x06, + 0x84, 0xa0, 0x96, 0x37, 0x1a, 0x29, 0x2b, 0xeb, 0x8c, 0xb5, + 0x23, 0x22, 0x10, 0xef, 0x81, 0xe8, 0xdc, 0xa9, 0xdd, 0x8e, + 0x1d, 0x2c, 0xfc, 0xf5, 0x07, 0x19, 0xb7, 0x94, 0x91, 0xf7, + 0x2e, 0x07, 0xa1, 0xbc, 0xc5, 0x17, 0x34, 0xbe, 0x8a, 0x62, + 0x05, 0x5e, 0x9f, 0xe3, 0xce, 0xfd, 0x16, 0x42, 0xca, 0x25, + 0x2e, 0x0a, 0x03, 0x54, 0xd5, 0x3a, 0x52, 0x7f, 0x99, 0x94, + 0x96, 0xc6, 0xf5, 0xf0, 0xe3, 0x09, 0xd6, 0x00, 0x9b, 0x6f, + 0x0b, 0xa4, 0x9a, 0x13, 0x70, 0x9e, 0x67, 0xf9, 0x8c, 0x64, + 0xab, 0x22, 0x5d, 0xb3, 0xba, 0x2d, 0xe2, 0x70, 0xb8, 0x0c, + 0x6d, 0xd3, 0x12, 0x70, 0x5e, 0x04, 0x80, 0xef, 0x5e, 0x42, + 0x0a, 0x77, 0x57, 0x79, 0xa2, 0x1d, 0xe5, 0xbd, 0x20, 0xce, + 0x45, 0xc3, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, + 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, + 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, + 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, + 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, + 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, + 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, + 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, + 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, + 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, + 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, + 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, + 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, + 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81, 0xc6, 0x98, + 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19, 0x41, 0xae, + 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48, 0xf5, 0x42, + 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c, 0xd0, 0xee, + 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b, 0x34, 0x38, + 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84, 0xfc, 0x9b, + 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7, 0x31, 0xf4, + 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a, 0xcb, 0x6b, + 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f, 0x01, 0x46, + 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61, 0xf3, 0xdf, + 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21, 0x12, 0x4c, + 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82, 0xd1, 0xca, + 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, + 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x5d, + 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44, 0x98, 0xbf, + 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc, 0x35, 0x2f, + 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e, 0xc9, 0xb9, + 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29, 0x77, 0x01, + 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c, 0x13, 0x01, + 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00, 0x47, 0x36, + 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28, 0x82, 0xce, + 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac, 0x88, 0x45, + 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba, 0xb9, 0xc9, + 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5, 0xac, 0x5d, + 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3, 0x77, 0x62, + 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08, 0x59, 0x21, + 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6, 0x30, 0x82, 0x02, + 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, 0xd2, 0xdc, 0xc9, + 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, + 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, 0x38, 0x30, 0x38, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, + 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, + 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, + 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, 0xb5, 0xc1, 0x73, + 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, 0xeb, 0x1d, 0x9d, + 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, 0x75, 0x84, 0x66, + 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, 0x8f, 0x59, 0x64, + 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, 0x72, 0x93, 0xf2, + 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, 0x61, 0x50, 0xea, + 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, 0x2b, 0x75, 0xa6, + 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, 0xd5, 0xaf, 0x77, + 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, 0xda, 0xee, 0x72, + 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, 0x5d, 0x99, 0x4e, + 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, 0x6c, 0xe7, 0x5d, + 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, 0x16, 0x92, 0x66, + 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, 0x44, 0x24, 0x61, + 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, + 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, 0x17, 0x8d, 0x27, + 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, 0x36, 0xbd, 0xac, + 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, 0x05, 0x80, 0x6d, + 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, 0x29, 0xa1, 0xc6, + 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, 0xc8, 0x94, 0xa9, + 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, 0xdb, 0x63, 0x97, + 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, 0x3d, 0xed, 0xbb, + 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, 0xf8, 0x3c, 0x0e, + 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, 0xc0, 0x18, 0x53, + 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, 0xc9, 0x8e, 0x90, + 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, 0x6f, 0xc9, 0xe8, + 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, 0x63, 0x18, 0xc0, + 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, 0x10, 0xd4, 0x72, + 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, 0x02, 0x1f, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, + 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, + 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, + 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, + 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, + 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, + 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, + 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, + 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, + 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3, 0xd3, 0x02, + 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8, 0xc7, 0x13, + 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6, 0xdb, 0x3b, + 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea, 0x6e, 0x33, + 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed, 0xc5, 0x5b, + 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae, 0xde, 0x5a, + 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf, 0x8b, 0x0b, + 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b, 0x92, 0xd8, + 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b, 0xc4, 0xa0, + 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32, 0x26, 0x9a, + 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19, 0x7a, 0x80, + 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2, 0x3f, 0x1f, + 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, + 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19, 0xa0, 0xb8, + 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36, 0x4a, 0x8b, + 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17, 0xd7, 0x64, + 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b, 0xd4, 0xb5, + 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde, 0x87, 0xb2, + 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec, 0x0a, 0x86, + 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66, 0xc8, 0x7a, + 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea, 0xe5, 0xeb, + 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd, 0x89, 0xb3, + 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe, 0x04, 0xef, + 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66, 0x5a, 0x2f, + 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14, 0x55, 0xdc, + 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54, 0xf1, 0x45, + 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2f, 0x02, 0x01, + 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, + 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, + 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, + 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, + 0x20, 0x43, 0x41, 0x02, 0x01, 0x04, 0x30, 0x07, 0x06, 0x05, + 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04, 0x81, 0x80, 0x1f, 0x95, 0x53, 0x9c, 0x63, 0xcc, 0x9e, + 0xe3, 0x41, 0x30, 0xaf, 0x66, 0xac, 0x7c, 0x39, 0x69, 0xa0, + 0x02, 0xe3, 0x28, 0xfa, 0xf6, 0x71, 0xf4, 0xcf, 0x97, 0x2a, + 0xbb, 0xe0, 0x1d, 0x71, 0x73, 0x4a, 0xa7, 0xea, 0xb0, 0x72, + 0xc3, 0xd2, 0xba, 0x52, 0x42, 0x06, 0x88, 0x4a, 0xa6, 0x41, + 0x1d, 0x2f, 0x82, 0xb3, 0x7d, 0x32, 0x59, 0x34, 0x4e, 0x47, + 0x1b, 0xaa, 0x5e, 0x90, 0xe2, 0x73, 0x62, 0x2d, 0x6f, 0x6c, + 0x47, 0x52, 0x05, 0x90, 0xcb, 0xac, 0x30, 0xa8, 0x20, 0x71, + 0x14, 0x39, 0x16, 0x85, 0x3d, 0x32, 0x2f, 0x9d, 0x31, 0x97, + 0xa8, 0x96, 0xb9, 0xf2, 0x2b, 0xdc, 0xa6, 0x2f, 0x68, 0xc7, + 0xac, 0x46, 0xa2, 0xc7, 0x26, 0xd0, 0xde, 0xac, 0x1d, 0x5d, + 0x70, 0x65, 0xc6, 0x26, 0xdd, 0x30, 0x3f, 0x3a, 0xbd, 0x5e, + 0x8f, 0x87, 0x64, 0xab, 0xe7, 0xf9, 0x71, 0x64, 0x03, 0x05, + 0xbf ) ); + +/** Signature with a broken certificate chain */ +SIGNATURE ( brokenchain_sig, + DATA ( 0x30, 0x82, 0x09, 0x8a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0x7b, 0x30, + 0x82, 0x09, 0x77, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x08, 0x21, 0x30, 0x82, 0x02, 0xac, 0x30, 0x82, + 0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, + 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, + 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30, + 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, + 0x02, 0x81, 0x81, 0x00, 0xc3, 0x3a, 0xdb, 0x7b, 0x17, 0x24, + 0x47, 0xb9, 0xb9, 0x17, 0x02, 0x17, 0xa8, 0xce, 0x21, 0x97, + 0x92, 0x2f, 0x65, 0x53, 0x3b, 0x7e, 0x5c, 0x7d, 0x13, 0xab, + 0x46, 0xe8, 0x4a, 0x44, 0x6c, 0x5d, 0x8f, 0xa2, 0x0c, 0x1d, + 0x69, 0xc1, 0x66, 0x48, 0xc4, 0x1a, 0xc9, 0x32, 0xe5, 0x97, + 0x92, 0xb7, 0x11, 0xa7, 0x1f, 0x21, 0xac, 0x96, 0xcb, 0x85, + 0x10, 0xcc, 0x23, 0x20, 0x51, 0xdd, 0xaf, 0xbe, 0xf5, 0x23, + 0x12, 0x0b, 0x03, 0xe9, 0xf9, 0x61, 0x86, 0x64, 0x82, 0xa4, + 0xfd, 0x53, 0x24, 0xdf, 0xc2, 0x96, 0x2e, 0x28, 0xbb, 0x94, + 0xfb, 0x2c, 0xaf, 0x9e, 0x07, 0x79, 0x96, 0x48, 0x24, 0xf0, + 0x9d, 0xb3, 0x11, 0x3d, 0x4c, 0x2e, 0xd8, 0xc9, 0xf9, 0x69, + 0xca, 0xdb, 0x16, 0xbd, 0x4c, 0xc5, 0xce, 0x28, 0x18, 0xdc, + 0x88, 0x1b, 0x31, 0x0d, 0x10, 0x6b, 0x5b, 0x10, 0xe9, 0xcc, + 0xfe, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x24, 0x30, + 0x22, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x22, 0x20, 0xe4, 0xc5, 0x0a, 0xef, + 0xae, 0xab, 0xbd, 0xab, 0x96, 0x56, 0x2c, 0x30, 0xeb, 0x06, + 0x84, 0xa0, 0x96, 0x37, 0x1a, 0x29, 0x2b, 0xeb, 0x8c, 0xb5, + 0x23, 0x22, 0x10, 0xef, 0x81, 0xe8, 0xdc, 0xa9, 0xdd, 0x8e, + 0x1d, 0x2c, 0xfc, 0xf5, 0x07, 0x19, 0xb7, 0x94, 0x91, 0xf7, + 0x2e, 0x07, 0xa1, 0xbc, 0xc5, 0x17, 0x34, 0xbe, 0x8a, 0x62, + 0x05, 0x5e, 0x9f, 0xe3, 0xce, 0xfd, 0x16, 0x42, 0xca, 0x25, + 0x2e, 0x0a, 0x03, 0x54, 0xd5, 0x3a, 0x52, 0x7f, 0x99, 0x94, + 0x96, 0xc6, 0xf5, 0xf0, 0xe3, 0x09, 0xd6, 0x00, 0x9b, 0x6f, + 0x0b, 0xa4, 0x9a, 0x13, 0x70, 0x9e, 0x67, 0xf9, 0x8c, 0x64, + 0xab, 0x22, 0x5d, 0xb3, 0xba, 0x2d, 0xe2, 0x70, 0xb8, 0x0c, + 0x6d, 0xd3, 0x12, 0x70, 0x5e, 0x04, 0x80, 0xef, 0x5e, 0x42, + 0x0a, 0x77, 0x57, 0x79, 0xa2, 0x1d, 0xe5, 0xbd, 0x20, 0xce, + 0x45, 0xc3, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, + 0x9c, 0x58, 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, + 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, + 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, + 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, + 0x39, 0x30, 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, + 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, + 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, + 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, + 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, + 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xaa, 0x72, 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, + 0xab, 0x5e, 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, + 0xc7, 0xfa, 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, + 0x2d, 0xfd, 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, + 0x23, 0xc3, 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, + 0xf1, 0x47, 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, + 0x7a, 0xec, 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, + 0x48, 0x97, 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, + 0xb7, 0x9e, 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, + 0xfd, 0x9b, 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, + 0x8d, 0xd7, 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, + 0x2c, 0x24, 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, + 0x18, 0xb9, 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, + 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, + 0x9e, 0xea, 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, + 0xbe, 0x82, 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, + 0x30, 0x1c, 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, + 0x77, 0x75, 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, + 0xee, 0xb1, 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, + 0xbe, 0xf4, 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, + 0xa5, 0xd1, 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, + 0x0a, 0x04, 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, + 0x96, 0xf6, 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, + 0x77, 0x77, 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, + 0x4c, 0x34, 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, + 0xa9, 0xf5, 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, + 0xc5, 0x94, 0x10, 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02, + 0xb6, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, + 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, + 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, + 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, + 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, + 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, + 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, + 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, + 0x89, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b, + 0xd1, 0x48, 0xc3, 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22, + 0x3d, 0x90, 0xd8, 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0, + 0xad, 0x0e, 0xe6, 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6, + 0xea, 0x50, 0xea, 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49, + 0xd0, 0xf0, 0xed, 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa, + 0xd3, 0x3f, 0xae, 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f, + 0x40, 0x5e, 0xcf, 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e, + 0x0f, 0x18, 0x6b, 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6, + 0x15, 0xe8, 0x5b, 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd, + 0xa9, 0x7e, 0x32, 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca, + 0x2a, 0xd6, 0x19, 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, + 0xe7, 0x61, 0xd2, 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34, + 0xcb, 0x08, 0xa9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26, + 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, + 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70, + 0x02, 0x08, 0x19, 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41, + 0x90, 0x2a, 0x36, 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5, + 0xf8, 0x79, 0x17, 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04, + 0x54, 0x7a, 0x0b, 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06, + 0x2b, 0xf8, 0xde, 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba, + 0x9f, 0x8f, 0xec, 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73, + 0x2f, 0xa1, 0x66, 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5, + 0x75, 0xda, 0xea, 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49, + 0x9f, 0x8b, 0xfd, 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, + 0x29, 0xb2, 0xbe, 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3, + 0x9f, 0x07, 0x66, 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1, + 0xb0, 0x62, 0x14, 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13, + 0x04, 0x41, 0x54, 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30, + 0x82, 0x01, 0x2f, 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30, + 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, + 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, + 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01, + 0x04, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, 0x1f, 0x95, + 0x53, 0x9c, 0x63, 0xcc, 0x9e, 0xe3, 0x41, 0x30, 0xaf, 0x66, + 0xac, 0x7c, 0x39, 0x69, 0xa0, 0x02, 0xe3, 0x28, 0xfa, 0xf6, + 0x71, 0xf4, 0xcf, 0x97, 0x2a, 0xbb, 0xe0, 0x1d, 0x71, 0x73, + 0x4a, 0xa7, 0xea, 0xb0, 0x72, 0xc3, 0xd2, 0xba, 0x52, 0x42, + 0x06, 0x88, 0x4a, 0xa6, 0x41, 0x1d, 0x2f, 0x82, 0xb3, 0x7d, + 0x32, 0x59, 0x34, 0x4e, 0x47, 0x1b, 0xaa, 0x5e, 0x90, 0xe2, + 0x73, 0x62, 0x2d, 0x6f, 0x6c, 0x47, 0x52, 0x05, 0x90, 0xcb, + 0xac, 0x30, 0xa8, 0x20, 0x71, 0x14, 0x39, 0x16, 0x85, 0x3d, + 0x32, 0x2f, 0x9d, 0x31, 0x97, 0xa8, 0x96, 0xb9, 0xf2, 0x2b, + 0xdc, 0xa6, 0x2f, 0x68, 0xc7, 0xac, 0x46, 0xa2, 0xc7, 0x26, + 0xd0, 0xde, 0xac, 0x1d, 0x5d, 0x70, 0x65, 0xc6, 0x26, 0xdd, + 0x30, 0x3f, 0x3a, 0xbd, 0x5e, 0x8f, 0x87, 0x64, 0xab, 0xe7, + 0xf9, 0x71, 0x64, 0x03, 0x05, 0xbf ) ); + +/** Signature generated with a non-code-signing certificate */ +SIGNATURE ( genericsigned_sig, + DATA ( 0x30, 0x82, 0x0c, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x20, 0x30, + 0x82, 0x0c, 0x1c, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x0a, 0xc6, 0x30, 0x82, 0x02, 0x9a, 0x30, 0x82, + 0x02, 0x03, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x05, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, + 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x35, + 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30, + 0x30, 0x30, 0x31, 0x33, 0x35, 0x5a, 0x30, 0x81, 0x8b, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x19, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, + 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, + 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, + 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc6, 0xfc, 0x96, + 0x1e, 0x90, 0x32, 0xed, 0xb8, 0x54, 0xb2, 0xc2, 0x39, 0x66, + 0x19, 0xca, 0xd8, 0x45, 0x21, 0xb7, 0x5a, 0x8d, 0x8d, 0x71, + 0xef, 0x69, 0x37, 0x40, 0xbb, 0xa4, 0xde, 0x09, 0x1b, 0x17, + 0x83, 0x3a, 0x7a, 0xf1, 0x7b, 0x02, 0x31, 0x5d, 0x1f, 0x3a, + 0xe5, 0x29, 0x28, 0x9b, 0x7e, 0x7b, 0x5a, 0xc4, 0x18, 0x3e, + 0x43, 0xe6, 0xe9, 0x6e, 0xd1, 0x8d, 0x86, 0xcf, 0xb5, 0x9f, + 0x7f, 0x50, 0x4e, 0x06, 0x13, 0xf7, 0xb2, 0xee, 0xef, 0x0e, + 0xab, 0x50, 0x44, 0x42, 0xfd, 0x3a, 0xa9, 0x47, 0x83, 0x34, + 0x17, 0xdf, 0xee, 0x3d, 0x84, 0x1f, 0xed, 0x7e, 0xfa, 0x0f, + 0xa8, 0xfc, 0x07, 0xf8, 0xd1, 0x49, 0x99, 0x1a, 0xad, 0x39, + 0x16, 0xb3, 0x71, 0x15, 0x2e, 0x82, 0x20, 0x7a, 0x92, 0xed, + 0x1e, 0x37, 0xf6, 0x46, 0x5e, 0x7d, 0x9b, 0xa1, 0x53, 0x4d, + 0x13, 0x91, 0xcd, 0x7a, 0x77, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xa3, 0x0f, 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, + 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xb2, 0x39, 0x0b, 0x02, + 0x33, 0xca, 0x48, 0x96, 0x13, 0x53, 0xe9, 0x1b, 0x28, 0xd6, + 0x35, 0x4e, 0x0c, 0x9d, 0xd0, 0xe3, 0x79, 0x65, 0x0a, 0xe7, + 0xa6, 0x22, 0x61, 0x26, 0xbe, 0xb4, 0x05, 0xec, 0x5f, 0x83, + 0xb7, 0x0e, 0xa4, 0xae, 0x50, 0xb1, 0xa9, 0x45, 0x25, 0xf2, + 0x52, 0x1a, 0x63, 0x05, 0x50, 0x75, 0x33, 0xca, 0x8a, 0xb1, + 0xf2, 0x19, 0xd3, 0x93, 0x84, 0x67, 0x42, 0xe3, 0xb7, 0xa6, + 0xf9, 0x4d, 0x90, 0x7e, 0x13, 0x40, 0xd3, 0x22, 0x9f, 0x83, + 0xaf, 0x70, 0xb2, 0x7d, 0x4d, 0xcc, 0xae, 0x18, 0x9e, 0xca, + 0xc8, 0xcb, 0x82, 0x93, 0xcb, 0xce, 0xc6, 0x32, 0xcf, 0x4e, + 0x04, 0x64, 0x18, 0x5b, 0xc2, 0x1a, 0xb6, 0xd1, 0x8a, 0xc4, + 0x99, 0xce, 0xdd, 0xd7, 0x7e, 0xec, 0xf5, 0xa9, 0xa7, 0x00, + 0xc2, 0xd3, 0x6a, 0xb9, 0xcd, 0x25, 0x88, 0x08, 0x71, 0xf5, + 0x6d, 0x44, 0xe7, 0x93, 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, + 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, + 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, + 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, + 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, + 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81, + 0xc6, 0x98, 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19, + 0x41, 0xae, 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48, + 0xf5, 0x42, 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c, + 0xd0, 0xee, 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b, + 0x34, 0x38, 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84, + 0xfc, 0x9b, 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7, + 0x31, 0xf4, 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a, + 0xcb, 0x6b, 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f, + 0x01, 0x46, 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61, + 0xf3, 0xdf, 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21, + 0x12, 0x4c, 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82, + 0xd1, 0xca, 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, + 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, + 0x00, 0x5d, 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44, + 0x98, 0xbf, 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc, + 0x35, 0x2f, 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e, + 0xc9, 0xb9, 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29, + 0x77, 0x01, 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c, + 0x13, 0x01, 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00, + 0x47, 0x36, 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28, + 0x82, 0xce, 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac, + 0x88, 0x45, 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba, + 0xb9, 0xc9, 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5, + 0xac, 0x5d, 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3, + 0x77, 0x62, 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08, + 0x59, 0x21, 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6, 0x30, + 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02, + 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, 0xd2, + 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, + 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, + 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, + 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, + 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, + 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, + 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, 0x38, + 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, + 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, + 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, + 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x81, + 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, 0xb5, + 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, 0xeb, + 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, 0x75, + 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, 0x8f, + 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, 0x72, + 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, 0x61, + 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, 0x2b, + 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, 0xd5, + 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, 0xda, + 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, 0x5d, + 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, 0x6c, + 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, 0x16, + 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, 0x44, + 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, 0x17, + 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, 0x36, + 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, 0x05, + 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, 0x29, + 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, 0xc8, + 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, 0xdb, + 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, 0x3d, + 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, 0xf8, + 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, 0xc0, + 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, 0xc9, + 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, 0x6f, + 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, 0x63, + 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, 0x10, + 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, + 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, + 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, + 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, + 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, + 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, + 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, + 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, + 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, + 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3, + 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8, + 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6, + 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea, + 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed, + 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae, + 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf, + 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b, + 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b, + 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32, + 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19, + 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2, + 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19, + 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36, + 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17, + 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b, + 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde, + 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec, + 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66, + 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea, + 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd, + 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe, + 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66, + 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14, + 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54, + 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2f, + 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, + 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01, 0x05, 0x30, 0x07, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x04, 0x81, 0x80, 0xc5, 0x08, 0x17, 0x23, 0xb9, + 0x8d, 0x45, 0x0b, 0x1a, 0x9a, 0x10, 0xa7, 0x16, 0x57, 0x05, + 0x86, 0x0c, 0x9a, 0xfd, 0x2d, 0x9c, 0x87, 0x15, 0xb3, 0x0f, + 0xd5, 0x3b, 0x7b, 0xa8, 0xce, 0xa2, 0xcc, 0x2a, 0x2a, 0x6a, + 0xa0, 0xab, 0x2f, 0x57, 0x8c, 0xb7, 0xc7, 0x4e, 0x2a, 0xbd, + 0x72, 0xc5, 0xef, 0x2a, 0xd8, 0xb8, 0xf2, 0x9d, 0xbe, 0xd4, + 0xa7, 0x55, 0x3e, 0x06, 0x3b, 0x3f, 0xfa, 0x92, 0x4f, 0x1f, + 0x84, 0x84, 0x16, 0xcf, 0x9b, 0x26, 0x71, 0xf7, 0x57, 0x6a, + 0x6d, 0xdd, 0x34, 0x6b, 0x12, 0xc4, 0x70, 0x78, 0x59, 0x9b, + 0xf7, 0x45, 0xf4, 0xae, 0x30, 0xb0, 0x8c, 0x21, 0xb7, 0xb1, + 0x96, 0xda, 0x91, 0x0e, 0x57, 0x7e, 0x1b, 0xe2, 0xef, 0x82, + 0xd5, 0xa3, 0xd1, 0xeb, 0x47, 0x5c, 0x33, 0x91, 0xf8, 0x90, + 0xf9, 0x99, 0x0c, 0x69, 0x05, 0xee, 0xa1, 0x1a, 0x2d, 0x44, + 0x7e, 0x7c, 0x99 ) ); + +/** Signature generated with a non-signing certificate */ +SIGNATURE ( nonsigned_sig, + DATA ( 0x30, 0x82, 0x0c, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x0c, 0x03, 0x30, + 0x82, 0x0b, 0xff, 0x02, 0x01, 0x01, 0x31, 0x09, 0x30, 0x07, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x0a, 0xa9, 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, + 0x01, 0xe6, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, + 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, + 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, + 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, + 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, + 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, + 0x5a, 0x30, 0x81, 0x84, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, + 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, + 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, + 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, + 0x6f, 0x74, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, + 0x89, 0x02, 0x81, 0x81, 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, + 0xe0, 0x1d, 0x38, 0x41, 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, + 0xcb, 0x9c, 0x9c, 0x93, 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, + 0x39, 0xf6, 0x42, 0xe4, 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, + 0xba, 0x25, 0x58, 0xc8, 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, + 0x5b, 0xbc, 0x89, 0xca, 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, + 0x25, 0x67, 0x0a, 0x38, 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, + 0x02, 0x14, 0xd6, 0xf2, 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, + 0x4d, 0x47, 0xaf, 0x87, 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, + 0xf3, 0xb5, 0xd4, 0x15, 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, + 0x34, 0x8e, 0x50, 0x4b, 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, + 0x68, 0xdb, 0xa8, 0x17, 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, + 0xfc, 0xc3, 0x9b, 0x9d, 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, + 0x60, 0xef, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, + 0xf3, 0x68, 0xe3, 0x75, 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, + 0xea, 0xd1, 0x26, 0x33, 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, + 0x20, 0x84, 0x08, 0x78, 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, + 0x4d, 0x6c, 0xbb, 0xd5, 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, + 0x4d, 0x10, 0x16, 0x9f, 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, + 0x9d, 0x57, 0x71, 0x45, 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, + 0x03, 0x9c, 0x2b, 0x25, 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, + 0x14, 0xbf, 0xcf, 0xf0, 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, + 0xd2, 0xe9, 0xed, 0xbf, 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, + 0xeb, 0xf7, 0xa8, 0x26, 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, + 0x42, 0xd1, 0xf1, 0xfd, 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, + 0x67, 0xf0, 0x16, 0x3a, 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, + 0x18, 0x1f, 0x09, 0x8e, 0x4d, 0x30, 0x82, 0x02, 0xb3, 0x30, + 0x82, 0x02, 0x1c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, + 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x6f, + 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x90, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, + 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, + 0x65, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xc9, 0x3a, 0xee, 0xc6, 0x3c, 0xac, 0x4d, + 0x81, 0xc6, 0x98, 0x5e, 0xe1, 0x48, 0x66, 0x1a, 0x1e, 0x60, + 0x19, 0x41, 0xae, 0xca, 0x14, 0x97, 0xc8, 0x3a, 0x50, 0xb6, + 0x48, 0xf5, 0x42, 0xac, 0x0f, 0xe1, 0xe3, 0x47, 0xf0, 0xbf, + 0x7c, 0xd0, 0xee, 0x8f, 0xb7, 0xa6, 0x19, 0xad, 0xbb, 0xc5, + 0x1b, 0x34, 0x38, 0xc8, 0xbd, 0x55, 0x84, 0x93, 0x72, 0xaf, + 0x84, 0xfc, 0x9b, 0x97, 0x1d, 0xb5, 0x54, 0x24, 0xd6, 0x5d, + 0xb7, 0x31, 0xf4, 0xbd, 0x3b, 0x40, 0x97, 0xc0, 0xa9, 0x5a, + 0x2a, 0xcb, 0x6b, 0x98, 0x07, 0xdb, 0xb5, 0x9f, 0xe8, 0x31, + 0x3f, 0x01, 0x46, 0x46, 0x70, 0x05, 0xa2, 0x0f, 0x8c, 0x7a, + 0x61, 0xf3, 0xdf, 0xdb, 0xa1, 0x37, 0x2c, 0x88, 0x6a, 0x81, + 0x21, 0x12, 0x4c, 0xf5, 0xcd, 0xaf, 0xc9, 0xd2, 0x36, 0x3d, + 0x82, 0xd1, 0xca, 0x19, 0xaf, 0x4e, 0xae, 0x50, 0x71, 0x44, + 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x5d, 0x3c, 0xb3, 0x52, 0x19, 0xa6, 0x9e, 0x4a, + 0x44, 0x98, 0xbf, 0x51, 0x20, 0x47, 0x0a, 0xf3, 0x26, 0x1a, + 0xcc, 0x35, 0x2f, 0xc9, 0xed, 0xe0, 0x9d, 0x46, 0xeb, 0xbc, + 0x7e, 0xc9, 0xb9, 0x1d, 0x76, 0xa4, 0x1d, 0xc2, 0xd9, 0x16, + 0x29, 0x77, 0x01, 0x40, 0xdd, 0xe5, 0xcb, 0x28, 0x91, 0x3a, + 0x0c, 0x13, 0x01, 0x1b, 0x72, 0x62, 0x45, 0x27, 0xfd, 0xd7, + 0x00, 0x47, 0x36, 0x09, 0x1e, 0x7b, 0xd2, 0xcb, 0x95, 0x3d, + 0x28, 0x82, 0xce, 0x83, 0x59, 0x32, 0xf9, 0xe6, 0xec, 0x89, + 0xac, 0x88, 0x45, 0x22, 0x88, 0x6f, 0x5e, 0xa2, 0x79, 0x95, + 0xba, 0xb9, 0xc9, 0xb6, 0x4c, 0x7c, 0xb4, 0x29, 0xa1, 0x02, + 0xf5, 0xac, 0x5d, 0x8e, 0x52, 0xeb, 0xe8, 0xb1, 0x56, 0x49, + 0xb3, 0x77, 0x62, 0x7d, 0x87, 0x4d, 0x17, 0xf2, 0x62, 0x83, + 0x08, 0x59, 0x21, 0x60, 0x0d, 0x84, 0x8e, 0x5a, 0x84, 0xf6, + 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, + 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, + 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, + 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, + 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, + 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, + 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, + 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, + 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, + 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, + 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, + 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, + 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, + 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, + 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, + 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, + 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, + 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, + 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, + 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, + 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, + 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, + 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, + 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, + 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, + 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, + 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, + 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, + 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, + 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, + 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, + 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, + 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, + 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, + 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, + 0x10, 0xd4, 0x72, 0xd2, 0xb8, 0x30, 0x82, 0x02, 0xb6, 0x30, + 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, + 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x1e, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, + 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, + 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, + 0x17, 0x0d, 0x31, 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, + 0x30, 0x31, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, + 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, + 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, + 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, + 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, + 0x66, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xc3, 0x55, 0xad, 0xdf, 0x7b, 0xd1, 0x48, + 0xc3, 0xd3, 0x02, 0x54, 0x6c, 0x92, 0x45, 0x22, 0x3d, 0x90, + 0xd8, 0xc7, 0x13, 0xcd, 0xc1, 0x59, 0xc6, 0xe0, 0xad, 0x0e, + 0xe6, 0xdb, 0x3b, 0xe8, 0x63, 0xea, 0x4e, 0xb6, 0xea, 0x50, + 0xea, 0x6e, 0x33, 0x9d, 0x28, 0x25, 0x42, 0x49, 0xd0, 0xf0, + 0xed, 0xc5, 0x5b, 0x6b, 0x4a, 0xe7, 0x45, 0xfa, 0xd3, 0x3f, + 0xae, 0xde, 0x5a, 0x90, 0xab, 0xf1, 0x61, 0x2f, 0x40, 0x5e, + 0xcf, 0x8b, 0x0b, 0x10, 0x59, 0xa9, 0xd0, 0x1e, 0x0f, 0x18, + 0x6b, 0x92, 0xd8, 0x9f, 0x58, 0x10, 0x84, 0xb6, 0x15, 0xe8, + 0x5b, 0xc4, 0xa0, 0x3e, 0x49, 0x8b, 0xea, 0xdd, 0xa9, 0x7e, + 0x32, 0x26, 0x9a, 0x68, 0x44, 0xf0, 0x30, 0xca, 0x2a, 0xd6, + 0x19, 0x7a, 0x80, 0xfd, 0xd7, 0xfc, 0xc7, 0x5d, 0xe7, 0x61, + 0xd2, 0x3f, 0x1f, 0x2c, 0x40, 0x70, 0x7b, 0x34, 0xcb, 0x08, + 0xa9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x26, 0x30, 0x24, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, + 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x40, 0xd2, 0x70, 0x02, 0x08, + 0x19, 0xa0, 0xb8, 0x8d, 0x9d, 0x3d, 0x62, 0x41, 0x90, 0x2a, + 0x36, 0x4a, 0x8b, 0x21, 0x42, 0x9a, 0xb4, 0xc5, 0xf8, 0x79, + 0x17, 0xd7, 0x64, 0x4d, 0xbf, 0x8f, 0x6a, 0x04, 0x54, 0x7a, + 0x0b, 0xd4, 0xb5, 0x0e, 0xab, 0xf7, 0xb7, 0x06, 0x2b, 0xf8, + 0xde, 0x87, 0xb2, 0x37, 0x3b, 0x95, 0x01, 0xba, 0x9f, 0x8f, + 0xec, 0x0a, 0x86, 0xca, 0x51, 0xb6, 0x25, 0x73, 0x2f, 0xa1, + 0x66, 0xc8, 0x7a, 0x5e, 0x51, 0xbd, 0x49, 0xb5, 0x75, 0xda, + 0xea, 0xe5, 0xeb, 0x5d, 0xe3, 0xb0, 0xad, 0x49, 0x9f, 0x8b, + 0xfd, 0x89, 0xb3, 0xb7, 0xb2, 0x4c, 0x7d, 0x8a, 0x29, 0xb2, + 0xbe, 0x04, 0xef, 0x9c, 0x73, 0x3c, 0xea, 0xa3, 0x9f, 0x07, + 0x66, 0x5a, 0x2f, 0x38, 0xad, 0x1a, 0xeb, 0xe1, 0xb0, 0x62, + 0x14, 0x55, 0xdc, 0x8c, 0x83, 0xbb, 0xc7, 0x13, 0x04, 0x41, + 0x54, 0xf1, 0x45, 0x31, 0x82, 0x01, 0x33, 0x30, 0x82, 0x01, + 0x2f, 0x02, 0x01, 0x01, 0x30, 0x81, 0x8e, 0x30, 0x81, 0x88, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, + 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, + 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x02, 0x01, 0x03, 0x30, + 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, 0x33, 0x5c, 0xf8, 0xb4, + 0xa5, 0x70, 0xb9, 0x0f, 0x05, 0x50, 0x72, 0xdb, 0xa3, 0xba, + 0x8e, 0x0d, 0x6d, 0x8a, 0x2a, 0x91, 0x65, 0xb8, 0x76, 0xd0, + 0xfc, 0x9e, 0x1a, 0xdb, 0x2b, 0xd2, 0xfc, 0x03, 0xef, 0x8d, + 0xef, 0xfe, 0x32, 0x16, 0xad, 0xf8, 0xcb, 0x28, 0xb0, 0x61, + 0x15, 0xb8, 0x38, 0x72, 0xfc, 0x5d, 0xa1, 0xd2, 0xae, 0x9d, + 0x6a, 0xb0, 0x5e, 0xbb, 0x78, 0xd3, 0x39, 0x24, 0xa3, 0x71, + 0xa6, 0x90, 0x64, 0xa5, 0x82, 0xba, 0x3b, 0x85, 0x2d, 0x16, + 0x78, 0xf4, 0xcc, 0x9f, 0xfa, 0xc5, 0x68, 0x44, 0x2c, 0x22, + 0xb9, 0x4c, 0x07, 0x5c, 0xb4, 0x79, 0x1a, 0x48, 0xc2, 0x66, + 0x71, 0x57, 0x6d, 0xdf, 0x33, 0xa2, 0x26, 0x99, 0xdd, 0xe9, + 0xb9, 0x1b, 0xe1, 0xa6, 0x4d, 0x53, 0x8e, 0x71, 0x81, 0xa9, + 0x5d, 0x70, 0x47, 0x54, 0xbc, 0x15, 0xad, 0x9c, 0xe8, 0x90, + 0x52, 0x3e, 0x49, 0x86 ) ); + +/** iPXE self-test root CA certificate */ +static uint8_t root_crt_fingerprint[] = + FINGERPRINT ( 0x71, 0x5d, 0x51, 0x37, 0x5e, 0x18, 0xb3, 0xbc, + 0xbb, 0x30, 0x0e, 0x8f, 0x50, 0xc7, 0x55, 0xf5, + 0x96, 0xe7, 0xa8, 0x6d, 0x63, 0x2d, 0x32, 0x38, + 0xaf, 0x00, 0xc4, 0x1a, 0xfc, 0xd8, 0xac, 0xc3 ); + +/** Certificate store containing the iPXE self-test root CA */ +static struct x509_root test_root = { + .digest = &cms_test_algorithm, + .count = 1, + .fingerprints = root_crt_fingerprint, +}; + +/** Dummy fingerprint (not matching any certificates) */ +static uint8_t dummy_fingerprint[] = + FINGERPRINT ( 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff ); + +/** Certificate store containing a dummy fingerprint */ +static struct x509_root dummy_root = { + .digest = &cms_test_algorithm, + .count = 1, + .fingerprints = dummy_fingerprint, +}; + +/** Time at which all test certificates are valid */ +static time_t test_time = 1332374737ULL; /* Thu Mar 22 00:05:37 2012 */ + +/** Time at which end-entity test certificates are invalid */ +static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */ + +/** + * Report signature parsing test result + * + * @v sgn Test signature + */ +#define cms_signature_ok( sgn ) do { \ + ok ( cms_signature ( (sgn)->data, (sgn)->len, \ + &(sgn)->sig ) == 0 ); \ + } while ( 0 ) + +/** + * Report signature verification test result + * + * @v sgn Test signature + * @v code Test signed code + * @v name Test verification name + * @v time Test verification time + * @v root Test root certificate store + */ +#define cms_verify_ok( sgn, code, name, time, root ) do { \ + x509_invalidate_chain ( (sgn)->sig->certificates ); \ + ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \ + (code)->len, name, time, root ) == 0 ); \ + } while ( 0 ) + +/** + * Report signature verification failure test result + * + * @v sgn Test signature + * @v code Test signed code + * @v name Test verification name + * @v time Test verification time + * @v root Test root certificate store + */ +#define cms_verify_fail_ok( sgn, code, name, time, root ) do { \ + x509_invalidate_chain ( (sgn)->sig->certificates ); \ + ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \ + (code)->len, name, time, root ) != 0 ); \ + } while ( 0 ) + +/** + * Perform CMS self-tests + * + */ +static void cms_test_exec ( void ) { + + /* Check that all signatures can be parsed */ + cms_signature_ok ( &codesigned_sig ); + cms_signature_ok ( &brokenchain_sig ); + cms_signature_ok ( &genericsigned_sig ); + cms_signature_ok ( &nonsigned_sig ); + + /* Check good signature */ + cms_verify_ok ( &codesigned_sig, &test_code, + "codesign.test.ipxe.org", test_time, &test_root ); + cms_verify_ok ( &codesigned_sig, &test_code, + NULL, test_time, &test_root ); + + /* Check incorrect signer name */ + cms_verify_fail_ok ( &codesigned_sig, &test_code, + "wrongname.test.ipxe.org", test_time, &test_root ); + + /* Check non-code-signing certificate */ + cms_verify_fail_ok ( &genericsigned_sig, &test_code, + NULL, test_time, &test_root ); + + /* Check non-signing certificate */ + cms_verify_fail_ok ( &nonsigned_sig, &test_code, + NULL, test_time, &test_root ); + + /* Check broken chain */ + cms_verify_fail_ok ( &brokenchain_sig, &test_code, + NULL, test_time, &test_root ); + + /* Check untrusted signature */ + cms_verify_fail_ok ( &codesigned_sig, &test_code, + NULL, test_time, &dummy_root ); + + /* Check incorrect signed content */ + cms_verify_fail_ok ( &codesigned_sig, &bad_code, + NULL, test_time, &test_root ); + + /* Check expired signature */ + cms_verify_fail_ok ( &codesigned_sig, &test_code, + NULL, test_expired, &test_root ); + + /* Drop signature references */ + cms_put ( nonsigned_sig.sig ); + cms_put ( genericsigned_sig.sig ); + cms_put ( brokenchain_sig.sig ); + cms_put ( codesigned_sig.sig ); +} + +/** CMS self-test */ +struct self_test cms_test __self_test = { + .name = "cms", + .exec = cms_test_exec, +}; + +/* Drag in algorithms required for tests */ +REQUIRE_OBJECT ( rsa ); +REQUIRE_OBJECT ( md5 ); +REQUIRE_OBJECT ( sha1 ); +REQUIRE_OBJECT ( sha256 ); diff --git a/src/tests/crc32_test.c b/src/tests/crc32_test.c new file mode 100644 index 00000000..873f633a --- /dev/null +++ b/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/src/tests/entropy_sample.c b/src/tests/entropy_sample.c new file mode 100644 index 00000000..9e75b4e9 --- /dev/null +++ b/src/tests/entropy_sample.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Entropy sampling + * + */ + +#include <stdio.h> +#include <ipxe/entropy.h> +#include <ipxe/test.h> + +/** Total number of test samples */ +#define SAMPLE_COUNT 65536 + +/** Number of samples per block */ +#define SAMPLE_BLOCKSIZE 256 + +/** + * Generate entropy samples for external testing + * + */ +static void entropy_sample_test_exec ( void ) { + static noise_sample_t samples[SAMPLE_BLOCKSIZE]; + unsigned int i; + unsigned int j; + int rc; + + /* Collect and print blocks of samples */ + for ( i = 0 ; i < ( SAMPLE_COUNT / SAMPLE_BLOCKSIZE ) ; i++ ) { + + /* Collect one block of samples */ + rc = entropy_enable(); + ok ( rc == 0 ); + for ( j = 0 ; j < SAMPLE_BLOCKSIZE ; j++ ) { + rc = get_noise ( &samples[j] ); + ok ( rc == 0 ); + } + entropy_disable(); + + /* Print out sample values */ + for ( j = 0 ; j < SAMPLE_BLOCKSIZE ; j++ ) { + printf ( "SAMPLE %d %d\n", ( i * SAMPLE_BLOCKSIZE + j ), + samples[j] ); + } + } +} + +/** Entropy sampling self-test */ +struct self_test entropy_sample_test __self_test = { + .name = "entropy_sample", + .exec = entropy_sample_test_exec, +}; diff --git a/src/tests/hash_df_test.c b/src/tests/hash_df_test.c new file mode 100644 index 00000000..ccbc86ea --- /dev/null +++ b/src/tests/hash_df_test.c @@ -0,0 +1,897 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Hash-based derivation function (Hash_df) tests + * + * These test vectors are provided by NIST as part of the + * Cryptographic Toolkit Examples, downloadable from: + * + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/Hash_DRBG.pdf + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <assert.h> +#include <string.h> +#include <ipxe/hash_df.h> +#include <ipxe/sha1.h> +#include <ipxe/sha256.h> +#include <ipxe/test.h> + +/** Define inline input data */ +#define INPUT(...) { __VA_ARGS__ } + +/** Define inline expected data */ +#define EXPECT(...) { __VA_ARGS__ } + +/** A Hash_df test */ +struct hash_df_test { + /** Underlying hash algorithm */ + struct digest_algorithm *hash; + /** Input data */ + const void *input; + /** Length of input data */ + size_t input_len; + /** Expected output data */ + const void *expected; + /** Length of expected output data */ + size_t expected_len; +}; + +/** + * Define a Hash_df test + * + * @v name Test name + * @v hash_algorithm Underlying hash algorithm + * @v input_array Input data + * @v expected_array Expected output data + * @ret test Hash_df test + */ +#define HASH_DF_TEST( name, hash_algorithm, input_array, expected_array ) \ + static const uint8_t name ## _input [] = input_array; \ + static const uint8_t name ## _expected [] = expected_array; \ + static struct hash_df_test name = { \ + .hash = &(hash_algorithm), \ + .input = name ## _input, \ + .input_len = sizeof ( name ## _input ), \ + .expected = name ## _expected, \ + .expected_len = sizeof ( name ## _expected ), \ + } + +/** SHA-1 Test 1 */ +HASH_DF_TEST ( test_sha1_1, sha1_algorithm, + INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24 ), + EXPECT ( 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf, 0x6c, + 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc, 0xfd, + 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab, 0x28, + 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97, 0xab, + 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d, 0x94, + 0xbe, 0xe3, 0x3c, 0xbb, 0x89 ) ); + +/** SHA-1 Test 2 */ +HASH_DF_TEST ( test_sha1_2, sha1_algorithm, + INPUT ( 0x00, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf, + 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc, + 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab, + 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97, + 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d, + 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89 ), + EXPECT ( 0x54, 0xc5, 0x21, 0x7b, 0x51, 0x02, 0xd8, 0xda, 0x8b, 0xf1, + 0x68, 0x6e, 0xdb, 0xab, 0x2b, 0xbc, 0x0c, 0x11, 0xb0, 0xcc, + 0xb0, 0xf0, 0xaf, 0x23, 0x4c, 0x24, 0xcf, 0x15, 0xec, 0xc8, + 0xcb, 0x39, 0xc2, 0x33, 0xaa, 0xca, 0x48, 0xfc, 0xce, 0xee, + 0x86, 0x3d, 0xa8, 0x81, 0xff, 0xcb, 0xb4, 0x34, 0xa6, 0xcc, + 0xb7, 0xda, 0x2f, 0xb2, 0x10 ) ); + +/** SHA-1 Test 3 */ +HASH_DF_TEST ( test_sha1_3, sha1_algorithm, + INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, + 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76 ), + EXPECT ( 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23, 0x21, + 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85, 0x03, + 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3, 0xd0, + 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d, 0x58, + 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a, 0x93, + 0x32, 0x4b, 0x27, 0xbd, 0xe8 ) ); + +/** SHA-1 Test 4 */ +HASH_DF_TEST ( test_sha1_4, sha1_algorithm, + INPUT ( 0x00, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23, + 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85, + 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3, + 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d, + 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a, + 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8 ), + EXPECT ( 0xa7, 0x02, 0x66, 0xf7, 0xf9, 0x1e, 0xc4, 0xd2, 0x88, 0x73, + 0x14, 0x79, 0x34, 0xce, 0xaf, 0x2a, 0x2c, 0xc3, 0x5a, 0x0f, + 0xd5, 0xe0, 0x0a, 0xba, 0xe7, 0x9d, 0xc6, 0x60, 0x5f, 0xab, + 0xd6, 0xf5, 0xf9, 0x28, 0xe1, 0x8c, 0x63, 0x26, 0x8e, 0x1a, + 0xf4, 0x85, 0xda, 0x6c, 0xbf, 0x04, 0x16, 0xdc, 0xdc, 0x5f, + 0xb8, 0xbc, 0x9c, 0x94, 0xb6 ) ); + +/** SHA-1 Test 5 */ +HASH_DF_TEST ( test_sha1_5, sha1_algorithm, + INPUT ( 0x01, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf, + 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc, + 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab, + 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97, + 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d, + 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6 ), + EXPECT ( 0x0a, 0x04, 0x41, 0xa5, 0x2b, 0xed, 0xf7, 0x94, 0xf5, 0xaa, + 0x62, 0x7b, 0xcb, 0xd8, 0x1f, 0x93, 0xe0, 0x11, 0xd5, 0x1f, + 0x34, 0x74, 0x80, 0x2c, 0x37, 0x50, 0x76, 0x75, 0x51, 0xb4, + 0x5b, 0x69, 0xf3, 0xd3, 0x59, 0x39, 0xc9, 0x32, 0xae, 0x1c, + 0xb7, 0xc9, 0x89, 0x4f, 0xb8, 0x84, 0x65, 0xe0, 0xcf, 0xd1, + 0xcc, 0x26, 0x1e, 0x22, 0xc5 ) ); + +/** SHA-1 Test 6 */ +HASH_DF_TEST ( test_sha1_6, sha1_algorithm, + INPUT ( 0x00, 0x0a, 0x04, 0x41, 0xa5, 0x2b, 0xed, 0xf7, 0x94, 0xf5, + 0xaa, 0x62, 0x7b, 0xcb, 0xd8, 0x1f, 0x93, 0xe0, 0x11, 0xd5, + 0x1f, 0x34, 0x74, 0x80, 0x2c, 0x37, 0x50, 0x76, 0x75, 0x51, + 0xb4, 0x5b, 0x69, 0xf3, 0xd3, 0x59, 0x39, 0xc9, 0x32, 0xae, + 0x1c, 0xb7, 0xc9, 0x89, 0x4f, 0xb8, 0x84, 0x65, 0xe0, 0xcf, + 0xd1, 0xcc, 0x26, 0x1e, 0x22, 0xc5 ), + EXPECT ( 0x04, 0x11, 0xc8, 0xb0, 0xdb, 0xa7, 0x56, 0xe8, 0x84, 0x2b, + 0x3f, 0xb0, 0x2d, 0x2f, 0xeb, 0x7c, 0xee, 0xa5, 0x67, 0x42, + 0xee, 0x93, 0x79, 0xc9, 0x0e, 0x6d, 0x3b, 0x2f, 0x10, 0x10, + 0xd4, 0x0f, 0x4f, 0x4d, 0xca, 0xda, 0x61, 0xcf, 0xdf, 0xb4, + 0x8a, 0xf8, 0x47, 0xca, 0xcc, 0x4c, 0x92, 0xc6, 0x14, 0x44, + 0x85, 0xc2, 0x27, 0xca, 0x05 ) ); + +/** SHA-1 Test 7 */ +HASH_DF_TEST ( test_sha1_7, sha1_algorithm, + INPUT ( 0x01, 0x0e, 0x16, 0x0a, 0x56, 0x07, 0x95, 0x4e, 0x7d, 0x79, + 0xd5, 0xa2, 0x2b, 0xf9, 0x08, 0x0b, 0x10, 0xce, 0xb7, 0x3c, + 0x62, 0x23, 0x07, 0xf9, 0xf5, 0x45, 0xbd, 0xb1, 0xa4, 0x61, + 0xc5, 0x2f, 0x79, 0x43, 0x21, 0x24, 0x3a, 0xac, 0xe2, 0x3f, + 0x36, 0x3f, 0xef, 0xb3, 0x5d, 0xc5, 0xbe, 0xa7, 0xe7, 0x31, + 0x44, 0x14, 0xcf, 0x78, 0xb3, 0xf9, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6 ), + EXPECT ( 0xdc, 0x24, 0xdf, 0x10, 0x2f, 0xa9, 0xf9, 0x6c, 0xc1, 0xcf, + 0xf8, 0xc1, 0x16, 0xc7, 0x9d, 0x14, 0x97, 0xd7, 0xc2, 0x7b, + 0xba, 0x5b, 0xa8, 0x01, 0xe1, 0x56, 0x21, 0x93, 0x35, 0x3f, + 0x31, 0xe3, 0x22, 0x39, 0x57, 0x84, 0x69, 0xb8, 0x0f, 0x2f, + 0x51, 0x64, 0x54, 0x37, 0x28, 0x71, 0x7f, 0x17, 0x1f, 0xdb, + 0x02, 0xb2, 0xad, 0x57, 0x95 ) ); + +/** SHA-1 Test 8 */ +HASH_DF_TEST ( test_sha1_8, sha1_algorithm, + INPUT ( 0x00, 0xdc, 0x24, 0xdf, 0x10, 0x2f, 0xa9, 0xf9, 0x6c, 0xc1, + 0xcf, 0xf8, 0xc1, 0x16, 0xc7, 0x9d, 0x14, 0x97, 0xd7, 0xc2, + 0x7b, 0xba, 0x5b, 0xa8, 0x01, 0xe1, 0x56, 0x21, 0x93, 0x35, + 0x3f, 0x31, 0xe3, 0x22, 0x39, 0x57, 0x84, 0x69, 0xb8, 0x0f, + 0x2f, 0x51, 0x64, 0x54, 0x37, 0x28, 0x71, 0x7f, 0x17, 0x1f, + 0xdb, 0x02, 0xb2, 0xad, 0x57, 0x95 ), + EXPECT ( 0xff, 0xaf, 0x45, 0x66, 0x5b, 0x11, 0x0c, 0xa1, 0x33, 0x5a, + 0x3f, 0xce, 0x73, 0xa7, 0x98, 0x1d, 0x0f, 0xd5, 0xc8, 0xd9, + 0x03, 0xf6, 0x5f, 0xaa, 0x46, 0xa3, 0xd5, 0x97, 0xbf, 0x34, + 0xc4, 0xe0, 0xcc, 0x16, 0x75, 0x60, 0xab, 0x94, 0xec, 0x10, + 0xd6, 0x41, 0x5f, 0x37, 0x83, 0xb0, 0x15, 0x67, 0x89, 0x1b, + 0x57, 0x66, 0x2a, 0xbb, 0x39 ) ); + +/** SHA-1 Test 9 */ +HASH_DF_TEST ( test_sha1_9, sha1_algorithm, + INPUT ( 0x01, 0xd0, 0x8f, 0xb4, 0x41, 0xf2, 0xf4, 0xcb, 0x37, 0xcf, + 0x6c, 0x24, 0x20, 0xa8, 0x2c, 0x74, 0x27, 0xac, 0xf7, 0xfc, + 0xfd, 0x79, 0x90, 0x14, 0x38, 0x34, 0xa5, 0xc2, 0x56, 0xab, + 0x28, 0x39, 0x36, 0x6d, 0x96, 0x34, 0x8c, 0xfe, 0x8c, 0x97, + 0xab, 0x67, 0x67, 0xb0, 0x5e, 0x83, 0xa9, 0x80, 0x40, 0x6d, + 0x94, 0xbe, 0xe3, 0x3c, 0xbb, 0x89, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ), + EXPECT ( 0x8f, 0xde, 0xc9, 0xe6, 0x18, 0x96, 0x36, 0xf0, 0xa5, 0xce, + 0x53, 0xe8, 0x1c, 0x13, 0xac, 0x93, 0x84, 0xfa, 0xfb, 0xa0, + 0xee, 0x50, 0xc1, 0xe2, 0xc8, 0xa0, 0x99, 0xde, 0x41, 0xd8, + 0xcc, 0x7a, 0x31, 0x42, 0x9e, 0x8c, 0x8c, 0x88, 0x80, 0xe3, + 0xb4, 0x5d, 0x89, 0xdb, 0x61, 0x2c, 0xd9, 0xd2, 0x8a, 0x55, + 0xc0, 0xf0, 0xd1, 0xf8, 0xf9 ) ); + +/** SHA-1 Test 10 */ +HASH_DF_TEST ( test_sha1_10, sha1_algorithm, + INPUT ( 0x00, 0x8f, 0xde, 0xc9, 0xe6, 0x18, 0x96, 0x36, 0xf0, 0xa5, + 0xce, 0x53, 0xe8, 0x1c, 0x13, 0xac, 0x93, 0x84, 0xfa, 0xfb, + 0xa0, 0xee, 0x50, 0xc1, 0xe2, 0xc8, 0xa0, 0x99, 0xde, 0x41, + 0xd8, 0xcc, 0x7a, 0x31, 0x42, 0x9e, 0x8c, 0x8c, 0x88, 0x80, + 0xe3, 0xb4, 0x5d, 0x89, 0xdb, 0x61, 0x2c, 0xd9, 0xd2, 0x8a, + 0x55, 0xc0, 0xf0, 0xd1, 0xf8, 0xf9 ), + EXPECT ( 0x97, 0xd0, 0x76, 0x31, 0xb2, 0x2f, 0x7c, 0x95, 0x7f, 0x19, + 0xf8, 0x44, 0xf4, 0xdc, 0x2a, 0xfa, 0x6f, 0xf9, 0x7c, 0x35, + 0x66, 0x18, 0x98, 0x21, 0x69, 0x91, 0xd1, 0x5b, 0xda, 0x75, + 0xbb, 0xd0, 0x5e, 0xdf, 0x8a, 0x0f, 0xa8, 0x0c, 0xca, 0xb9, + 0x51, 0x95, 0xf4, 0x79, 0xcd, 0x76, 0x20, 0x22, 0x35, 0x10, + 0x2e, 0xf6, 0x27, 0x29, 0x19 ) ); + +/** SHA-1 Test 11 */ +HASH_DF_TEST ( test_sha1_11, sha1_algorithm, + INPUT ( 0x01, 0x27, 0xaf, 0x40, 0x17, 0xca, 0xc5, 0xb3, 0x86, 0x24, + 0xe8, 0x4c, 0x2d, 0x10, 0xef, 0xd7, 0x8d, 0xf4, 0xf4, 0x77, + 0xd6, 0x54, 0x69, 0x5a, 0x04, 0x32, 0x32, 0x6b, 0x3a, 0x1c, + 0x4e, 0x88, 0x4a, 0x90, 0x22, 0x28, 0xe8, 0x9e, 0xaa, 0x90, + 0x36, 0xcd, 0x2a, 0xf7, 0x05, 0x66, 0x81, 0x26, 0x23, 0x72, + 0xc7, 0x13, 0x71, 0xd4, 0x53, 0x3d, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ), + EXPECT ( 0x2c, 0x9c, 0x0d, 0x80, 0x03, 0xe3, 0x40, 0x23, 0xbe, 0x5b, + 0x63, 0xfd, 0xb9, 0xd2, 0x24, 0xb4, 0x25, 0x0c, 0xc8, 0x15, + 0x5b, 0xd1, 0xee, 0xd8, 0xe5, 0x5d, 0x91, 0x06, 0x2f, 0xdd, + 0x27, 0x64, 0xb8, 0xae, 0xa9, 0xc8, 0x2f, 0x84, 0x7e, 0x09, + 0xa3, 0xfe, 0xa1, 0xc7, 0x11, 0x7d, 0x6f, 0x7d, 0xd2, 0xef, + 0x77, 0x7d, 0x7c, 0xf3, 0xeb ) ); + +/** SHA-1 Test 12 */ +HASH_DF_TEST ( test_sha1_12, sha1_algorithm, + INPUT ( 0x00, 0x2c, 0x9c, 0x0d, 0x80, 0x03, 0xe3, 0x40, 0x23, 0xbe, + 0x5b, 0x63, 0xfd, 0xb9, 0xd2, 0x24, 0xb4, 0x25, 0x0c, 0xc8, + 0x15, 0x5b, 0xd1, 0xee, 0xd8, 0xe5, 0x5d, 0x91, 0x06, 0x2f, + 0xdd, 0x27, 0x64, 0xb8, 0xae, 0xa9, 0xc8, 0x2f, 0x84, 0x7e, + 0x09, 0xa3, 0xfe, 0xa1, 0xc7, 0x11, 0x7d, 0x6f, 0x7d, 0xd2, + 0xef, 0x77, 0x7d, 0x7c, 0xf3, 0xeb ), + EXPECT ( 0x7e, 0x8a, 0xa4, 0x93, 0x42, 0x72, 0xf2, 0xa2, 0x8b, 0xbf, + 0xd7, 0xaf, 0xcc, 0x88, 0xce, 0x1c, 0x80, 0x6a, 0x38, 0xea, + 0x7b, 0x89, 0x45, 0xc8, 0xd1, 0xb6, 0xf1, 0x75, 0x03, 0x78, + 0x54, 0x6a, 0xb1, 0xa2, 0x96, 0x00, 0xd6, 0x44, 0xec, 0x52, + 0x0e, 0x8b, 0xff, 0xf6, 0x0c, 0xb7, 0x7f, 0xa5, 0x4b, 0xb1, + 0x1a, 0x83, 0x31, 0xcb, 0x24 ) ); + +/** SHA-1 Test 13 */ +HASH_DF_TEST ( test_sha1_13, sha1_algorithm, + INPUT ( 0x01, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23, + 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85, + 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3, + 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d, + 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a, + 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6 ), + EXPECT ( 0xe5, 0x04, 0x3d, 0x1b, 0x95, 0x4b, 0x34, 0xba, 0x60, 0xd2, + 0x48, 0xe8, 0x83, 0xef, 0x49, 0x8c, 0x5c, 0x52, 0x36, 0xb8, + 0x26, 0x0e, 0x23, 0x8e, 0x02, 0xc8, 0xd4, 0xfc, 0x5f, 0xfe, + 0x90, 0xfa, 0x40, 0x13, 0x44, 0x70, 0x75, 0xbb, 0x54, 0x3e, + 0xf0, 0x0c, 0x3b, 0xda, 0x59, 0x6b, 0x10, 0x88, 0x61, 0xf0, + 0x6b, 0xf9, 0x1b, 0x45, 0xd6 ) ); + +/** SHA-1 Test 14 */ +HASH_DF_TEST ( test_sha1_14, sha1_algorithm, + INPUT ( 0x00, 0xe5, 0x04, 0x3d, 0x1b, 0x95, 0x4b, 0x34, 0xba, 0x60, + 0xd2, 0x48, 0xe8, 0x83, 0xef, 0x49, 0x8c, 0x5c, 0x52, 0x36, + 0xb8, 0x26, 0x0e, 0x23, 0x8e, 0x02, 0xc8, 0xd4, 0xfc, 0x5f, + 0xfe, 0x90, 0xfa, 0x40, 0x13, 0x44, 0x70, 0x75, 0xbb, 0x54, + 0x3e, 0xf0, 0x0c, 0x3b, 0xda, 0x59, 0x6b, 0x10, 0x88, 0x61, + 0xf0, 0x6b, 0xf9, 0x1b, 0x45, 0xd6 ), + EXPECT ( 0x1f, 0x3f, 0x63, 0x10, 0xed, 0x10, 0xfc, 0x9f, 0x93, 0x8c, + 0x43, 0x22, 0x61, 0xaf, 0x42, 0xe9, 0xe9, 0x17, 0x5f, 0x08, + 0x0f, 0x32, 0x22, 0xdc, 0x11, 0x8b, 0xa7, 0xcf, 0x88, 0x8c, + 0xdc, 0x3f, 0x36, 0x0d, 0xd2, 0x8f, 0x5e, 0xcb, 0x7c, 0x80, + 0xa6, 0xbc, 0xfc, 0xfc, 0x0f, 0x51, 0xfe, 0x2f, 0x77, 0xc1, + 0xc9, 0x9d, 0xf0, 0xa2, 0x09 ) ); + +/** SHA-1 Test 15 */ +HASH_DF_TEST ( test_sha1_15, sha1_algorithm, + INPUT ( 0x01, 0x04, 0x43, 0xa0, 0x2c, 0x82, 0x5c, 0x31, 0x59, 0xf4, + 0x5e, 0x8c, 0x0a, 0xe5, 0x9e, 0x8c, 0x76, 0x45, 0x69, 0x95, + 0xc0, 0x35, 0x40, 0x46, 0x6a, 0x14, 0x54, 0x7c, 0xcb, 0xe8, + 0x8b, 0x6d, 0x39, 0x76, 0x21, 0x17, 0x32, 0x84, 0x72, 0xf5, + 0x2b, 0x84, 0x57, 0x5a, 0xaf, 0xe8, 0x8b, 0x2d, 0x1e, 0x50, + 0x4f, 0x21, 0xec, 0x4e, 0x31, 0x35, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6 ), + EXPECT ( 0x9d, 0xc3, 0x52, 0x08, 0xee, 0x2b, 0x8c, 0x58, 0x1e, 0xa3, + 0x0b, 0xaa, 0xcb, 0x5d, 0x74, 0x31, 0x7a, 0x87, 0x94, 0x54, + 0x10, 0x71, 0x7e, 0x58, 0xd3, 0x70, 0x5f, 0xbd, 0xc7, 0x60, + 0xbe, 0x0c, 0xc9, 0x0e, 0xd1, 0xcc, 0xbb, 0x89, 0x7d, 0x47, + 0xd2, 0x7e, 0x2b, 0x2e, 0x42, 0x2b, 0x32, 0xb9, 0x7f, 0x05, + 0x0d, 0x1b, 0xd2, 0xb4, 0x90 ) ); + +/** SHA-1 Test 16 */ +HASH_DF_TEST ( test_sha1_16, sha1_algorithm, + INPUT ( 0x00, 0x9d, 0xc3, 0x52, 0x08, 0xee, 0x2b, 0x8c, 0x58, 0x1e, + 0xa3, 0x0b, 0xaa, 0xcb, 0x5d, 0x74, 0x31, 0x7a, 0x87, 0x94, + 0x54, 0x10, 0x71, 0x7e, 0x58, 0xd3, 0x70, 0x5f, 0xbd, 0xc7, + 0x60, 0xbe, 0x0c, 0xc9, 0x0e, 0xd1, 0xcc, 0xbb, 0x89, 0x7d, + 0x47, 0xd2, 0x7e, 0x2b, 0x2e, 0x42, 0x2b, 0x32, 0xb9, 0x7f, + 0x05, 0x0d, 0x1b, 0xd2, 0xb4, 0x90 ), + EXPECT ( 0x1a, 0x5a, 0xd6, 0xce, 0xa3, 0xd1, 0x5d, 0xa5, 0xfb, 0x47, + 0x42, 0x13, 0x13, 0x09, 0xf0, 0xed, 0x88, 0xcf, 0x4c, 0x90, + 0xa6, 0xc1, 0xcc, 0xee, 0x35, 0xa8, 0x76, 0xeb, 0xfc, 0xcc, + 0x82, 0x67, 0x29, 0xb6, 0x63, 0x9f, 0x81, 0x19, 0x65, 0xb0, + 0xef, 0x85, 0x76, 0xe7, 0x5c, 0xb3, 0xcf, 0xe8, 0x22, 0x07, + 0x68, 0xb2, 0x6c, 0xe7, 0x7a ) ); + +/** SHA-1 Test 17 */ +HASH_DF_TEST ( test_sha1_17, sha1_algorithm, + INPUT ( 0x01, 0x99, 0xb9, 0x53, 0x7b, 0x84, 0x27, 0xb8, 0xce, 0x23, + 0x21, 0x9a, 0x61, 0x1c, 0xbe, 0x61, 0x06, 0x44, 0xcf, 0x85, + 0x03, 0xee, 0xc5, 0xba, 0x22, 0xde, 0x1a, 0xb2, 0x12, 0xc3, + 0xd0, 0x85, 0x8e, 0x9e, 0x3b, 0x90, 0x26, 0xd4, 0xe7, 0x7d, + 0x58, 0xe0, 0x2e, 0x85, 0xa2, 0x31, 0x4c, 0xe3, 0xd7, 0x4a, + 0x93, 0x32, 0x4b, 0x27, 0xbd, 0xe8, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ), + EXPECT ( 0x56, 0x3a, 0x5d, 0x20, 0x7d, 0x37, 0x70, 0x7b, 0xf5, 0xf2, + 0x4d, 0x0b, 0xd4, 0x93, 0x5d, 0xc3, 0x8d, 0xbe, 0x04, 0x36, + 0x37, 0xb3, 0xff, 0x8a, 0xb6, 0x8c, 0xfc, 0xe2, 0xf2, 0x90, + 0xd1, 0x69, 0x95, 0x20, 0x55, 0x24, 0x19, 0x0f, 0xd2, 0x91, + 0xaa, 0x8a, 0x6e, 0x6b, 0x8e, 0x6d, 0x56, 0xa4, 0x31, 0x33, + 0x3b, 0x40, 0x8e, 0x6f, 0xa8 ) ); + +/** SHA-1 Test 18 */ +HASH_DF_TEST ( test_sha1_18, sha1_algorithm, + INPUT ( 0x00, 0x56, 0x3a, 0x5d, 0x20, 0x7d, 0x37, 0x70, 0x7b, 0xf5, + 0xf2, 0x4d, 0x0b, 0xd4, 0x93, 0x5d, 0xc3, 0x8d, 0xbe, 0x04, + 0x36, 0x37, 0xb3, 0xff, 0x8a, 0xb6, 0x8c, 0xfc, 0xe2, 0xf2, + 0x90, 0xd1, 0x69, 0x95, 0x20, 0x55, 0x24, 0x19, 0x0f, 0xd2, + 0x91, 0xaa, 0x8a, 0x6e, 0x6b, 0x8e, 0x6d, 0x56, 0xa4, 0x31, + 0x33, 0x3b, 0x40, 0x8e, 0x6f, 0xa8 ), + EXPECT ( 0xc5, 0xd3, 0xe9, 0x55, 0x1e, 0x00, 0xe4, 0xee, 0x32, 0xb2, + 0x11, 0x6f, 0xaf, 0x4d, 0xef, 0xf4, 0xd4, 0xcf, 0xad, 0x2b, + 0xdc, 0x2d, 0xba, 0xa2, 0xe0, 0xe7, 0xf9, 0xdd, 0xb9, 0xd8, + 0x1e, 0xed, 0x45, 0xe0, 0xa5, 0x0d, 0xa5, 0xaf, 0xd5, 0xc1, + 0xf6, 0xbc, 0xda, 0xf8, 0x1d, 0x28, 0x9c, 0xf4, 0xbd, 0x3c, + 0x91, 0xb7, 0x00, 0x5c, 0x18 ) ); + +/** SHA-1 Test 19 */ +HASH_DF_TEST ( test_sha1_19, sha1_algorithm, + INPUT ( 0x01, 0x1c, 0x0e, 0x46, 0x75, 0x9b, 0x38, 0x55, 0x6a, 0x28, + 0xa4, 0x5e, 0x7b, 0x83, 0xe1, 0x4d, 0xb8, 0x62, 0x8d, 0xb1, + 0x62, 0x13, 0xe1, 0xba, 0x2d, 0x97, 0x74, 0xf6, 0xc0, 0xac, + 0x68, 0xf0, 0x56, 0xdb, 0x00, 0xfb, 0x12, 0xe1, 0x5b, 0xf4, + 0xde, 0x95, 0x50, 0xb7, 0x33, 0x1e, 0x2d, 0xbd, 0x66, 0x4c, + 0x3a, 0xb7, 0x76, 0xe8, 0x25, 0x51, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ), + EXPECT ( 0x60, 0x01, 0x93, 0xc8, 0xf6, 0x03, 0x1a, 0x2d, 0x49, 0x37, + 0x2a, 0x8b, 0x0f, 0x60, 0xf6, 0x8c, 0x1d, 0xfd, 0xac, 0xd4, + 0xf8, 0xea, 0x01, 0x37, 0x47, 0xd7, 0x14, 0x82, 0x33, 0x3d, + 0xf5, 0x25, 0x2e, 0x95, 0xb8, 0x22, 0x57, 0x39, 0x1b, 0xf1, + 0x0a, 0xb0, 0x7d, 0x12, 0x08, 0xb6, 0xbd, 0x66, 0x5b, 0x30, + 0x0a, 0xa4, 0xdb, 0x9c, 0x3e ) ); + +/** SHA-1 Test 20 */ +HASH_DF_TEST ( test_sha1_20, sha1_algorithm, + INPUT ( 0x00, 0x60, 0x01, 0x93, 0xc8, 0xf6, 0x03, 0x1a, 0x2d, 0x49, + 0x37, 0x2a, 0x8b, 0x0f, 0x60, 0xf6, 0x8c, 0x1d, 0xfd, 0xac, + 0xd4, 0xf8, 0xea, 0x01, 0x37, 0x47, 0xd7, 0x14, 0x82, 0x33, + 0x3d, 0xf5, 0x25, 0x2e, 0x95, 0xb8, 0x22, 0x57, 0x39, 0x1b, + 0xf1, 0x0a, 0xb0, 0x7d, 0x12, 0x08, 0xb6, 0xbd, 0x66, 0x5b, + 0x30, 0x0a, 0xa4, 0xdb, 0x9c, 0x3e ), + EXPECT ( 0x6b, 0x71, 0x82, 0x3b, 0x18, 0x20, 0x07, 0x71, 0xca, 0xae, + 0x5d, 0x12, 0x55, 0xc1, 0x40, 0x3e, 0xdf, 0xe3, 0x8b, 0x4d, + 0x18, 0xc7, 0x87, 0xbb, 0x44, 0xcd, 0x17, 0x18, 0x61, 0x52, + 0xef, 0xea, 0xd6, 0xfd, 0xc4, 0xb8, 0x94, 0xf9, 0x20, 0x02, + 0xc0, 0x72, 0x09, 0x55, 0x5d, 0x7e, 0x35, 0x54, 0xf9, 0xd1, + 0x2f, 0xc5, 0x59, 0x7f, 0x22 ) ); + +/** SHA-256 Test 1 */ +HASH_DF_TEST ( test_sha256_1, sha256_algorithm, + INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27 ), + EXPECT ( 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c, 0xa7, + 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd, 0x46, + 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b, 0xcd, + 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c, 0x0d, + 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d, 0xf4, + 0x04, 0x48, 0xd2, 0xd8, 0xe1 ) ); + +/** SHA-256 Test 2 */ +HASH_DF_TEST ( test_sha256_2, sha256_algorithm, + INPUT ( 0x00, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c, + 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd, + 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b, + 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c, + 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d, + 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1 ), + EXPECT ( 0xe1, 0x5d, 0xe4, 0xa8, 0xe3, 0xb1, 0x41, 0x9b, 0x61, 0xd5, + 0x34, 0xf1, 0x5d, 0xbd, 0x31, 0xee, 0x19, 0xec, 0x59, 0x5f, + 0x8b, 0x98, 0x11, 0x1a, 0x94, 0xf5, 0x22, 0x37, 0xad, 0x5d, + 0x66, 0xf0, 0xcf, 0xaa, 0xfd, 0xdc, 0x90, 0x19, 0x59, 0x02, + 0xe9, 0x79, 0xf7, 0x9b, 0x65, 0x35, 0x7f, 0xea, 0x85, 0x99, + 0x8e, 0x4e, 0x37, 0xd2, 0xc1 ) ); + +/** SHA-256 Test 3 */ +HASH_DF_TEST ( test_sha256_3, sha256_algorithm, + INPUT ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76 ), + EXPECT ( 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3, 0x03, + 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62, 0xd1, + 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32, 0xf7, + 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee, 0xc8, + 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7, 0x99, + 0x29, 0x90, 0x94, 0xa1, 0xca ) ); + +/** SHA-256 Test 4 */ +HASH_DF_TEST ( test_sha256_4, sha256_algorithm, + INPUT ( 0x00, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3, + 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62, + 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32, + 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee, + 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7, + 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca ), + EXPECT ( 0x44, 0x74, 0x8a, 0x78, 0xb1, 0x6e, 0x75, 0x55, 0x9f, 0x88, + 0x1d, 0x51, 0xc1, 0x5d, 0xfe, 0x6c, 0x52, 0xcf, 0xb0, 0xbb, + 0x71, 0x62, 0x01, 0x69, 0xc7, 0x93, 0x34, 0x27, 0x67, 0xe7, + 0xf8, 0x87, 0x5f, 0x42, 0xcb, 0x6a, 0x20, 0xc8, 0x9d, 0x7c, + 0x6e, 0xf3, 0xdc, 0x61, 0x0d, 0x8f, 0xf2, 0x03, 0xd6, 0x76, + 0x6c, 0xed, 0x19, 0x19, 0xd0 ) ); + +/** SHA-256 Test 5 */ +HASH_DF_TEST ( test_sha256_5, sha256_algorithm, + INPUT ( 0x01, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c, + 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd, + 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b, + 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c, + 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d, + 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6 ), + EXPECT ( 0x3c, 0x40, 0xe8, 0xdc, 0x71, 0x72, 0xfd, 0xa2, 0x32, 0x55, + 0x0a, 0x1d, 0x8e, 0x14, 0x47, 0xc1, 0x1f, 0x47, 0x48, 0x88, + 0xf9, 0x6c, 0xd8, 0x5c, 0x38, 0x63, 0xd5, 0xe4, 0x84, 0x26, + 0x67, 0x56, 0x28, 0xd0, 0x88, 0x85, 0x34, 0x7c, 0x3e, 0xfd, + 0x62, 0x92, 0xfd, 0xdc, 0xd1, 0xa1, 0x42, 0x1e, 0xed, 0x51, + 0xb7, 0x13, 0xab, 0x09, 0x0f ) ); + +/** SHA-256 Test 6 */ +HASH_DF_TEST ( test_sha256_6, sha256_algorithm, + INPUT ( 0x00, 0x3c, 0x40, 0xe8, 0xdc, 0x71, 0x72, 0xfd, 0xa2, 0x32, + 0x55, 0x0a, 0x1d, 0x8e, 0x14, 0x47, 0xc1, 0x1f, 0x47, 0x48, + 0x88, 0xf9, 0x6c, 0xd8, 0x5c, 0x38, 0x63, 0xd5, 0xe4, 0x84, + 0x26, 0x67, 0x56, 0x28, 0xd0, 0x88, 0x85, 0x34, 0x7c, 0x3e, + 0xfd, 0x62, 0x92, 0xfd, 0xdc, 0xd1, 0xa1, 0x42, 0x1e, 0xed, + 0x51, 0xb7, 0x13, 0xab, 0x09, 0x0f ), + EXPECT ( 0xe7, 0x56, 0x83, 0x84, 0xf2, 0x64, 0xe4, 0xa7, 0xe7, 0xae, + 0x85, 0x0d, 0x9d, 0x50, 0x1f, 0xd6, 0x31, 0x83, 0x56, 0x4f, + 0xd7, 0xd3, 0x90, 0x44, 0x6f, 0x5b, 0xe5, 0xf6, 0x7b, 0x50, + 0x19, 0x5b, 0x52, 0x84, 0x69, 0x2a, 0xd4, 0xb7, 0x6d, 0xfd, + 0x4f, 0x52, 0x4b, 0xcf, 0xcc, 0xab, 0x62, 0xc1, 0x30, 0x9f, + 0x25, 0x15, 0x17, 0xdf, 0xfd ) ); + +/** SHA-256 Test 7 */ +HASH_DF_TEST ( test_sha256_7, sha256_algorithm, + INPUT ( 0x01, 0x23, 0x97, 0x6c, 0x61, 0x63, 0xd7, 0xe2, 0x4a, 0x1a, + 0x03, 0x8f, 0x2b, 0x2b, 0x64, 0x67, 0x97, 0x50, 0xca, 0x9e, + 0xd8, 0xd1, 0x40, 0x69, 0x8d, 0x64, 0x22, 0x39, 0x7b, 0x02, + 0x96, 0x9e, 0x6e, 0xcd, 0xd2, 0x9d, 0xac, 0xc5, 0x76, 0x7e, + 0x2c, 0xc2, 0xd0, 0xa1, 0x56, 0xc8, 0x7a, 0xd0, 0xb3, 0x57, + 0x89, 0x05, 0x07, 0xe0, 0x37, 0x77, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6 ), + EXPECT ( 0xe9, 0x83, 0xb1, 0x66, 0xa9, 0x2a, 0x99, 0x7e, 0xab, 0xcc, + 0x96, 0x6c, 0x6a, 0xa3, 0xd3, 0xb3, 0xa1, 0x68, 0x1f, 0xc5, + 0x8f, 0x58, 0x29, 0x40, 0x3b, 0x48, 0x60, 0x1e, 0xc1, 0x77, + 0x54, 0x94, 0x2e, 0x11, 0xc1, 0xcd, 0x46, 0x5b, 0x7d, 0xbe, + 0x2a, 0x78, 0xca, 0x04, 0x2c, 0xf9, 0xb3, 0x05, 0x71, 0xff, + 0x12, 0xe3, 0xb9, 0xf6, 0xc9 ) ); + +/** SHA-256 Test 8 */ +HASH_DF_TEST ( test_sha256_8, sha256_algorithm, + INPUT ( 0x00, 0xe9, 0x83, 0xb1, 0x66, 0xa9, 0x2a, 0x99, 0x7e, 0xab, + 0xcc, 0x96, 0x6c, 0x6a, 0xa3, 0xd3, 0xb3, 0xa1, 0x68, 0x1f, + 0xc5, 0x8f, 0x58, 0x29, 0x40, 0x3b, 0x48, 0x60, 0x1e, 0xc1, + 0x77, 0x54, 0x94, 0x2e, 0x11, 0xc1, 0xcd, 0x46, 0x5b, 0x7d, + 0xbe, 0x2a, 0x78, 0xca, 0x04, 0x2c, 0xf9, 0xb3, 0x05, 0x71, + 0xff, 0x12, 0xe3, 0xb9, 0xf6, 0xc9 ), + EXPECT ( 0xa9, 0x77, 0x5c, 0xe1, 0x65, 0x5b, 0xff, 0x95, 0x1b, 0xe0, + 0xaf, 0x5b, 0x79, 0x59, 0x72, 0x5c, 0x76, 0x7d, 0x86, 0xf1, + 0xe1, 0x9b, 0x11, 0xb8, 0x90, 0x04, 0xf6, 0x97, 0x4d, 0xbf, + 0xa0, 0x46, 0x04, 0x45, 0x8e, 0x5c, 0x52, 0x8e, 0x7e, 0x1d, + 0xfa, 0xb3, 0x88, 0x7b, 0xa4, 0xaa, 0xdb, 0xd6, 0xfb, 0xde, + 0x0b, 0x31, 0x6f, 0x1d, 0x91 ) ); + +/** SHA-256 Test 9 */ +HASH_DF_TEST ( test_sha256_9, sha256_algorithm, + INPUT ( 0x01, 0xab, 0x41, 0xcd, 0xe4, 0x37, 0xab, 0x8b, 0x09, 0x1c, + 0xa7, 0xc5, 0x75, 0x5d, 0x10, 0xf0, 0x11, 0x0c, 0x1d, 0xbd, + 0x46, 0x2f, 0x22, 0x6c, 0xfd, 0xab, 0xfb, 0xb0, 0x4a, 0x8b, + 0xcd, 0xef, 0x95, 0x16, 0x7d, 0x84, 0xaf, 0x64, 0x12, 0x8c, + 0x0d, 0x71, 0xf4, 0xd5, 0xb8, 0xc0, 0xed, 0xfb, 0xbe, 0x3d, + 0xf4, 0x04, 0x48, 0xd2, 0xd8, 0xe1, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ), + EXPECT ( 0x57, 0xb2, 0xcf, 0x00, 0xb5, 0x42, 0x97, 0x46, 0x0b, 0x08, + 0x7e, 0x52, 0x75, 0xd7, 0xdd, 0x74, 0x23, 0xb6, 0xe3, 0xb6, + 0x5e, 0x35, 0x16, 0xd2, 0x48, 0x11, 0x99, 0xa0, 0x17, 0xb5, + 0x3a, 0x22, 0x20, 0x33, 0xfe, 0x68, 0xa6, 0x0b, 0xd0, 0xbd, + 0x70, 0x40, 0x26, 0xcd, 0x5a, 0x3e, 0x79, 0x55, 0xdb, 0x01, + 0xdc, 0xb2, 0x84, 0x48, 0xd1 ) ); + +/** SHA-256 Test 10 */ +HASH_DF_TEST ( test_sha256_10, sha256_algorithm, + INPUT ( 0x00, 0x57, 0xb2, 0xcf, 0x00, 0xb5, 0x42, 0x97, 0x46, 0x0b, + 0x08, 0x7e, 0x52, 0x75, 0xd7, 0xdd, 0x74, 0x23, 0xb6, 0xe3, + 0xb6, 0x5e, 0x35, 0x16, 0xd2, 0x48, 0x11, 0x99, 0xa0, 0x17, + 0xb5, 0x3a, 0x22, 0x20, 0x33, 0xfe, 0x68, 0xa6, 0x0b, 0xd0, + 0xbd, 0x70, 0x40, 0x26, 0xcd, 0x5a, 0x3e, 0x79, 0x55, 0xdb, + 0x01, 0xdc, 0xb2, 0x84, 0x48, 0xd1 ), + EXPECT ( 0x5b, 0xc1, 0xc6, 0x45, 0xcc, 0x8d, 0x32, 0x15, 0x82, 0xaf, + 0xbb, 0x00, 0x16, 0x99, 0x2b, 0x0f, 0x3a, 0xfe, 0x0f, 0x54, + 0x7a, 0xe7, 0xa7, 0x4c, 0x9c, 0x05, 0xa1, 0x44, 0x02, 0xfb, + 0xb1, 0xd5, 0x40, 0xe6, 0x80, 0x9d, 0x8b, 0xee, 0xf5, 0x99, + 0xed, 0x4c, 0x39, 0x16, 0x47, 0x40, 0xed, 0xa0, 0xd9, 0xc3, + 0x79, 0x5d, 0xe5, 0x52, 0xc5 ) ); + +/** SHA-256 Test 11 */ +HASH_DF_TEST ( test_sha256_11, sha256_algorithm, + INPUT ( 0x01, 0xb3, 0x74, 0x95, 0x46, 0x81, 0xcf, 0xc9, 0x5b, 0x8d, + 0xb8, 0x39, 0x52, 0x8c, 0x71, 0x08, 0x83, 0x5e, 0xb4, 0xf3, + 0x0a, 0xd9, 0x1c, 0xbe, 0x9e, 0xa0, 0xd5, 0x45, 0xcc, 0xfd, + 0x18, 0x13, 0x2a, 0xf1, 0xd3, 0x76, 0x8f, 0x47, 0x02, 0x77, + 0x2b, 0x69, 0x15, 0x9f, 0x2c, 0xc0, 0x7f, 0x48, 0x74, 0x1e, + 0xb5, 0xb2, 0xb1, 0x22, 0x11, 0x25, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ), + EXPECT ( 0x5d, 0xc1, 0xc5, 0xf4, 0xb4, 0x11, 0x50, 0xce, 0xe0, 0xef, + 0xc1, 0x29, 0xb8, 0x37, 0xb3, 0x1c, 0x84, 0xd7, 0x91, 0xff, + 0x2e, 0x7e, 0xda, 0xc2, 0x9c, 0x2c, 0x50, 0xcf, 0x8a, 0x40, + 0x70, 0x9b, 0x98, 0x64, 0x0f, 0x7b, 0xbd, 0x32, 0xbc, 0xf0, + 0xfc, 0xb6, 0x13, 0xf9, 0x6d, 0x55, 0xd1, 0x60, 0x56, 0xbb, + 0x3c, 0xa6, 0xa7, 0x74, 0x05 ) ); + +/** SHA-256 Test 12 */ +HASH_DF_TEST ( test_sha256_12, sha256_algorithm, + INPUT ( 0x00, 0x5d, 0xc1, 0xc5, 0xf4, 0xb4, 0x11, 0x50, 0xce, 0xe0, + 0xef, 0xc1, 0x29, 0xb8, 0x37, 0xb3, 0x1c, 0x84, 0xd7, 0x91, + 0xff, 0x2e, 0x7e, 0xda, 0xc2, 0x9c, 0x2c, 0x50, 0xcf, 0x8a, + 0x40, 0x70, 0x9b, 0x98, 0x64, 0x0f, 0x7b, 0xbd, 0x32, 0xbc, + 0xf0, 0xfc, 0xb6, 0x13, 0xf9, 0x6d, 0x55, 0xd1, 0x60, 0x56, + 0xbb, 0x3c, 0xa6, 0xa7, 0x74, 0x05 ), + EXPECT ( 0x62, 0x22, 0x10, 0x8c, 0xed, 0xfe, 0x6d, 0x6a, 0x22, 0x9f, + 0x8c, 0x3c, 0xbf, 0x44, 0x68, 0xc8, 0xf5, 0x17, 0x22, 0x86, + 0x4c, 0xc4, 0x16, 0xa4, 0x29, 0x26, 0xd9, 0x9b, 0xa6, 0xf0, + 0x45, 0xc1, 0xf6, 0x21, 0x11, 0x56, 0x94, 0x6c, 0x6e, 0x79, + 0x37, 0x29, 0x97, 0x4e, 0xb4, 0xc5, 0xa6, 0x07, 0x8f, 0x9a, + 0x1d, 0x4d, 0x1c, 0xd7, 0x49 ) ); + +/** SHA-256 Test 13 */ +HASH_DF_TEST ( test_sha256_13, sha256_algorithm, + INPUT ( 0x01, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3, + 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62, + 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32, + 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee, + 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7, + 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6 ), + EXPECT ( 0xe0, 0x26, 0xa5, 0xc2, 0xe7, 0x62, 0x3e, 0x62, 0xb7, 0x1a, + 0x2e, 0x04, 0xc2, 0x5f, 0x0b, 0x08, 0x58, 0x2b, 0xe2, 0x16, + 0x36, 0x34, 0xc0, 0x49, 0x6d, 0x2b, 0x65, 0xda, 0x7e, 0xaa, + 0x03, 0xb5, 0xc3, 0xb6, 0xb5, 0x10, 0xbb, 0x3f, 0xe4, 0x74, + 0x34, 0x07, 0x1f, 0x70, 0x7a, 0xc7, 0xfe, 0x4c, 0x39, 0x6a, + 0xaa, 0xee, 0x76, 0x4c, 0x90 ) ); + +/** SHA-256 Test 14 */ +HASH_DF_TEST ( test_sha256_14, sha256_algorithm, + INPUT ( 0x00, 0xe0, 0x26, 0xa5, 0xc2, 0xe7, 0x62, 0x3e, 0x62, 0xb7, + 0x1a, 0x2e, 0x04, 0xc2, 0x5f, 0x0b, 0x08, 0x58, 0x2b, 0xe2, + 0x16, 0x36, 0x34, 0xc0, 0x49, 0x6d, 0x2b, 0x65, 0xda, 0x7e, + 0xaa, 0x03, 0xb5, 0xc3, 0xb6, 0xb5, 0x10, 0xbb, 0x3f, 0xe4, + 0x74, 0x34, 0x07, 0x1f, 0x70, 0x7a, 0xc7, 0xfe, 0x4c, 0x39, + 0x6a, 0xaa, 0xee, 0x76, 0x4c, 0x90 ), + EXPECT ( 0xc9, 0xea, 0x75, 0x4b, 0xee, 0x0a, 0xb6, 0x44, 0x15, 0xca, + 0x7f, 0xe3, 0x2e, 0xbb, 0xfb, 0x07, 0xed, 0x93, 0x2e, 0x7c, + 0x95, 0x7e, 0xce, 0xae, 0xf0, 0xcd, 0x2f, 0xa7, 0x7a, 0x46, + 0xf9, 0xe8, 0x59, 0x62, 0x78, 0x97, 0x54, 0xc6, 0xd2, 0x98, + 0xf9, 0xb5, 0xe4, 0x59, 0x6b, 0x4e, 0x0e, 0x6d, 0xf4, 0xf4, + 0xb8, 0x23, 0x60, 0xda, 0x33 ) ); + +/** SHA-256 Test 15 */ +HASH_DF_TEST ( test_sha256_15, sha256_algorithm, + INPUT ( 0x01, 0xaa, 0x11, 0x1b, 0x0e, 0xd5, 0x6c, 0xf4, 0xa6, 0xcc, + 0xe4, 0xad, 0xe7, 0xf1, 0x1b, 0x06, 0x10, 0x45, 0xbf, 0x10, + 0x92, 0xcb, 0xb3, 0x8f, 0xf3, 0x23, 0x95, 0xea, 0x62, 0xd2, + 0x6b, 0x27, 0xc8, 0x86, 0x89, 0x45, 0xc5, 0x93, 0xba, 0x70, + 0xc3, 0x84, 0xad, 0xad, 0x45, 0x77, 0x1c, 0x93, 0xb0, 0x9c, + 0x27, 0x69, 0x07, 0x52, 0xd1, 0xd8, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6 ), + EXPECT ( 0xfc, 0x5f, 0x56, 0x48, 0xed, 0xc4, 0xfc, 0x30, 0x7b, 0x5c, + 0x5a, 0x53, 0xd5, 0x12, 0x89, 0xb5, 0x0e, 0x73, 0xdc, 0xec, + 0x4a, 0xa1, 0xcb, 0x47, 0xa3, 0xba, 0xd8, 0x46, 0xbb, 0x57, + 0xc3, 0xc4, 0x80, 0x49, 0x1d, 0xf5, 0x21, 0xc4, 0x66, 0x9b, + 0xff, 0xf3, 0x7a, 0x41, 0x8b, 0xaf, 0x6e, 0x9b, 0xea, 0xec, + 0x34, 0x96, 0xd0, 0xf1, 0xa6 ) ); + +/** SHA-256 Test 16 */ +HASH_DF_TEST ( test_sha256_16, sha256_algorithm, + INPUT ( 0x00, 0xfc, 0x5f, 0x56, 0x48, 0xed, 0xc4, 0xfc, 0x30, 0x7b, + 0x5c, 0x5a, 0x53, 0xd5, 0x12, 0x89, 0xb5, 0x0e, 0x73, 0xdc, + 0xec, 0x4a, 0xa1, 0xcb, 0x47, 0xa3, 0xba, 0xd8, 0x46, 0xbb, + 0x57, 0xc3, 0xc4, 0x80, 0x49, 0x1d, 0xf5, 0x21, 0xc4, 0x66, + 0x9b, 0xff, 0xf3, 0x7a, 0x41, 0x8b, 0xaf, 0x6e, 0x9b, 0xea, + 0xec, 0x34, 0x96, 0xd0, 0xf1, 0xa6 ), + EXPECT ( 0x62, 0xb0, 0x7d, 0xc3, 0x9e, 0xbd, 0xf3, 0x10, 0x87, 0xb8, + 0x5d, 0xdc, 0xec, 0xfd, 0x43, 0x35, 0x62, 0xe5, 0x3b, 0xae, + 0x9f, 0x72, 0x1c, 0x5a, 0xfa, 0xb8, 0xf1, 0xcf, 0x01, 0x61, + 0xc8, 0x8e, 0x45, 0x50, 0x3e, 0x15, 0xb2, 0x6e, 0x7b, 0x80, + 0xd5, 0x1d, 0xb0, 0xb9, 0x24, 0x52, 0x36, 0x2d, 0xc3, 0xdc, + 0x57, 0x0d, 0xfe, 0x6e, 0x17 ) ); + +/** SHA-256 Test 17 */ +HASH_DF_TEST ( test_sha256_17, sha256_algorithm, + INPUT ( 0x01, 0xa3, 0xe9, 0x4e, 0x39, 0x26, 0xfd, 0xa1, 0x69, 0xc3, + 0x03, 0xd6, 0x64, 0x38, 0x39, 0x05, 0xe0, 0xd7, 0x99, 0x62, + 0xd1, 0x65, 0x44, 0x6d, 0x63, 0xbd, 0xa6, 0x54, 0xd1, 0x32, + 0xf7, 0x2d, 0xb4, 0x71, 0x56, 0x4b, 0x45, 0x6f, 0xf2, 0xee, + 0xc8, 0x36, 0x42, 0x2a, 0xcc, 0x5a, 0x02, 0x99, 0x35, 0xa7, + 0x99, 0x29, 0x90, 0x94, 0xa1, 0xca, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 ), + EXPECT ( 0x98, 0x75, 0xbb, 0x7c, 0x7a, 0x0b, 0x23, 0x6b, 0xf4, 0x6f, + 0x4e, 0xa6, 0x6f, 0x67, 0xc7, 0xb4, 0x4f, 0x80, 0xef, 0x70, + 0x61, 0x4b, 0xef, 0xe8, 0xb0, 0x85, 0xcc, 0xaf, 0x55, 0x89, + 0xa7, 0x6f, 0x85, 0xfd, 0x96, 0x69, 0x53, 0xe2, 0x0a, 0x55, + 0xd2, 0xf3, 0x5b, 0xa5, 0x81, 0xef, 0x51, 0x11, 0xbf, 0xbf, + 0x05, 0x65, 0x3a, 0xf7, 0xe7 ) ); + +/** SHA-256 Test 18 */ +HASH_DF_TEST ( test_sha256_18, sha256_algorithm, + INPUT ( 0x00, 0x98, 0x75, 0xbb, 0x7c, 0x7a, 0x0b, 0x23, 0x6b, 0xf4, + 0x6f, 0x4e, 0xa6, 0x6f, 0x67, 0xc7, 0xb4, 0x4f, 0x80, 0xef, + 0x70, 0x61, 0x4b, 0xef, 0xe8, 0xb0, 0x85, 0xcc, 0xaf, 0x55, + 0x89, 0xa7, 0x6f, 0x85, 0xfd, 0x96, 0x69, 0x53, 0xe2, 0x0a, + 0x55, 0xd2, 0xf3, 0x5b, 0xa5, 0x81, 0xef, 0x51, 0x11, 0xbf, + 0xbf, 0x05, 0x65, 0x3a, 0xf7, 0xe7 ), + EXPECT ( 0x12, 0x80, 0xfe, 0x1f, 0x05, 0x79, 0x8c, 0xca, 0xed, 0x5d, + 0x6d, 0xf6, 0xe7, 0xd2, 0x6f, 0x04, 0x6e, 0x53, 0x8c, 0xc5, + 0x2a, 0x6a, 0x03, 0x0d, 0xa8, 0x26, 0xb2, 0xb4, 0x79, 0x82, + 0xd6, 0xee, 0x8a, 0x68, 0x67, 0x58, 0x07, 0x06, 0x93, 0x9e, + 0xcc, 0x03, 0xfc, 0x11, 0xb0, 0x05, 0x9f, 0xe2, 0xae, 0xad, + 0xea, 0x0a, 0x46, 0x98, 0x5c ) ); + +/** SHA-256 Test 19 */ +HASH_DF_TEST ( test_sha256_19, sha256_algorithm, + INPUT ( 0x01, 0xaa, 0xf6, 0xb9, 0x9b, 0x7f, 0x84, 0xb0, 0x36, 0xe1, + 0xcc, 0xbc, 0x9d, 0x57, 0x3a, 0x36, 0xb8, 0xbd, 0xd4, 0x7c, + 0x35, 0x8b, 0xb5, 0xf3, 0xc1, 0xd6, 0xe7, 0x90, 0x3a, 0xaa, + 0x29, 0xf1, 0xc8, 0x7a, 0xe6, 0x66, 0xb8, 0x86, 0x93, 0xbe, + 0xf4, 0x6c, 0x51, 0xc2, 0x4c, 0x47, 0xbe, 0xfe, 0x4b, 0x35, + 0x75, 0x4d, 0xcb, 0xfa, 0x1e, 0x7d, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 ), + EXPECT ( 0xb0, 0x6d, 0xbf, 0xb1, 0x4e, 0x7f, 0x4e, 0x01, 0x25, 0x62, + 0x94, 0x2f, 0xe4, 0xf2, 0xa9, 0x60, 0x17, 0x07, 0x55, 0x9d, + 0x7d, 0xd1, 0x90, 0x89, 0x8b, 0xc8, 0x06, 0x24, 0xe5, 0xc8, + 0xc1, 0xbb, 0x9b, 0x90, 0xfb, 0x2e, 0xef, 0x12, 0xed, 0x24, + 0xbe, 0xbd, 0x8d, 0xf7, 0x1e, 0xf6, 0x5c, 0x70, 0xfa, 0x4e, + 0x91, 0x86, 0x3a, 0x31, 0xbe ) ); + +/** SHA-256 Test 20 */ +HASH_DF_TEST ( test_sha256_20, sha256_algorithm, + INPUT ( 0x00, 0xb0, 0x6d, 0xbf, 0xb1, 0x4e, 0x7f, 0x4e, 0x01, 0x25, + 0x62, 0x94, 0x2f, 0xe4, 0xf2, 0xa9, 0x60, 0x17, 0x07, 0x55, + 0x9d, 0x7d, 0xd1, 0x90, 0x89, 0x8b, 0xc8, 0x06, 0x24, 0xe5, + 0xc8, 0xc1, 0xbb, 0x9b, 0x90, 0xfb, 0x2e, 0xef, 0x12, 0xed, + 0x24, 0xbe, 0xbd, 0x8d, 0xf7, 0x1e, 0xf6, 0x5c, 0x70, 0xfa, + 0x4e, 0x91, 0x86, 0x3a, 0x31, 0xbe ), + EXPECT ( 0x5c, 0x07, 0xb7, 0x9c, 0x12, 0x83, 0x1b, 0xac, 0x36, 0x52, + 0x17, 0x8b, 0x2f, 0x90, 0x7a, 0x69, 0x61, 0x98, 0x39, 0xd8, + 0xa7, 0xfa, 0xa2, 0xb6, 0x95, 0xef, 0xb3, 0x10, 0x82, 0x38, + 0x01, 0x35, 0x85, 0x19, 0x1f, 0x59, 0x9c, 0x99, 0x07, 0xc7, + 0x21, 0x92, 0xed, 0x25, 0x7e, 0x9f, 0x6c, 0xd3, 0x77, 0xdd, + 0x6b, 0xac, 0x33, 0x7c, 0x19 ) ); + +/** + * Report Hash_df test result + * + * @v test Hash_df test + */ +#define hash_df_ok( test ) do { \ + uint8_t output[ (test)->expected_len ]; \ + hash_df ( (test)->hash, (test)->input, (test)->input_len, \ + output, sizeof ( output ) ); \ + ok ( memcmp ( (test)->expected, output, \ + sizeof ( output ) ) == 0 ); \ + } while ( 0 ) + +/** + * Perform Hash_df self-test + * + */ +static void hash_df_test_exec ( void ) { + + hash_df_ok ( &test_sha1_1 ); + hash_df_ok ( &test_sha1_2 ); + hash_df_ok ( &test_sha1_3 ); + hash_df_ok ( &test_sha1_4 ); + hash_df_ok ( &test_sha1_5 ); + hash_df_ok ( &test_sha1_6 ); + hash_df_ok ( &test_sha1_7 ); + hash_df_ok ( &test_sha1_8 ); + hash_df_ok ( &test_sha1_9 ); + hash_df_ok ( &test_sha1_10 ); + hash_df_ok ( &test_sha1_11 ); + hash_df_ok ( &test_sha1_12 ); + hash_df_ok ( &test_sha1_13 ); + hash_df_ok ( &test_sha1_14 ); + hash_df_ok ( &test_sha1_15 ); + hash_df_ok ( &test_sha1_16 ); + hash_df_ok ( &test_sha1_17 ); + hash_df_ok ( &test_sha1_18 ); + hash_df_ok ( &test_sha1_19 ); + hash_df_ok ( &test_sha1_20 ); + + hash_df_ok ( &test_sha256_1 ); + hash_df_ok ( &test_sha256_2 ); + hash_df_ok ( &test_sha256_3 ); + hash_df_ok ( &test_sha256_4 ); + hash_df_ok ( &test_sha256_5 ); + hash_df_ok ( &test_sha256_6 ); + hash_df_ok ( &test_sha256_7 ); + hash_df_ok ( &test_sha256_8 ); + hash_df_ok ( &test_sha256_9 ); + hash_df_ok ( &test_sha256_10 ); + hash_df_ok ( &test_sha256_11 ); + hash_df_ok ( &test_sha256_12 ); + hash_df_ok ( &test_sha256_13 ); + hash_df_ok ( &test_sha256_14 ); + hash_df_ok ( &test_sha256_15 ); + hash_df_ok ( &test_sha256_16 ); + hash_df_ok ( &test_sha256_17 ); + hash_df_ok ( &test_sha256_18 ); + hash_df_ok ( &test_sha256_19 ); + hash_df_ok ( &test_sha256_20 ); +} + +/** Hash_df self-test */ +struct self_test hash_df_test __self_test = { + .name = "hash_df", + .exec = hash_df_test_exec, +}; diff --git a/src/tests/hmac_drbg_test.c b/src/tests/hmac_drbg_test.c index cf066620..d03efef0 100644 --- a/src/tests/hmac_drbg_test.c +++ b/src/tests/hmac_drbg_test.c @@ -33,7 +33,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 */ @@ -41,10 +44,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** An HMAC_DRBG instantiation test */ struct hmac_drbg_test_instantiate { - /** Entropy (including nonce) */ + /** Underlying hash algorithm */ + struct digest_algorithm *hash; + /** Output block length */ + size_t out_len; + /** Entropy */ const void *entropy; - /** Length of entropy (including nonce) */ + /** 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 */ @@ -63,19 +74,26 @@ struct hmac_drbg_test_instantiate { * Define an HMAC_DRBG instantiation test * * @v name Test name - * @v entropy_array Entropy input (including nonce) + * @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, entropy_array, \ - personal_array, key, value ) \ +#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 const struct hmac_drbg_test_instantiate name = { \ + 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, \ @@ -91,19 +109,33 @@ struct hmac_drbg_test_instantiate { * @v test Instantiation test */ #define instantiate_ok( state, test ) do { \ - assert ( (test)->expected_key_len == HMAC_DRBG_OUTLEN_BYTES ); \ - assert ( (test)->expected_value_len == HMAC_DRBG_OUTLEN_BYTES ); \ - hmac_drbg_instantiate ( (state), (test)->entropy, \ - (test)->entropy_len, (test)->personal, \ + 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, \ - sizeof ( (state)->key ) ) == 0 ); \ + (test)->expected_key_len ) == 0 ); \ ok ( memcmp ( (state)->value, (test)->expected_value, \ - sizeof ( (state)->value ) ) == 0 ); \ + (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 */ @@ -126,17 +158,20 @@ struct hmac_drbg_test_reseed { * 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, entropy_array, additional_array, \ - key, value ) \ +#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 const struct hmac_drbg_test_reseed name = { \ + 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, \ @@ -154,19 +189,23 @@ struct hmac_drbg_test_reseed { * @v test Reseed test */ #define reseed_ok( state, test ) do { \ - assert ( (test)->expected_key_len == HMAC_DRBG_OUTLEN_BYTES ); \ - assert ( (test)->expected_value_len == HMAC_DRBG_OUTLEN_BYTES ); \ - hmac_drbg_reseed ( (state), (test)->entropy, \ + 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, \ - sizeof ( (state)->key ) ) == 0 ); \ + (test)->expected_key_len ) == 0 ); \ ok ( memcmp ( (state)->value, (test)->expected_value, \ - sizeof ( (state)->value ) ) == 0 ); \ + (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 */ @@ -182,25 +221,28 @@ struct hmac_drbg_test_generate { /** Expected pseudorandom data */ const void *expected_data; /** Length of data */ - size_t len; + 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, additional_array, key, value, \ - data ) \ +#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 const struct hmac_drbg_test_generate name = { \ + 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, \ @@ -208,7 +250,7 @@ struct hmac_drbg_test_generate { .expected_value = name ## _value, \ .expected_value_len = sizeof ( name ## _value ), \ .expected_data = name ## _data, \ - .len = sizeof ( name ## _data ), \ + .expected_data_len = sizeof ( name ## _data ), \ } /** @@ -218,25 +260,28 @@ struct hmac_drbg_test_generate { * @v test Generation test */ #define generate_ok( state, test ) do { \ - uint8_t data[ (test)->len ]; \ + uint8_t data[ (test)->expected_data_len ]; \ int rc; \ \ - assert ( (test)->expected_key_len == HMAC_DRBG_OUTLEN_BYTES ); \ - assert ( (test)->expected_value_len == HMAC_DRBG_OUTLEN_BYTES );\ - rc = hmac_drbg_generate ( (state), (test)->additional, \ - (test)->additional_len, data, \ - sizeof ( data ) ); \ + 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, \ - sizeof ( (state)->key ) ) == 0 ); \ + (test)->expected_key_len ) == 0 ); \ ok ( memcmp ( (state)->value, (test)->expected_value, \ - sizeof ( (state)->value ) ) == 0 ); \ + (test)->expected_value_len ) == 0 ); \ ok ( memcmp ( data, (test)->expected_data, \ - sizeof ( data ) ) == 0 ); \ + (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 */ @@ -249,11 +294,14 @@ struct hmac_drbg_test_generate_fail { * 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, additional_array, len ) \ - static const struct hmac_drbg_test_generate_fail name = { \ +#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, \ @@ -269,28 +317,32 @@ struct hmac_drbg_test_generate_fail { uint8_t data[ (test)->requested_len ]; \ int rc; \ \ - rc = hmac_drbg_generate ( (state), (test)->additional, \ + rc = hmac_drbg_generate ( (test)->hash, (state), \ + (test)->additional, \ (test)->additional_len, data, \ sizeof ( data ) ); \ ok ( rc != 0 ); \ } while ( 0 ) -/** "EntropyInput" and "Nonce" - * - * These are pre-concatenated since our implementation expects to - * receive the nonce in the form of additional entropy. - */ +/** "EntropyInput" */ static const uint8_t entropy_input[] = { - /* "EntropyInput" */ 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" */ + 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, @@ -342,16 +394,16 @@ static const uint8_t additional_input_2[] = { 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6 }; -/** Test 1 : Instantiation */ -HMAC_DRBG_TEST_INSTANTIATE ( instantiate_1, - entropy_input, personalisation_string_empty, +/** 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 ) ); -/** Test 1.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_1_1, +/** 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 ), @@ -362,8 +414,8 @@ HMAC_DRBG_TEST_GENERATE ( generate_1_1, 0x8c, 0x0b, 0x22, 0xcd, 0x06, 0x30, 0xbf, 0xb0, 0x12, 0x7f, 0xb5, 0x40, 0x8c, 0x8e, 0xfc, 0x17, 0xa9, 0x29, 0x89, 0x6e ) ); -/** Test 1.2 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_1_2, +/** 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 ), @@ -374,11 +426,11 @@ HMAC_DRBG_TEST_GENERATE ( generate_1_2, 0x9c, 0xe3, 0x67, 0xd0, 0x3a, 0xea, 0xde, 0x37, 0x82, 0x7f, 0xa8, 0xe9, 0xcb, 0x6a, 0x08, 0x19, 0x61, 0x15, 0xd9, 0x48 ) ); -/** Test 2 : Instantiation */ -#define instantiate_2 instantiate_1 +/** SHA-1 Test 2 : Instantiation */ +#define sha1_instantiate_2 sha1_instantiate_1 -/** Test 2.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_2_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 ), @@ -389,8 +441,8 @@ HMAC_DRBG_TEST_GENERATE ( generate_2_1, 0x9a, 0xd0, 0xbb, 0x26, 0xfa, 0xc0, 0x49, 0x7b, 0x5c, 0x57, 0xe1, 0x61, 0xe3, 0x66, 0x81, 0xbc, 0xc9, 0x30, 0xce, 0x80 ) ); -/** Test 2.2 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_2_2, +/** 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 ), @@ -401,16 +453,16 @@ HMAC_DRBG_TEST_GENERATE ( generate_2_2, 0xb9, 0xc3, 0x7b, 0x7f, 0xe8, 0x1b, 0xa9, 0x40, 0x45, 0xa1, 0x4a, 0x7c, 0xb5, 0x14, 0xb4, 0x46, 0x66, 0x6e, 0xa5, 0xa7 ) ); -/** Test 3 : Instantiation */ -HMAC_DRBG_TEST_INSTANTIATE ( instantiate_3, - entropy_input, personalisation_string, +/** 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 ) ); -/** Test 3.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_3_1, +/** 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 ), @@ -421,8 +473,8 @@ HMAC_DRBG_TEST_GENERATE ( generate_3_1, 0x9b, 0xd0, 0x60, 0x20, 0x8e, 0xea, 0x7d, 0x71, 0xf9, 0xd1, 0x23, 0xdf, 0x47, 0xb3, 0xce, 0x06, 0x9d, 0x98, 0xed, 0xe6 ) ); -/** Test 3.2 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_3_2, +/** 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 ), @@ -433,11 +485,11 @@ HMAC_DRBG_TEST_GENERATE ( generate_3_2, 0x63, 0x97, 0x65, 0x47, 0x2b, 0x71, 0xac, 0xeb, 0xe2, 0xea, 0x8b, 0x1b, 0x6b, 0x49, 0x62, 0x9c, 0xb6, 0x73, 0x17, 0xe0 ) ); -/** Test 4 : Instantiation */ -#define instantiate_4 instantiate_3 +/** SHA-1 Test 4 : Instantiation */ +#define sha1_instantiate_4 sha1_instantiate_3 -/** Test 4.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_4_1, +/** 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 ), @@ -448,8 +500,8 @@ HMAC_DRBG_TEST_GENERATE ( generate_4_1, 0x6d, 0xfc, 0x30, 0x2e, 0xad, 0x4c, 0xe3, 0xf5, 0x54, 0xc7, 0x9b, 0x0d, 0x44, 0x23, 0x9e, 0xba, 0x56, 0xa7, 0xea, 0x2d ) ); -/** Test 4.2 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_4_2, +/** 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 ), @@ -460,23 +512,23 @@ HMAC_DRBG_TEST_GENERATE ( generate_4_2, 0xdc, 0x91, 0x21, 0x5d, 0x44, 0xb1, 0x07, 0xb4, 0xd5, 0xa7, 0x79, 0x01, 0x59, 0x25, 0x09, 0x76, 0x52, 0x80, 0xf9, 0x69 ) ); -/** Test 5 : Instantiation */ -#define instantiate_5 instantiate_1 +/** SHA-1 Test 5 : Instantiation */ +#define sha1_instantiate_5 sha1_instantiate_1 -/** Test 5.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_5_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 ) ); -/** Test 5.2 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_5_2, +/** 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 ) ); -/** Test 5.3 : Retried first call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_5_3, +/** 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 ), @@ -487,20 +539,20 @@ HMAC_DRBG_TEST_GENERATE ( generate_5_3, 0xbc, 0x0e, 0xfc, 0x28, 0x2a, 0xbd, 0x87, 0x60, 0x5c, 0xc9, 0x0c, 0xba, 0x9b, 0x86, 0x33, 0xdc, 0xb1, 0xda, 0xe0, 0x2e ) ); -/** Test 5.4 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_5_4, +/** 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 ) ); -/** Test 5.5 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_5_5, +/** 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 ) ); -/** Test 5.6 : Retried second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_5_6, +/** 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 ), @@ -511,23 +563,23 @@ HMAC_DRBG_TEST_GENERATE ( generate_5_6, 0x1a, 0x0a, 0xd3, 0x9b, 0xd1, 0x5e, 0x86, 0x2e, 0x64, 0x4f, 0x31, 0xe4, 0xa2, 0xd7, 0xd8, 0x43, 0xe5, 0x7c, 0x59, 0x68 ) ); -/** Test 6 : Instantiate */ -#define instantiate_6 instantiate_1 +/** SHA-1 Test 6 : Instantiate */ +#define sha1_instantiate_6 sha1_instantiate_1 -/** Test 6.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_6_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 ) ); -/** Test 6.2 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_6_2, +/** 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 ) ); -/** Test 6.3 : Retried first call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_6_3, +/** 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 ), @@ -538,20 +590,20 @@ HMAC_DRBG_TEST_GENERATE ( generate_6_3, 0x57, 0xae, 0xe8, 0x15, 0xb9, 0xc0, 0x70, 0x04, 0xc7, 0xe9, 0x92, 0xeb, 0x8c, 0x7e, 0x59, 0x19, 0x64, 0xaf, 0xee, 0xa2 ) ); -/** Test 6.4 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_6_4, +/** 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 ) ); -/** Test 6.5 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_6_5, +/** 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 ) ); -/** Test 6.6 : Retried second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_6_6, +/** 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 ), @@ -562,23 +614,23 @@ HMAC_DRBG_TEST_GENERATE ( generate_6_6, 0x2d, 0xc6, 0x4a, 0x16, 0x42, 0x11, 0x88, 0x9a, 0x01, 0x0f, 0x24, 0x71, 0xa0, 0x91, 0x2f, 0xfe, 0xa1, 0xbf, 0x01, 0x95 ) ); -/** Test 7 : Instantiation */ -#define instantiate_7 instantiate_3 +/** SHA-1 Test 7 : Instantiation */ +#define sha1_instantiate_7 sha1_instantiate_3 -/** Test 7.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_7_1, +/** 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 ) ); -/** Test 7.2 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_7_2, +/** 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 ) ); -/** Test 7.3 : Retried first call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_7_3, +/** 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 ), @@ -589,20 +641,20 @@ HMAC_DRBG_TEST_GENERATE ( generate_7_3, 0xb5, 0x70, 0x81, 0xe4, 0x22, 0x0f, 0x22, 0xc5, 0xc2, 0x83, 0xe2, 0xc9, 0x1b, 0x8e, 0x30, 0x5a, 0xb8, 0x69, 0xc6, 0x25 ) ); -/** Test 7.4 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_7_4, +/** 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 ) ); -/** Test 7.5 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_7_5, +/** 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 ) ); -/** Test 7.6 : Retried second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_7_6, +/** 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 ), @@ -613,23 +665,23 @@ HMAC_DRBG_TEST_GENERATE ( generate_7_6, 0x61, 0x48, 0x2c, 0xa5, 0x4d, 0x5f, 0xa7, 0x23, 0xf4, 0xc8, 0x8b, 0x4f, 0xa5, 0x04, 0xbf, 0x03, 0x27, 0x7f, 0xa7, 0x83 ) ); -/** Test 8 : Instantiate */ -#define instantiate_8 instantiate_3 +/** SHA-1 Test 8 : Instantiate */ +#define sha1_instantiate_8 sha1_instantiate_3 -/** Test 8.1 : First call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_8_1, +/** 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 ) ); -/** Test 8.2 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_8_2, +/** 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 ) ); -/** Test 8.3 : Retried first call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_8_3, +/** 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 ), @@ -640,20 +692,20 @@ HMAC_DRBG_TEST_GENERATE ( generate_8_3, 0x34, 0x71, 0xfd, 0xa5, 0x5c, 0x6d, 0xdd, 0x2c, 0x03, 0xef, 0xa3, 0xb9, 0x64, 0x3a, 0xb3, 0xbb, 0x22, 0xf6, 0xc9, 0xf2 ) ); -/** Test 8.4 : Second call to Generate */ -HMAC_DRBG_TEST_GENERATE_FAIL ( generate_fail_8_4, +/** 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 ) ); -/** Test 8.5 : Reseed */ -HMAC_DRBG_TEST_RESEED ( reseed_8_5, +/** 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 ) ); -/** Test 8.6 : Retried second call to Generate */ -HMAC_DRBG_TEST_GENERATE ( generate_8_6, +/** 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 ), @@ -664,6 +716,480 @@ HMAC_DRBG_TEST_GENERATE ( generate_8_6, 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 * @@ -723,69 +1249,133 @@ static void hmac_drbg_test_exec ( void ) { * greater than the reseed_interval. */ - /* Test 1 */ - instantiate_ok ( &state, &instantiate_1 ); - generate_ok ( &state, &generate_1_1 ); - generate_ok ( &state, &generate_1_2 ); + /* SHA-1 Test 1 */ + instantiate_ok ( &state, &sha1_instantiate_1 ); + generate_ok ( &state, &sha1_generate_1_1 ); + generate_ok ( &state, &sha1_generate_1_2 ); - /* Test 2 */ - instantiate_ok ( &state, &instantiate_2 ); - generate_ok ( &state, &generate_2_1 ); - generate_ok ( &state, &generate_2_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 ); - /* Test 3 */ - instantiate_ok ( &state, &instantiate_3 ); - generate_ok ( &state, &generate_3_1 ); - generate_ok ( &state, &generate_3_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 ); - /* Test 4 */ - instantiate_ok ( &state, &instantiate_4 ); - generate_ok ( &state, &generate_4_1 ); - generate_ok ( &state, &generate_4_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 ); - /* Test 5 */ - instantiate_ok ( &state, &instantiate_5 ); + /* SHA-1 Test 5 */ + instantiate_ok ( &state, &sha1_instantiate_5 ); force_reseed_required ( &state ); /* See above comments */ - generate_fail_ok ( &state, &generate_fail_5_1 ); - reseed_ok ( &state, &reseed_5_2 ); - generate_ok ( &state, &generate_5_3 ); + 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, &generate_fail_5_4 ); - reseed_ok ( &state, &reseed_5_5 ); - generate_ok ( &state, &generate_5_6 ); + generate_fail_ok ( &state, &sha1_generate_fail_5_4 ); + reseed_ok ( &state, &sha1_reseed_5_5 ); + generate_ok ( &state, &sha1_generate_5_6 ); - /* Test 6 */ - instantiate_ok ( &state, &instantiate_6 ); + /* SHA-1 Test 6 */ + instantiate_ok ( &state, &sha1_instantiate_6 ); force_reseed_required ( &state ); /* See above comments */ - generate_fail_ok ( &state, &generate_fail_6_1 ); - reseed_ok ( &state, &reseed_6_2 ); - generate_ok ( &state, &generate_6_3 ); + 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, &generate_fail_6_4 ); - reseed_ok ( &state, &reseed_6_5 ); - generate_ok ( &state, &generate_6_6 ); + generate_fail_ok ( &state, &sha1_generate_fail_6_4 ); + reseed_ok ( &state, &sha1_reseed_6_5 ); + generate_ok ( &state, &sha1_generate_6_6 ); - /* Test 7 */ - instantiate_ok ( &state, &instantiate_7 ); + /* SHA-1 Test 7 */ + instantiate_ok ( &state, &sha1_instantiate_7 ); force_reseed_required ( &state ); /* See above comments */ - generate_fail_ok ( &state, &generate_fail_7_1 ); - reseed_ok ( &state, &reseed_7_2 ); - generate_ok ( &state, &generate_7_3 ); + 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, &generate_fail_7_4 ); - reseed_ok ( &state, &reseed_7_5 ); - generate_ok ( &state, &generate_7_6 ); + generate_fail_ok ( &state, &sha1_generate_fail_7_4 ); + reseed_ok ( &state, &sha1_reseed_7_5 ); + generate_ok ( &state, &sha1_generate_7_6 ); - /* Test 8 */ - instantiate_ok ( &state, &instantiate_8 ); + /* SHA-1 Test 8 */ + instantiate_ok ( &state, &sha1_instantiate_8 ); force_reseed_required ( &state ); /* See above comments */ - generate_fail_ok ( &state, &generate_fail_8_1 ); - reseed_ok ( &state, &reseed_8_2 ); - generate_ok ( &state, &generate_8_3 ); + 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, &generate_fail_8_4 ); - reseed_ok ( &state, &reseed_8_5 ); - generate_ok ( &state, &generate_8_6 ); + 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 */ diff --git a/src/tests/list_test.c b/src/tests/list_test.c index d75f8324..5184b308 100644 --- a/src/tests/list_test.c +++ b/src/tests/list_test.c @@ -118,6 +118,41 @@ static int list_check_contents ( struct list_head *list, 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 * @@ -126,6 +161,9 @@ 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 ) ); @@ -330,35 +368,46 @@ static void list_test_exec ( void ) { ok ( list_entry ( &list_tests[3].list, struct list_test, list ) == &list_tests[3] ); - /* Test list_first_entry() */ + /* 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 ); - { - char *expected = "673"; - struct list_head *pos; - struct list_test *entry; - list_for_each ( pos, list ) { - entry = list_entry ( pos, struct list_test, list ); - ok ( entry->label == *(expected++) ); - } - } + list_iterate_ok ( list_for_each, "673", raw_pos, list ); - /* list_for_each_entry() and list_for_each_entry_reverse() are - * already tested as part of list_contents_ok() - */ + /* 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 ); @@ -367,8 +416,6 @@ static void list_test_exec ( void ) { list_add_tail ( &list_tests[1].list, list ); { char *expected = "241"; - struct list_test *pos; - struct list_test *tmp; list_for_each_entry_safe ( pos, tmp, list, list ) { list_contents_ok ( list, expected ); list_del ( &pos->list ); @@ -378,6 +425,34 @@ static void list_test_exec ( void ) { } 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 ); diff --git a/src/tests/md5_test.c b/src/tests/md5_test.c new file mode 100644 index 00000000..17972daa --- /dev/null +++ b/src/tests/md5_test.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * MD5 tests + * + */ + +#include <stdint.h> +#include <ipxe/md5.h> +#include <ipxe/test.h> +#include "digest_test.h" + +/** An MD5 test vector */ +struct md5_test_vector { + /** Test data */ + void *data; + /** Test data length */ + size_t len; + /** Expected digest */ + uint8_t digest[MD5_DIGEST_SIZE]; +}; + +/** MD5 test vectors */ +static struct md5_test_vector md5_test_vectors[] = { + /* Test inputs borrowed from SHA-1 tests, with results + * calculated using md5sum. + */ + { NULL, 0, + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "abc", 3, + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + { 0x82, 0x15, 0xef, 0x07, 0x96, 0xa2, 0x0b, 0xca, + 0xaa, 0xe1, 0x16, 0xd3, 0x87, 0x6c, 0x66, 0x4a } }, +}; + +/** MD5 test fragment lists */ +static struct digest_test_fragments md5_test_fragments[] = { + { { 0, -1UL, } }, + { { 1, 1, 1, 1, 1, 1, 1, 1 } }, + { { 2, 0, 23, 4, 6, 1, 0 } }, +}; + +/** + * Perform MD5 self-test + * + */ +static void md5_test_exec ( void ) { + struct digest_algorithm *digest = &md5_algorithm; + struct md5_test_vector *test; + unsigned int i; + unsigned int j; + + for ( i = 0 ; i < ( sizeof ( md5_test_vectors ) / + sizeof ( md5_test_vectors[0] ) ) ; i++ ) { + test = &md5_test_vectors[i]; + /* Test with a single pass */ + digest_ok ( digest, NULL, test->data, test->len, test->digest ); + /* Test with fragment lists */ + for ( j = 0 ; j < ( sizeof ( md5_test_fragments ) / + sizeof ( md5_test_fragments[0] ) ) ; j++ ){ + digest_ok ( digest, &md5_test_fragments[j], + test->data, test->len, test->digest ); + } + } +} + +/** MD5 self-test */ +struct self_test md5_test __self_test = { + .name = "md5", + .exec = md5_test_exec, +}; diff --git a/src/tests/pubkey_test.h b/src/tests/pubkey_test.h new file mode 100644 index 00000000..7678453a --- /dev/null +++ b/src/tests/pubkey_test.h @@ -0,0 +1,175 @@ +#ifndef _PUBKEY_TEST_H +#define _PUBKEY_TEST_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/crypto.h> +#include <ipxe/test.h> + +/** + * Report public key decryption test result + * + * @v pubkey Public key algorithm + * @v key Key + * @v key_len Key length + * @v ciphertext Ciphertext + * @v ciphertext_len Ciphertext length + * @v expected Expected plaintext + * @v expected_len Expected plaintext length + */ +#define pubkey_decrypt_ok( pubkey, key, key_len, ciphertext, \ + ciphertext_len, expected, expected_len ) do {\ + uint8_t ctx[ (pubkey)->ctxsize ]; \ + \ + ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \ + { \ + size_t max_len = pubkey_max_len ( (pubkey), ctx ); \ + uint8_t decrypted[ max_len ]; \ + int decrypted_len; \ + \ + decrypted_len = pubkey_decrypt ( (pubkey), ctx, \ + (ciphertext), \ + (ciphertext_len), \ + decrypted ); \ + ok ( decrypted_len == ( ( int ) (expected_len) ) ); \ + ok ( memcmp ( decrypted, (expected), \ + (expected_len) ) == 0 ); \ + } \ + pubkey_final ( (pubkey), ctx ); \ + } while ( 0 ) + +/** + * Report public key encryption and decryption test result + * + * @v pubkey Public key algorithm + * @v encrypt_key Encryption key + * @v encrypt_key_len Encryption key length + * @v decrypt_key Decryption key + * @v decrypt_key_len Decryption key length + * @v plaintext Plaintext + * @v plaintext_len Plaintext length + */ +#define pubkey_encrypt_ok( pubkey, encrypt_key, encrypt_key_len, \ + decrypt_key, decrypt_key_len, plaintext, \ + plaintext_len ) do { \ + uint8_t ctx[ (pubkey)->ctxsize ]; \ + \ + ok ( pubkey_init ( (pubkey), ctx, (encrypt_key), \ + (encrypt_key_len) ) == 0 ); \ + { \ + size_t max_len = pubkey_max_len ( (pubkey), ctx ); \ + uint8_t encrypted[ max_len ]; \ + int encrypted_len; \ + \ + encrypted_len = pubkey_encrypt ( (pubkey), ctx, \ + (plaintext), \ + (plaintext_len), \ + encrypted ); \ + ok ( encrypted_len >= 0 ); \ + pubkey_decrypt_ok ( (pubkey), (decrypt_key), \ + (decrypt_key_len), encrypted, \ + encrypted_len, (plaintext), \ + (plaintext_len) ); \ + } \ + pubkey_final ( (pubkey), ctx ); \ + } while ( 0 ) + +/** + * Report public key signature test result + * + * @v pubkey Public key algorithm + * @v key Key + * @v key_len Key length + * @v digest Digest algorithm + * @v plaintext Plaintext + * @v plaintext_len Plaintext length + * @v expected Expected signature + * @v expected_len Expected signature length + */ +#define pubkey_sign_ok( pubkey, key, key_len, digest, plaintext, \ + plaintext_len, expected, expected_len ) do { \ + uint8_t ctx[ (pubkey)->ctxsize ]; \ + uint8_t digestctx[ (digest)->ctxsize ]; \ + uint8_t digestout[ (digest)->digestsize ]; \ + \ + digest_init ( (digest), digestctx ); \ + digest_update ( (digest), digestctx, (plaintext), \ + (plaintext_len) ); \ + digest_final ( (digest), digestctx, digestout ); \ + \ + ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \ + { \ + size_t max_len = pubkey_max_len ( (pubkey), ctx ); \ + uint8_t signature[ max_len ]; \ + int signature_len; \ + \ + signature_len = pubkey_sign ( (pubkey), ctx, (digest), \ + digestout, signature ); \ + ok ( signature_len == ( ( int ) (expected_len) ) ); \ + ok ( memcmp ( signature, (expected), \ + (expected_len) ) == 0 ); \ + } \ + pubkey_final ( (pubkey), ctx ); \ + } while ( 0 ) + +/** + * Report public key verification test result + * + * @v pubkey Public key algorithm + * @v key Key + * @v key_len Key length + * @v digest Digest algorithm + * @v plaintext Plaintext + * @v plaintext_len Plaintext length + * @v signature Signature + * @v signature_len Signature length + */ +#define pubkey_verify_ok( pubkey, key, key_len, digest, plaintext, \ + plaintext_len, signature, signature_len ) do {\ + uint8_t ctx[ (pubkey)->ctxsize ]; \ + uint8_t digestctx[ (digest)->ctxsize ]; \ + uint8_t digestout[ (digest)->digestsize ]; \ + \ + digest_init ( (digest), digestctx ); \ + digest_update ( (digest), digestctx, (plaintext), \ + (plaintext_len) ); \ + digest_final ( (digest), digestctx, digestout ); \ + \ + ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \ + ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \ + (signature), (signature_len) ) == 0 ); \ + pubkey_final ( (pubkey), ctx ); \ + } while ( 0 ) + +/** + * Report public key verification test result + * + * @v pubkey Public key algorithm + * @v key Key + * @v key_len Key length + * @v digest Digest algorithm + * @v plaintext Plaintext + * @v plaintext_len Plaintext length + * @v signature Signature + * @v signature_len Signature length + */ +#define pubkey_verify_fail_ok( pubkey, key, key_len, digest, plaintext, \ + plaintext_len, signature, \ + signature_len ) do { \ + uint8_t ctx[ (pubkey)->ctxsize ]; \ + uint8_t digestctx[ (digest)->ctxsize ]; \ + uint8_t digestout[ (digest)->digestsize ]; \ + \ + digest_init ( (digest), digestctx ); \ + digest_update ( (digest), digestctx, (plaintext), \ + (plaintext_len) ); \ + digest_final ( (digest), digestctx, digestout ); \ + \ + ok ( pubkey_init ( (pubkey), ctx, (key), (key_len) ) == 0 ); \ + ok ( pubkey_verify ( (pubkey), ctx, (digest), digestout, \ + (signature), (signature_len) ) != 0 ); \ + pubkey_final ( (pubkey), ctx ); \ + } while ( 0 ) + +#endif /* _PUBKEY_TEST_H */ diff --git a/src/tests/rsa_test.c b/src/tests/rsa_test.c new file mode 100644 index 00000000..a451e38c --- /dev/null +++ b/src/tests/rsa_test.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * RSA self-tests + * + * These test vectors are generated using openssl's genrsa, rsa, + * rsautl, and dgst tools. + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <ipxe/crypto.h> +#include <ipxe/rsa.h> +#include <ipxe/md5.h> +#include <ipxe/sha1.h> +#include <ipxe/sha256.h> +#include <ipxe/test.h> +#include "pubkey_test.h" + +/** Define inline private key data */ +#define PRIVATE(...) { __VA_ARGS__ } + +/** Define inline public key data */ +#define PUBLIC(...) { __VA_ARGS__ } + +/** Define inline plaintext data */ +#define PLAINTEXT(...) { __VA_ARGS__ } + +/** Define inline ciphertext data */ +#define CIPHERTEXT(...) { __VA_ARGS__ } + +/** Define inline signature data */ +#define SIGNATURE(...) { __VA_ARGS__ } + +/** An RSA encryption and decryption self-test */ +struct rsa_encrypt_decrypt_test { + /** Private key */ + const void *private; + /** Private key length */ + size_t private_len; + /** Public key */ + const void *public; + /** Public key length */ + size_t public_len; + /** Plaintext */ + const void *plaintext; + /** Plaintext length */ + size_t plaintext_len; + /** Ciphertext + * + * Note that the encryption process includes some random + * padding, so a given plaintext will encrypt to multiple + * different ciphertexts. + */ + const void *ciphertext; + /** Ciphertext length */ + size_t ciphertext_len; +}; + +/** + * Define an RSA encryption and decryption test + * + * @v name Test name + * @v PRIVATE Private key + * @v PUBLIC Public key + * @v PLAINTEXT Plaintext + * @v CIPHERTEXT Ciphertext + * @ret test Encryption and decryption test + */ +#define RSA_ENCRYPT_DECRYPT_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, \ + CIPHERTEXT ) \ + static const uint8_t name ## _private[] = PRIVATE; \ + static const uint8_t name ## _public[] = PUBLIC; \ + static const uint8_t name ## _plaintext[] = PLAINTEXT; \ + static const uint8_t name ## _ciphertext[] = CIPHERTEXT; \ + static struct rsa_encrypt_decrypt_test name = { \ + .private = name ## _private, \ + .private_len = sizeof ( name ## _private ), \ + .public = name ## _public, \ + .public_len = sizeof ( name ## _public ), \ + .plaintext = name ## _plaintext, \ + .plaintext_len = sizeof ( name ## _plaintext ), \ + .ciphertext = name ## _ciphertext, \ + .ciphertext_len = sizeof ( name ## _ciphertext ), \ + } + +/** An RSA signature self-test */ +struct rsa_signature_test { + /** Private key */ + const void *private; + /** Private key length */ + size_t private_len; + /** Public key */ + const void *public; + /** Public key length */ + size_t public_len; + /** Plaintext */ + const void *plaintext; + /** Plaintext length */ + size_t plaintext_len; + /** Digest algorithm */ + struct digest_algorithm *digest; + /** Signature */ + const void *signature; + /** Signature length */ + size_t signature_len; +}; + +/** + * Define an RSA signature test + * + * @v name Test name + * @v PRIVATE Private key + * @v PUBLIC Public key + * @v PLAINTEXT Plaintext + * @v DIGEST Digest algorithm + * @v SIGNATURE Signature + * @ret test Signature test + */ +#define RSA_SIGNATURE_TEST( name, PRIVATE, PUBLIC, PLAINTEXT, DIGEST, \ + SIGNATURE ) \ + static const uint8_t name ## _private[] = PRIVATE; \ + static const uint8_t name ## _public[] = PUBLIC; \ + static const uint8_t name ## _plaintext[] = PLAINTEXT; \ + static const uint8_t name ## _signature[] = SIGNATURE; \ + static struct rsa_signature_test name = { \ + .private = name ## _private, \ + .private_len = sizeof ( name ## _private ), \ + .public = name ## _public, \ + .public_len = sizeof ( name ## _public ), \ + .plaintext = name ## _plaintext, \ + .plaintext_len = sizeof ( name ## _plaintext ), \ + .digest = DIGEST, \ + .signature = name ## _signature, \ + .signature_len = sizeof ( name ## _signature ), \ + } + +/** + * Report RSA encryption and decryption test result + * + * @v test RSA encryption and decryption test + */ +#define rsa_encrypt_decrypt_ok( test ) do { \ + pubkey_decrypt_ok ( &rsa_algorithm, (test)->private, \ + (test)->private_len, (test)->ciphertext, \ + (test)->ciphertext_len, (test)->plaintext, \ + (test)->plaintext_len ); \ + pubkey_encrypt_ok ( &rsa_algorithm, (test)->private, \ + (test)->private_len, (test)->public, \ + (test)->public_len, (test)->plaintext, \ + (test)->plaintext_len ); \ + pubkey_encrypt_ok ( &rsa_algorithm, (test)->public, \ + (test)->public_len, (test)->private, \ + (test)->private_len, (test)->plaintext, \ + (test)->plaintext_len ); \ + } while ( 0 ) + + +/** + * Report RSA signature test result + * + * @v test RSA signature test + */ +#define rsa_signature_ok( test ) do { \ + uint8_t bad_signature[ (test)->signature_len ]; \ + pubkey_sign_ok ( &rsa_algorithm, (test)->private, \ + (test)->private_len, (test)->digest, \ + (test)->plaintext, (test)->plaintext_len, \ + (test)->signature, (test)->signature_len ); \ + pubkey_verify_ok ( &rsa_algorithm, (test)->public, \ + (test)->public_len, (test)->digest, \ + (test)->plaintext, (test)->plaintext_len, \ + (test)->signature, (test)->signature_len ); \ + memset ( bad_signature, 0, sizeof ( bad_signature ) ); \ + pubkey_verify_fail_ok ( &rsa_algorithm, (test)->public, \ + (test)->public_len, (test)->digest, \ + (test)->plaintext, \ + (test)->plaintext_len, bad_signature, \ + sizeof ( bad_signature ) ); \ + } while ( 0 ) + +/** "Hello world" encryption and decryption test */ +RSA_ENCRYPT_DECRYPT_TEST ( hw_test, + PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xd2, 0xf1, 0x04, 0x67, 0xf6, 0x2c, 0x96, 0x07, 0xa6, 0xbd, + 0x85, 0xac, 0xc1, 0x17, 0x5d, 0xe8, 0xf0, 0x93, 0x94, 0x0c, + 0x45, 0x67, 0x26, 0x67, 0xde, 0x7e, 0xfb, 0xa8, 0xda, 0xbd, + 0x07, 0xdf, 0xcf, 0x45, 0x04, 0x6d, 0xbd, 0x69, 0x8b, 0xfb, + 0xc1, 0x72, 0xc0, 0xfc, 0x03, 0x04, 0xf2, 0x82, 0xc4, 0x7b, + 0x6a, 0x3e, 0xec, 0x53, 0x7a, 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, + 0x1f, 0x2a, 0x13, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x40, 0x49, 0xb8, 0x61, 0xc9, 0xd3, 0x87, 0x11, 0x87, 0xeb, + 0x06, 0x21, 0x49, 0x96, 0xd2, 0x0b, 0xc7, 0xf5, 0x0c, 0x1e, + 0x99, 0x8b, 0x47, 0xd9, 0x6c, 0x43, 0x9e, 0x2d, 0x65, 0x7d, + 0xcc, 0xc2, 0x8b, 0x1a, 0x6f, 0x2b, 0x55, 0xbe, 0xb3, 0x9f, + 0xd1, 0xe2, 0x9a, 0xde, 0x1d, 0xac, 0xec, 0x67, 0xec, 0xa5, + 0xbf, 0x9c, 0x30, 0xd6, 0xf9, 0x0a, 0x1a, 0x48, 0xf3, 0xc2, + 0x93, 0x3a, 0x17, 0x27, 0x21, 0x02, 0x21, 0x00, 0xfc, 0x8d, + 0xfb, 0xee, 0x8a, 0xaa, 0x45, 0x19, 0x4b, 0xf0, 0x68, 0xb0, + 0x02, 0x38, 0x3e, 0x03, 0x6b, 0x24, 0x77, 0x20, 0xbd, 0x5e, + 0x6c, 0x76, 0xdb, 0xc9, 0xe1, 0x43, 0xa3, 0x40, 0x62, 0x6f, + 0x02, 0x21, 0x00, 0xd5, 0xd1, 0xb4, 0x4d, 0x03, 0x40, 0x69, + 0x3f, 0x9a, 0xa7, 0x44, 0x15, 0x28, 0x1e, 0xa5, 0x5f, 0xcf, + 0x97, 0x21, 0x12, 0xb3, 0xe6, 0x1c, 0x9a, 0x8d, 0xb7, 0xb4, + 0x80, 0x3a, 0x9c, 0xb0, 0x43, 0x02, 0x20, 0x71, 0xf0, 0xa0, + 0xab, 0x82, 0xf5, 0xc4, 0x8c, 0xe0, 0x1c, 0xcb, 0x2e, 0x35, + 0x22, 0x28, 0xa0, 0x24, 0x33, 0x64, 0x67, 0x69, 0xe7, 0xf2, + 0xa9, 0x41, 0x09, 0x78, 0x4e, 0xaa, 0x95, 0x3e, 0x93, 0x02, + 0x21, 0x00, 0x85, 0xcc, 0x4d, 0xd9, 0x0b, 0x39, 0xd9, 0x22, + 0x75, 0xf2, 0x49, 0x46, 0x3b, 0xee, 0xc1, 0x69, 0x6d, 0x0b, + 0x93, 0x24, 0x92, 0xf2, 0x61, 0xdf, 0xcc, 0xe2, 0xb1, 0xce, + 0xb3, 0xde, 0xac, 0xe5, 0x02, 0x21, 0x00, 0x9c, 0x23, 0x6a, + 0x95, 0xa6, 0xfe, 0x1e, 0xd8, 0x0c, 0x3f, 0x6e, 0xe6, 0x0a, + 0xeb, 0x97, 0xd6, 0x36, 0x1c, 0x80, 0xc1, 0x02, 0x87, 0x0d, + 0x4d, 0xfe, 0x28, 0x02, 0x1e, 0xde, 0xe1, 0xcc, 0x72 ), + PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, + 0x30, 0x48, 0x02, 0x41, 0x00, 0xd2, 0xf1, 0x04, 0x67, 0xf6, + 0x2c, 0x96, 0x07, 0xa6, 0xbd, 0x85, 0xac, 0xc1, 0x17, 0x5d, + 0xe8, 0xf0, 0x93, 0x94, 0x0c, 0x45, 0x67, 0x26, 0x67, 0xde, + 0x7e, 0xfb, 0xa8, 0xda, 0xbd, 0x07, 0xdf, 0xcf, 0x45, 0x04, + 0x6d, 0xbd, 0x69, 0x8b, 0xfb, 0xc1, 0x72, 0xc0, 0xfc, 0x03, + 0x04, 0xf2, 0x82, 0xc4, 0x7b, 0x6a, 0x3e, 0xec, 0x53, 0x7a, + 0xe3, 0x4e, 0xa8, 0xc9, 0xf9, 0x1f, 0x2a, 0x13, 0x0d, 0x02, + 0x03, 0x01, 0x00, 0x01 ), + PLAINTEXT ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, + 0x64, 0x0a ), + CIPHERTEXT ( 0x39, 0xff, 0x5c, 0x54, 0x65, 0x3e, 0x6a, 0xab, 0xc0, 0x62, + 0x91, 0xb2, 0xbf, 0x1d, 0x73, 0x5b, 0xd5, 0x4c, 0xbd, 0x16, + 0x0f, 0x24, 0xc9, 0xf5, 0xa7, 0xdd, 0x94, 0xd6, 0xf8, 0xae, + 0xd3, 0xa0, 0x9f, 0x4d, 0xff, 0x8d, 0x81, 0x34, 0x47, 0xff, + 0x2a, 0x87, 0x96, 0xd3, 0x17, 0x5d, 0x93, 0x4d, 0x7b, 0x27, + 0x88, 0x4f, 0xec, 0x43, 0x9c, 0xed, 0xb3, 0xf2, 0x19, 0x89, + 0x38, 0x43, 0xf9, 0x41 ) ); + +/** Random message MD5 signature test */ +RSA_SIGNATURE_TEST ( md5_test, + PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xf9, 0x3f, 0x78, 0x44, 0xe2, 0x0e, 0x25, 0xf1, 0x0e, 0x94, + 0xcd, 0xca, 0x6f, 0x9e, 0xea, 0x6d, 0xdf, 0xcd, 0xa0, 0x7c, + 0xe2, 0x21, 0xeb, 0xde, 0xa6, 0x01, 0x4b, 0xb0, 0x76, 0x4b, + 0xd8, 0x8b, 0x19, 0x83, 0xb4, 0xbe, 0x45, 0xde, 0x3d, 0x46, + 0x61, 0x0f, 0x11, 0xe2, 0x2c, 0xf5, 0xb0, 0x63, 0xa0, 0x84, + 0xc0, 0xaf, 0x4e, 0xbe, 0x6a, 0xd3, 0x84, 0x3f, 0xec, 0x42, + 0x17, 0xe9, 0x25, 0xe1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x40, 0x62, 0x7d, 0x93, 0x1f, 0xdd, 0x17, 0xec, 0x24, 0x42, + 0x37, 0xc8, 0xce, 0x0a, 0xa7, 0x88, 0x49, 0x5c, 0x9b, 0x9b, + 0xa4, 0x5d, 0x93, 0x3b, 0xea, 0x62, 0x3c, 0xb6, 0xd5, 0x07, + 0x19, 0xd7, 0x79, 0xf0, 0x3b, 0xab, 0xa3, 0xa5, 0x43, 0x35, + 0x8d, 0x58, 0x40, 0xa0, 0x95, 0xc5, 0x63, 0x28, 0x28, 0xda, + 0x13, 0x28, 0xdf, 0xc9, 0x05, 0xdc, 0x69, 0x46, 0xff, 0x2a, + 0xfb, 0xe4, 0xd1, 0x23, 0xa5, 0x02, 0x21, 0x00, 0xfc, 0xef, + 0x3b, 0x9d, 0x9d, 0x69, 0xf3, 0x66, 0x0a, 0x2b, 0x52, 0xd6, + 0x61, 0x14, 0x90, 0x6e, 0x7d, 0x3c, 0x08, 0x4b, 0x98, 0x44, + 0x00, 0xf2, 0xa4, 0x16, 0x2d, 0xd1, 0xf9, 0xa0, 0x1e, 0x37, + 0x02, 0x21, 0x00, 0xfc, 0x44, 0xcc, 0x7c, 0xc0, 0x26, 0x9a, + 0x0a, 0x6e, 0xda, 0x17, 0x05, 0x7d, 0x66, 0x8d, 0x29, 0x1a, + 0x44, 0xbf, 0x33, 0x76, 0xae, 0x8d, 0xe8, 0xb5, 0xed, 0xb8, + 0x6f, 0xdc, 0xfe, 0x10, 0xa7, 0x02, 0x20, 0x76, 0x48, 0x8a, + 0x60, 0x93, 0x14, 0xd1, 0x36, 0x8e, 0xda, 0xe3, 0xca, 0x4d, + 0x6c, 0x08, 0x7f, 0x23, 0x21, 0xc7, 0xdf, 0x52, 0x3d, 0xbb, + 0x13, 0xbd, 0x98, 0x81, 0xa5, 0x08, 0x4f, 0xd0, 0xd1, 0x02, + 0x21, 0x00, 0xd9, 0xa3, 0x11, 0x37, 0xdf, 0x1e, 0x6e, 0x6e, + 0xe9, 0xcb, 0xc5, 0x68, 0xbb, 0x13, 0x2a, 0x5d, 0x77, 0x88, + 0x2f, 0xdc, 0x5a, 0x5b, 0xa5, 0x9a, 0x4a, 0xba, 0x58, 0x10, + 0x49, 0xfb, 0xf6, 0xa9, 0x02, 0x21, 0x00, 0x89, 0xe8, 0x47, + 0x5b, 0x20, 0x04, 0x3b, 0x0f, 0xb9, 0xe0, 0x1d, 0xab, 0xcf, + 0xe8, 0x72, 0xfd, 0x7d, 0x17, 0x85, 0xc8, 0xd8, 0xbd, 0x1a, + 0x92, 0xe0, 0xbc, 0x7a, 0xc7, 0x31, 0xbe, 0xef, 0xf4 ), + PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, + 0x30, 0x48, 0x02, 0x41, 0x00, 0xf9, 0x3f, 0x78, 0x44, 0xe2, + 0x0e, 0x25, 0xf1, 0x0e, 0x94, 0xcd, 0xca, 0x6f, 0x9e, 0xea, + 0x6d, 0xdf, 0xcd, 0xa0, 0x7c, 0xe2, 0x21, 0xeb, 0xde, 0xa6, + 0x01, 0x4b, 0xb0, 0x76, 0x4b, 0xd8, 0x8b, 0x19, 0x83, 0xb4, + 0xbe, 0x45, 0xde, 0x3d, 0x46, 0x61, 0x0f, 0x11, 0xe2, 0x2c, + 0xf5, 0xb0, 0x63, 0xa0, 0x84, 0xc0, 0xaf, 0x4e, 0xbe, 0x6a, + 0xd3, 0x84, 0x3f, 0xec, 0x42, 0x17, 0xe9, 0x25, 0xe1, 0x02, + 0x03, 0x01, 0x00, 0x01 ), + PLAINTEXT ( 0x9d, 0x5b, 0x46, 0x42, 0x27, 0xc0, 0xf1, 0x4b, 0xe5, 0x9e, + 0xd3, 0x10, 0xa1, 0xeb, 0x16, 0xc3, 0xc6, 0x8f, 0x1a, 0x18, + 0x86, 0xc3, 0x92, 0x15, 0x2d, 0x65, 0xa0, 0x40, 0xe1, 0x3e, + 0x29, 0x79, 0x7c, 0xd4, 0x08, 0xef, 0x53, 0xeb, 0x08, 0x07, + 0x39, 0x21, 0xb3, 0x40, 0xff, 0x4b, 0xc7, 0x76, 0xb9, 0x12, + 0x32, 0x41, 0xcc, 0x5a, 0x86, 0x5c, 0x2e, 0x0b, 0x05, 0xd8, + 0x56, 0xd4, 0xdf, 0x6f, 0x2c, 0xf0, 0xbf, 0x4b, 0x6f, 0x68, + 0xde, 0x39, 0x4a, 0x3e, 0xae, 0x44, 0xb9, 0xc6, 0x24, 0xb3, + 0x83, 0x2e, 0x9f, 0xf5, 0x6d, 0x61, 0xc3, 0x8e, 0xe8, 0x8f, + 0xa6, 0x87, 0x58, 0x3f, 0x36, 0x13, 0xf4, 0x7e, 0xf0, 0x20, + 0x47, 0x87, 0x3f, 0x21, 0x6e, 0x51, 0x3c, 0xf1, 0xef, 0xca, + 0x9f, 0x77, 0x9c, 0x91, 0x4f, 0xd4, 0x56, 0xc0, 0x39, 0x11, + 0xab, 0x15, 0x2c, 0x5e, 0xad, 0x40, 0x09, 0xe6, 0xde, 0xe5, + 0x77, 0x60, 0x19, 0xd4, 0x0d, 0x77, 0x76, 0x24, 0x8b, 0xe6, + 0xdd, 0xa5, 0x8d, 0x4a, 0x55, 0x3a, 0xdf, 0xf8, 0x29, 0xfb, + 0x47, 0x8a, 0xfe, 0x98, 0x34, 0xf6, 0x30, 0x7f, 0x09, 0x03, + 0x26, 0x05, 0xd5, 0x46, 0x18, 0x96, 0xca, 0x96, 0x5b, 0x66, + 0xf2, 0x8d, 0xfc, 0xfc, 0x37, 0xf7, 0xc7, 0x6d, 0x6c, 0xd8, + 0x24, 0x0c, 0x6a, 0xec, 0x82, 0x5c, 0x72, 0xf1, 0xfc, 0x05, + 0xed, 0x8e, 0xe8, 0xd9, 0x8b, 0x8b, 0x67, 0x02, 0x95 ), + &md5_algorithm, + SIGNATURE ( 0xdb, 0x56, 0x3d, 0xea, 0xae, 0x81, 0x4b, 0x3b, 0x2e, 0x8e, + 0xb8, 0xee, 0x13, 0x61, 0xc6, 0xe7, 0xd7, 0x50, 0xcd, 0x0d, + 0x34, 0x3a, 0xfe, 0x9a, 0x8d, 0xf8, 0xfb, 0xd6, 0x7e, 0xbd, + 0xdd, 0xb3, 0xf9, 0xfb, 0xe0, 0xf8, 0xe7, 0x71, 0x03, 0xe6, + 0x55, 0xd5, 0xf4, 0x02, 0x3c, 0xb5, 0xbc, 0x95, 0x2b, 0x66, + 0x56, 0xec, 0x2f, 0x8e, 0xa7, 0xae, 0xd9, 0x80, 0xb3, 0xaa, + 0xac, 0x45, 0x00, 0xa8 ) ); + +/** Random message SHA-1 signature test */ +RSA_SIGNATURE_TEST ( sha1_test, + PRIVATE ( 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xe0, 0x3a, 0x8d, 0x35, 0xe1, 0x92, 0x2f, 0xea, 0x0d, 0x82, + 0x60, 0x2e, 0xb6, 0x0b, 0x02, 0xd3, 0xf4, 0x39, 0xfb, 0x06, + 0x43, 0x8e, 0xa1, 0x7c, 0xc5, 0xae, 0x0d, 0xc7, 0xee, 0x83, + 0xb3, 0x63, 0x20, 0x92, 0x34, 0xe2, 0x94, 0x3d, 0xdd, 0xbb, + 0x6c, 0x64, 0x69, 0x68, 0x25, 0x24, 0x81, 0x4b, 0x4d, 0x48, + 0x5a, 0xd2, 0x29, 0x14, 0xeb, 0x38, 0xdd, 0x3e, 0xb5, 0x57, + 0x45, 0x9b, 0xed, 0x33, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x40, 0x3d, 0xa9, 0x1c, 0x47, 0xe2, 0xdd, 0xf6, 0x7b, 0x20, + 0x77, 0xe7, 0xc7, 0x30, 0x9c, 0x5a, 0x8c, 0xba, 0xae, 0x6f, + 0x0f, 0x4b, 0xe8, 0x9f, 0x13, 0xd6, 0xb0, 0x84, 0x6d, 0xa4, + 0x73, 0x67, 0x12, 0xa9, 0x7c, 0x75, 0xaf, 0x62, 0x92, 0x7b, + 0x80, 0xaf, 0x39, 0x7d, 0x01, 0xb3, 0x43, 0xc8, 0x0d, 0x17, + 0x7f, 0x82, 0x59, 0x46, 0xb8, 0xe5, 0x4e, 0xba, 0x5e, 0x71, + 0x5c, 0xba, 0x62, 0x06, 0x91, 0x02, 0x21, 0x00, 0xf7, 0xaa, + 0xb6, 0x9c, 0xc8, 0xad, 0x68, 0xa8, 0xd7, 0x25, 0xb1, 0xb5, + 0x91, 0xd4, 0xc7, 0xd6, 0x69, 0x51, 0x5d, 0x04, 0xed, 0xd8, + 0xc6, 0xea, 0x69, 0xd2, 0x24, 0xbe, 0x5e, 0x7c, 0x89, 0xa5, + 0x02, 0x21, 0x00, 0xe7, 0xc5, 0xf4, 0x01, 0x35, 0xe0, 0x16, + 0xb5, 0x13, 0x86, 0x14, 0x5a, 0x6a, 0x8d, 0x03, 0x90, 0xae, + 0x7d, 0x3a, 0xc1, 0xfe, 0x8c, 0xa0, 0x4a, 0xb4, 0x94, 0x50, + 0x58, 0xa4, 0xc6, 0x73, 0xf7, 0x02, 0x21, 0x00, 0xe2, 0xda, + 0x16, 0x6c, 0x63, 0x90, 0x1a, 0xc6, 0x54, 0x53, 0x2d, 0x84, + 0x8f, 0x70, 0x24, 0x1f, 0x6b, 0xd6, 0x5f, 0xea, 0x8c, 0xe5, + 0xbb, 0xc5, 0xa9, 0x6a, 0x17, 0xc7, 0xdb, 0x8a, 0x1d, 0x15, + 0x02, 0x21, 0x00, 0xe4, 0x2a, 0x7e, 0xe4, 0x76, 0x2a, 0x2d, + 0x90, 0x83, 0x30, 0xda, 0x76, 0x8c, 0x30, 0x58, 0x13, 0x25, + 0x83, 0x88, 0xc5, 0x93, 0x96, 0xd2, 0xf1, 0xd8, 0x45, 0xad, + 0xb7, 0x26, 0x37, 0x6b, 0xcf, 0x02, 0x20, 0x73, 0x58, 0x1f, + 0x0a, 0xcd, 0x0c, 0x83, 0x27, 0xcc, 0x15, 0xa2, 0x1e, 0x07, + 0x32, 0x1b, 0xa3, 0xc6, 0xa6, 0xb8, 0x83, 0x97, 0x48, 0x45, + 0x50, 0x6c, 0x37, 0x45, 0xa5, 0x54, 0x2a, 0x59, 0x3c ), + PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, + 0x30, 0x48, 0x02, 0x41, 0x00, 0xe0, 0x3a, 0x8d, 0x35, 0xe1, + 0x92, 0x2f, 0xea, 0x0d, 0x82, 0x60, 0x2e, 0xb6, 0x0b, 0x02, + 0xd3, 0xf4, 0x39, 0xfb, 0x06, 0x43, 0x8e, 0xa1, 0x7c, 0xc5, + 0xae, 0x0d, 0xc7, 0xee, 0x83, 0xb3, 0x63, 0x20, 0x92, 0x34, + 0xe2, 0x94, 0x3d, 0xdd, 0xbb, 0x6c, 0x64, 0x69, 0x68, 0x25, + 0x24, 0x81, 0x4b, 0x4d, 0x48, 0x5a, 0xd2, 0x29, 0x14, 0xeb, + 0x38, 0xdd, 0x3e, 0xb5, 0x57, 0x45, 0x9b, 0xed, 0x33, 0x02, + 0x03, 0x01, 0x00, 0x01 ), + PLAINTEXT ( 0xf7, 0x42, 0x01, 0x57, 0x6b, 0x70, 0xcc, 0x4a, 0xdc, 0xed, + 0x12, 0x83, 0x3f, 0xef, 0x27, 0xc1, 0x3c, 0x85, 0xdd, 0x5e, + 0x0a, 0x34, 0x98, 0xf9, 0x21, 0xd3, 0x24, 0x2a, 0x5a, 0xb2, + 0xdf, 0x60, 0x21, 0x28, 0x7c, 0x5b, 0x7a, 0xbe, 0xcb, 0xea, + 0xbc, 0xd6, 0x0e, 0xae, 0x94, 0x64, 0x21, 0xda, 0x28, 0x66, + 0x2f, 0x71, 0x48, 0xe5, 0xea, 0x59, 0x38, 0x28, 0x3e, 0xed, + 0x3b, 0x95, 0x4f, 0x3d, 0x72, 0x2a, 0x00, 0xf3, 0x95, 0x4d, + 0xf0, 0x02, 0x71, 0x63, 0x5a, 0xbc, 0x84, 0xd1, 0x81, 0x3f, + 0x16, 0xcd, 0x28, 0x3d, 0x47, 0xa2, 0xee, 0xa1, 0x2f, 0x84, + 0x8a, 0x22, 0x02, 0x88, 0xd7, 0x83, 0x06, 0x4a, 0x9f, 0xea, + 0x0f, 0x15, 0x48, 0x43, 0x58, 0x6d, 0x39, 0x78, 0x5a, 0x43, + 0x3f, 0xed, 0x6f, 0x68, 0xde, 0x9c, 0xfe, 0xd3, 0x67, 0x74, + 0x08, 0x46, 0x7d, 0x20, 0x22, 0x60, 0x8c, 0x37, 0x35, 0x46, + 0x56, 0x19, 0x3c, 0xfa, 0xa5, 0x40, 0xac, 0x44, 0x90, 0x8a, + 0xa5, 0x80, 0xb2, 0x32, 0xbc, 0xb4, 0x3f, 0x3e, 0x5e, 0xd4, + 0x51, 0xa9, 0x2e, 0xd9, 0x7f, 0x5e, 0x32, 0xb1, 0x24, 0x35, + 0x88, 0x71, 0x3a, 0x01, 0x86, 0x5c, 0xa2, 0xe2, 0x2d, 0x02, + 0x30, 0x91, 0x1c, 0xaa, 0x6c, 0x24, 0x42, 0x1b, 0x1a, 0xba, + 0x30, 0x40, 0x49, 0x83, 0xd9, 0xd7, 0x66, 0x7e, 0x5c, 0x1a, + 0x4b, 0x7f, 0xa6, 0x8e, 0x8a, 0xd6, 0x0c, 0x65, 0x75 ), + &sha1_algorithm, + SIGNATURE ( 0xa5, 0x5a, 0x8a, 0x67, 0x81, 0x76, 0x7e, 0xad, 0x99, 0x22, + 0xf1, 0x47, 0x64, 0xd2, 0xfb, 0x81, 0x45, 0xeb, 0x85, 0x56, + 0xf8, 0x7d, 0xb8, 0xec, 0x41, 0x17, 0x84, 0xf7, 0x2b, 0xbb, + 0x2b, 0x8f, 0xb6, 0xb8, 0x8f, 0xc6, 0xab, 0x39, 0xbc, 0xa3, + 0x72, 0xb3, 0x63, 0x45, 0x5a, 0xe0, 0xac, 0xf8, 0x1c, 0x83, + 0x48, 0x84, 0x89, 0x8a, 0x6b, 0xdf, 0x93, 0xa0, 0xc3, 0x0b, + 0x0e, 0x3d, 0x80, 0x80 ) ); + +/** Random message SHA-256 signature test */ +RSA_SIGNATURE_TEST ( sha256_test, + PRIVATE ( 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, + 0xa5, 0xe9, 0xdb, 0xa9, 0x1a, 0x6e, 0xd6, 0x4c, 0x25, 0x50, + 0xfe, 0x61, 0x77, 0x08, 0x7a, 0x80, 0x36, 0xcb, 0x88, 0x49, + 0x5c, 0xe8, 0xaa, 0x15, 0xf8, 0xb3, 0xd6, 0x78, 0x51, 0x46, + 0x86, 0x3a, 0x5f, 0xd5, 0x9f, 0xab, 0xfe, 0x74, 0x8c, 0x53, + 0x0d, 0xb5, 0x3c, 0x7d, 0x2c, 0x35, 0x88, 0x3f, 0xde, 0xa2, + 0xce, 0x46, 0x94, 0x30, 0xa9, 0x76, 0xee, 0x25, 0xc5, 0x5d, + 0xa6, 0xa6, 0x3a, 0xa5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x40, 0x14, 0x4b, 0xbc, 0x4c, 0x3e, 0x68, 0x8a, 0x9c, 0x7c, + 0x00, 0x21, 0x6e, 0x28, 0xd2, 0x87, 0xb1, 0xc1, 0x82, 0x3a, + 0x64, 0xc7, 0x11, 0xcb, 0x24, 0xae, 0xec, 0xc8, 0xf2, 0xa4, + 0xf6, 0x9c, 0x9a, 0xbb, 0x05, 0x94, 0x80, 0x9b, 0xc1, 0x21, + 0x83, 0x36, 0x23, 0xba, 0x04, 0x20, 0x23, 0x06, 0x48, 0xa7, + 0xa4, 0xe6, 0x31, 0x8e, 0xa1, 0x73, 0xe5, 0x6b, 0x83, 0x4c, + 0x3a, 0xb8, 0xd8, 0x22, 0x61, 0x02, 0x21, 0x00, 0xd4, 0xdf, + 0xcb, 0x21, 0x4a, 0x9a, 0x35, 0x52, 0x02, 0x99, 0xcc, 0x40, + 0x83, 0x65, 0x30, 0x1f, 0x9d, 0x13, 0xd6, 0xd1, 0x79, 0x10, + 0xce, 0x5b, 0xeb, 0x25, 0xa2, 0x39, 0x4e, 0xdf, 0x1c, 0x29, + 0x02, 0x21, 0x00, 0xc7, 0x86, 0x8f, 0xd9, 0x88, 0xe9, 0x98, + 0x4b, 0x5c, 0x50, 0x06, 0x94, 0x05, 0x59, 0x31, 0x25, 0xa7, + 0xa8, 0xe6, 0x95, 0x2b, 0xe3, 0x74, 0x93, 0x51, 0xa8, 0x8e, + 0x3d, 0xe2, 0xe0, 0xfa, 0x1d, 0x02, 0x20, 0x6e, 0xe3, 0x81, + 0x31, 0xff, 0x65, 0xa3, 0x1e, 0xec, 0x61, 0xe7, 0x67, 0x37, + 0xcb, 0x0f, 0x2d, 0x78, 0xaa, 0xab, 0xfd, 0x84, 0x5e, 0x3f, + 0xd0, 0xdc, 0x06, 0x47, 0xa2, 0x28, 0xb6, 0xca, 0x39, 0x02, + 0x20, 0x13, 0x7d, 0x9f, 0x9b, 0xbe, 0x76, 0x23, 0x3c, 0x69, + 0x5e, 0x1f, 0xe6, 0x61, 0xc7, 0x5e, 0xb7, 0xb0, 0xf3, 0x1c, + 0xe3, 0x41, 0x90, 0x4c, 0x98, 0xff, 0x87, 0x19, 0xae, 0x0d, + 0xf5, 0xb0, 0x39, 0x02, 0x21, 0x00, 0xb7, 0xeb, 0xcd, 0x01, + 0x2e, 0x23, 0x42, 0x4f, 0x0c, 0x6f, 0xde, 0xc8, 0x4f, 0xa7, + 0x69, 0x09, 0x12, 0x34, 0xb6, 0x95, 0x4d, 0xb8, 0x7f, 0x16, + 0xd0, 0x48, 0x17, 0x4a, 0x9e, 0x6e, 0x5e, 0xe2 ), + PUBLIC ( 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, + 0x30, 0x48, 0x02, 0x41, 0x00, 0xa5, 0xe9, 0xdb, 0xa9, 0x1a, + 0x6e, 0xd6, 0x4c, 0x25, 0x50, 0xfe, 0x61, 0x77, 0x08, 0x7a, + 0x80, 0x36, 0xcb, 0x88, 0x49, 0x5c, 0xe8, 0xaa, 0x15, 0xf8, + 0xb3, 0xd6, 0x78, 0x51, 0x46, 0x86, 0x3a, 0x5f, 0xd5, 0x9f, + 0xab, 0xfe, 0x74, 0x8c, 0x53, 0x0d, 0xb5, 0x3c, 0x7d, 0x2c, + 0x35, 0x88, 0x3f, 0xde, 0xa2, 0xce, 0x46, 0x94, 0x30, 0xa9, + 0x76, 0xee, 0x25, 0xc5, 0x5d, 0xa6, 0xa6, 0x3a, 0xa5, 0x02, + 0x03, 0x01, 0x00, 0x01 ), + PLAINTEXT ( 0x60, 0xe7, 0xba, 0x9d, 0x5a, 0xe3, 0x2d, 0xfa, 0x5f, 0x47, + 0xdb, 0x93, 0x24, 0x2c, 0xc4, 0xe2, 0x61, 0xf3, 0x89, 0x4d, + 0x67, 0xad, 0xc8, 0xae, 0xf8, 0xe2, 0xfb, 0x52, 0x0f, 0x8d, + 0x18, 0x7e, 0x30, 0xd8, 0x8d, 0x94, 0x07, 0x92, 0x70, 0x91, + 0xaf, 0x3b, 0x92, 0xa6, 0x0f, 0x7a, 0x9b, 0x46, 0x85, 0x8c, + 0x2a, 0x5a, 0x78, 0x5d, 0x1e, 0x13, 0xbf, 0xe6, 0x12, 0xbd, + 0xb1, 0xbb, 0x92, 0x6d, 0x11, 0xed, 0xe1, 0xe4, 0x6e, 0x88, + 0x4d, 0x0b, 0x51, 0xd6, 0xfd, 0x6a, 0xb2, 0x9b, 0xd3, 0xfd, + 0x56, 0xec, 0xd9, 0xd6, 0xb8, 0xc5, 0xfd, 0x0c, 0xf7, 0x55, + 0x5f, 0xc5, 0x6f, 0xbc, 0xbb, 0x78, 0x2f, 0x50, 0x08, 0x65, + 0x0f, 0x12, 0xca, 0x5a, 0xea, 0x52, 0xd0, 0x94, 0x76, 0x17, + 0xe4, 0xba, 0x97, 0xba, 0x11, 0xbf, 0x05, 0x7e, 0xa1, 0xfd, + 0x7d, 0xb5, 0xf1, 0x3a, 0x7e, 0x6f, 0xa1, 0xaa, 0x97, 0x66, + 0x5d, 0x72, 0x76, 0x45, 0x40, 0xb5, 0x22, 0x71, 0x43, 0xe8, + 0x77, 0x76, 0xc8, 0x1b, 0xd2, 0xd1, 0x33, 0x05, 0x64, 0xa9, + 0xc2, 0xa8, 0x40, 0x40, 0x21, 0xdd, 0xcf, 0x07, 0x7e, 0xf2, + 0x4b, 0x80, 0x3d, 0x0f, 0x67, 0xf6, 0xbd, 0xc2, 0xc7, 0xe3, + 0x91, 0x71, 0xd6, 0x2d, 0xa1, 0xae, 0x81, 0x0c, 0xed, 0x54, + 0x48, 0x79, 0x8a, 0x78, 0x05, 0x74, 0x4d, 0x4f, 0xf0, 0xe0, + 0x3c, 0x41, 0x5c, 0x04, 0x0b, 0x68, 0x57, 0xc5, 0xd6 ), + &sha256_algorithm, + SIGNATURE ( 0x02, 0x2e, 0xc5, 0x2a, 0x2b, 0x7f, 0xb4, 0x80, 0xca, 0x9d, + 0x96, 0x5b, 0xaf, 0x1f, 0x72, 0x5b, 0x6e, 0xf1, 0x69, 0x7f, + 0x4d, 0x41, 0xd5, 0x9f, 0x00, 0xdc, 0x47, 0xf4, 0x68, 0x8f, + 0xda, 0xfc, 0xd1, 0x23, 0x96, 0x11, 0x1d, 0xc0, 0x1b, 0x1d, + 0x36, 0x66, 0x2a, 0xf9, 0x21, 0x51, 0xcb, 0xb9, 0x7d, 0x24, + 0x7d, 0x38, 0x37, 0xc4, 0xea, 0xdd, 0x3a, 0x6f, 0xa8, 0x65, + 0x60, 0x73, 0x77, 0x3c ) ); + +/** + * Perform RSA self-tests + * + */ +static void rsa_test_exec ( void ) { + + rsa_encrypt_decrypt_ok ( &hw_test ); + rsa_signature_ok ( &md5_test ); + rsa_signature_ok ( &sha1_test ); + rsa_signature_ok ( &sha256_test ); +} + +/** RSA self-test */ +struct self_test rsa_test __self_test = { + .name = "rsa", + .exec = rsa_test_exec, +}; diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c new file mode 100644 index 00000000..ac4abee4 --- /dev/null +++ b/src/tests/settings_test.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Settings self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <string.h> +#include <ipxe/settings.h> +#include <ipxe/test.h> + +/** Define inline raw data */ +#define RAW(...) { __VA_ARGS__ } + +/** + * Report a formatted-store test result + * + * @v settings Settings block + * @v setting Setting + * @v formatted Formatted value + * @v raw_array Expected raw value + */ +#define storef_ok( settings, setting, formatted, raw_array ) do { \ + const uint8_t expected[] = raw_array; \ + uint8_t actual[ sizeof ( expected ) ]; \ + int len; \ + \ + ok ( storef_setting ( settings, setting, formatted ) == 0 ); \ + len = fetch_setting ( settings, setting, actual, \ + sizeof ( actual ) ); \ + DBGC ( settings, "Stored %s \"%s\", got:\n", \ + (setting)->type->name, formatted ); \ + DBGC_HDA ( settings, 0, actual, len ); \ + ok ( len == ( int ) sizeof ( actual ) ); \ + ok ( memcmp ( actual, expected, sizeof ( actual ) ) == 0 ); \ + } while ( 0 ) + +/** + * Report a formatted-fetch test result + * + * @v settings Settings block + * @v setting Setting + * @v raw_array Raw value + * @v formatted Expected formatted value + */ +#define fetchf_ok( settings, setting, raw_array, formatted ) do { \ + const uint8_t raw[] = raw_array; \ + char actual[ strlen ( formatted ) + 1 ]; \ + int len; \ + \ + ok ( store_setting ( settings, setting, raw, \ + sizeof ( raw ) ) == 0 ); \ + len = fetchf_setting ( settings, setting, actual, \ + sizeof ( actual ) ); \ + DBGC ( settings, "Fetched %s \"%s\" from:\n", \ + (setting)->type->name, formatted ); \ + DBGC_HDA ( settings, 0, raw, sizeof ( raw ) ); \ + ok ( len == ( int ) ( sizeof ( actual ) - 1 ) ); \ + ok ( strcmp ( actual, formatted ) == 0 ); \ + } while ( 0 ) + +/** Test generic settings block */ +struct generic_settings test_generic_settings = { + .settings = { + .refcnt = NULL, + .siblings = + LIST_HEAD_INIT ( test_generic_settings.settings.siblings ), + .children = + LIST_HEAD_INIT ( test_generic_settings.settings.children ), + .op = &generic_settings_operations, + }, + .list = LIST_HEAD_INIT ( test_generic_settings.list ), +}; + +/** Test settings block */ +#define test_settings test_generic_settings.settings + +/** Test string setting */ +static struct setting test_string_setting = { + .name = "test_string", + .type = &setting_type_string, +}; + +/** Test URI-encoded string setting */ +static struct setting test_uristring_setting = { + .name = "test_uristring", + .type = &setting_type_uristring, +}; + +/** Test IPv4 address setting type */ +static struct setting test_ipv4_setting = { + .name = "test_ipv4", + .type = &setting_type_ipv4, +}; + +/** Test signed 8-bit integer setting type */ +static struct setting test_int8_setting = { + .name = "test_int8", + .type = &setting_type_int8, +}; + +/** Test signed 16-bit integer setting type */ +static struct setting test_int16_setting = { + .name = "test_int16", + .type = &setting_type_int16, +}; + +/** Test signed 32-bit integer setting type */ +static struct setting test_int32_setting = { + .name = "test_int32", + .type = &setting_type_int32, +}; + +/** Test unsigned 8-bit integer setting type */ +static struct setting test_uint8_setting = { + .name = "test_uint8", + .type = &setting_type_uint8, +}; + +/** Test unsigned 16-bit integer setting type */ +static struct setting test_uint16_setting = { + .name = "test_uint16", + .type = &setting_type_uint16, +}; + +/** Test unsigned 32-bit integer setting type */ +static struct setting test_uint32_setting = { + .name = "test_uint32", + .type = &setting_type_uint32, +}; + +/** Test colon-separated hex string setting type */ +static struct setting test_hex_setting = { + .name = "test_hex", + .type = &setting_type_hex, +}; + +/** Test hyphen-separated hex string setting type */ +static struct setting test_hexhyp_setting = { + .name = "test_hexhyp", + .type = &setting_type_hexhyp, +}; + +/** Test UUID setting type */ +static struct setting test_uuid_setting = { + .name = "test_uuid", + .type = &setting_type_uuid, +}; + +/** + * Perform settings self-tests + * + */ +static void settings_test_exec ( void ) { + + /* Register test settings block */ + ok ( register_settings ( &test_settings, NULL, "test" ) == 0 ); + + /* "string" setting type */ + storef_ok ( &test_settings, &test_string_setting, "hello", + RAW ( 'h', 'e', 'l', 'l', 'o' ) ); + fetchf_ok ( &test_settings, &test_string_setting, + RAW ( 'w', 'o', 'r', 'l', 'd' ), "world" ); + + /* "uristring" setting type */ + storef_ok ( &test_settings, &test_uristring_setting, "hello%20world", + RAW ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', + 'd' ) ); + fetchf_ok ( &test_settings, &test_uristring_setting, + RAW ( 1, 2, 3, 4, 5 ), "%01%02%03%04%05" ); + + /* "ipv4" setting type */ + storef_ok ( &test_settings, &test_ipv4_setting, "192.168.0.1", + RAW ( 192, 168, 0, 1 ) ); + fetchf_ok ( &test_settings, &test_ipv4_setting, + RAW ( 212, 13, 204, 60 ), "212.13.204.60" ); + + /* Integer setting types */ + storef_ok ( &test_settings, &test_int8_setting, + "54", RAW ( 54 ) ); + storef_ok ( &test_settings, &test_int8_setting, + "0x7f", RAW ( 0x7f ) ); + storef_ok ( &test_settings, &test_int8_setting, + "0x1234", RAW ( 0x34 ) ); + storef_ok ( &test_settings, &test_int8_setting, + "-32", RAW ( -32 ) ); + fetchf_ok ( &test_settings, &test_int8_setting, + RAW ( -9 ), "-9" ); + fetchf_ok ( &test_settings, &test_int8_setting, + RAW ( 106 ), "106" ); + storef_ok ( &test_settings, &test_uint8_setting, + "129", RAW ( 129 ) ); + storef_ok ( &test_settings, &test_uint8_setting, + "0x3421", RAW ( 0x21 ) ); + fetchf_ok ( &test_settings, &test_uint8_setting, + RAW ( 0x54 ), "0x54" ); + storef_ok ( &test_settings, &test_int16_setting, + "29483", RAW ( 0x73, 0x2b ) ); + fetchf_ok ( &test_settings, &test_int16_setting, + RAW ( 0x82, 0x14 ), "-32236" ); + fetchf_ok ( &test_settings, &test_int16_setting, + RAW ( 0x12, 0x78 ), "4728" ); + storef_ok ( &test_settings, &test_uint16_setting, + "48727", RAW ( 0xbe, 0x57 ) ); + fetchf_ok ( &test_settings, &test_uint16_setting, + RAW ( 0x9a, 0x24 ), "0x9a24" ); + storef_ok ( &test_settings, &test_int32_setting, + "2901274", RAW ( 0x00, 0x2c, 0x45, 0x1a ) ); + fetchf_ok ( &test_settings, &test_int32_setting, + RAW ( 0xff, 0x34, 0x2d, 0xaf ), "-13357649" ); + fetchf_ok ( &test_settings, &test_int32_setting, + RAW ( 0x01, 0x00, 0x34, 0xab ), "16790699" ); + storef_ok ( &test_settings, &test_uint32_setting, + "0xb598d21", RAW ( 0x0b, 0x59, 0x8d, 0x21 ) ); + fetchf_ok ( &test_settings, &test_uint32_setting, + RAW ( 0xf2, 0x37, 0xb2, 0x18 ), "0xf237b218" ); + + /* "hex" setting type */ + storef_ok ( &test_settings, &test_hex_setting, + "", RAW ( 0x00 ) ); + storef_ok ( &test_settings, &test_hex_setting, + ":", RAW ( 0x00, 0x00 ) ); + storef_ok ( &test_settings, &test_hex_setting, + "1:2:", RAW ( 0x01, 0x02, 0x00 ) ); + storef_ok ( &test_settings, &test_hex_setting, + "08:12:f5:22:90:1b:4b:47:a8:30:cb:4d:67:4c:d6:76", + RAW ( 0x08, 0x12, 0xf5, 0x22, 0x90, 0x1b, 0x4b, 0x47, 0xa8, + 0x30, 0xcb, 0x4d, 0x67, 0x4c, 0xd6, 0x76 ) ); + fetchf_ok ( &test_settings, &test_hex_setting, + RAW ( 0x62, 0xd9, 0xd4, 0xc4, 0x7e, 0x3b, 0x41, 0x46, 0x91, + 0xc6, 0xfd, 0x0c, 0xbf ), + "62:d9:d4:c4:7e:3b:41:46:91:c6:fd:0c:bf" ); + + /* "hexhyp" setting type */ + storef_ok ( &test_settings, &test_hexhyp_setting, + "11-33-22", RAW ( 0x11, 0x33, 0x22 ) ); + fetchf_ok ( &test_settings, &test_hexhyp_setting, + RAW ( 0x9f, 0xe5, 0x6d, 0xfb, 0x24, 0x3a, 0x4c, 0xbb, 0xa9, + 0x09, 0x6c, 0x66, 0x13, 0xc1, 0xa8, 0xec, 0x27 ), + "9f-e5-6d-fb-24-3a-4c-bb-a9-09-6c-66-13-c1-a8-ec-27" ); + + /* "uuid" setting type (no store capability) */ + fetchf_ok ( &test_settings, &test_uuid_setting, + RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8, + 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ), + "1a6a749d-0eda-461a-a87a-7cfe4fca4a57" ); + + /* Clear and unregister test settings block */ + clear_settings ( &test_settings ); + unregister_settings ( &test_settings ); +} + +/** Settings self-test */ +struct self_test settings_test __self_test = { + .name = "settings", + .exec = settings_test_exec, +}; diff --git a/src/tests/sha256_test.c b/src/tests/sha256_test.c new file mode 100644 index 00000000..7599ba5d --- /dev/null +++ b/src/tests/sha256_test.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * SHA-256 tests + * + */ + +#include <stdint.h> +#include <ipxe/sha256.h> +#include <ipxe/test.h> +#include "digest_test.h" + +/** An SHA-256 test vector */ +struct sha256_test_vector { + /** Test data */ + void *data; + /** Test data length */ + size_t len; + /** Expected digest */ + uint8_t digest[SHA256_DIGEST_SIZE]; +}; + +/** SHA-256 test vectors */ +static struct sha256_test_vector sha256_test_vectors[] = { + /* Empty test data + * + * Expected digest value obtained from "sha256sum /dev/null" + */ + { NULL, 0, + { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, + 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, + 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 } }, + /* Test data and expected digests taken from the NIST + * Cryptographic Toolkit Algorithm Examples at + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf + */ + { "abc", 3, + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, + 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, + 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, + 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, + 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, +}; + +/** SHA-256 test fragment lists */ +static struct digest_test_fragments sha256_test_fragments[] = { + { { 0, -1UL, } }, + { { 1, 1, 1, 1, 1, 1, 1, 1 } }, + { { 2, 0, 23, 4, 6, 1, 0 } }, +}; + +/** + * Perform SHA-256 self-test + * + */ +static void sha256_test_exec ( void ) { + struct digest_algorithm *digest = &sha256_algorithm; + struct sha256_test_vector *test; + unsigned int i; + unsigned int j; + + for ( i = 0 ; i < ( sizeof ( sha256_test_vectors ) / + sizeof ( sha256_test_vectors[0] ) ) ; i++ ) { + test = &sha256_test_vectors[i]; + /* Test with a single pass */ + digest_ok ( digest, NULL, test->data, test->len, test->digest ); + /* Test with fragment lists */ + for ( j = 0 ; j < ( sizeof ( sha256_test_fragments ) / + sizeof ( sha256_test_fragments[0] )); j++ ){ + digest_ok ( digest, &sha256_test_fragments[j], + test->data, test->len, test->digest ); + } + } +} + +/** SHA-256 self-test */ +struct self_test sha256_test __self_test = { + .name = "sha256", + .exec = sha256_test_exec, +}; diff --git a/src/tests/test.c b/src/tests/test.c index b5cc8506..11dd2f5e 100644 --- a/src/tests/test.c +++ b/src/tests/test.c @@ -29,9 +29,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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; @@ -100,8 +102,9 @@ static void run_tests ( struct self_test *tests ) { /** * Run all self-tests * + * @ret rc Return status code */ -static void test_init ( void ) { +static int run_all_tests ( void ) { struct self_test *tests; unsigned int failures = 0; unsigned int assertions = 0; @@ -125,20 +128,46 @@ static void test_init ( void ) { printf ( " with %d assertion failures", assertions ); } printf ( "\n" ); + return -EINPROGRESS; } else { printf ( "OK: all %d tests passed\n", total ); + return 0; } +} - /* Lock system */ - while ( 1 ) {} +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_NORMAL ) = { +struct init_fn test_init_fn __init_fn ( INIT_EARLY ) = { .initialise = test_init, }; - -/* Drag in all applicable self-tests */ -REQUIRE_OBJECT ( list_test ); -REQUIRE_OBJECT ( sha1_test ); -REQUIRE_OBJECT ( hmac_drbg_test ); diff --git a/src/tests/tests.c b/src/tests/tests.c new file mode 100644 index 00000000..cfecff6e --- /dev/null +++ b/src/tests/tests.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Self-test collection + * + */ + +/* Drag in all applicable self-tests */ +REQUIRE_OBJECT ( list_test ); +REQUIRE_OBJECT ( byteswap_test ); +REQUIRE_OBJECT ( settings_test ); +REQUIRE_OBJECT ( time_test ); +REQUIRE_OBJECT ( crc32_test ); +REQUIRE_OBJECT ( md5_test ); +REQUIRE_OBJECT ( sha1_test ); +REQUIRE_OBJECT ( sha256_test ); +REQUIRE_OBJECT ( aes_cbc_test ); +REQUIRE_OBJECT ( hmac_drbg_test ); +REQUIRE_OBJECT ( hash_df_test ); +REQUIRE_OBJECT ( bigint_test ); +REQUIRE_OBJECT ( rsa_test ); +REQUIRE_OBJECT ( x509_test ); +REQUIRE_OBJECT ( cms_test ); diff --git a/src/tests/time_test.c b/src/tests/time_test.c new file mode 100644 index 00000000..d12d3acf --- /dev/null +++ b/src/tests/time_test.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Date and time self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <time.h> +#include <ipxe/test.h> + +/** A mktime() test */ +struct mktime_test { + /** Broken-down time */ + struct tm tm; + /** Day of the week */ + int wday; + /** Day of the year */ + int yday; + /** Seconds since the Epoch */ + time_t time; +}; + +/** + * Define a mktime() test + * + * @v name Test name + * @v SEC Seconds [0,60] + * @v MIN Minutes [0,59] + * @v HOUR Hour [0,23] + * @v MDAY Day of month [1,31] + * @v MON Month of year [0,11] + * @v YEAR Years since 1900 + * @v WDAY Day of week [0,6] (Sunday=0) + * @v YDAY Day of year [0,365] + * @v ISDST Daylight savings flag (ignored) + * @v TIME Seconds since the Epoch + * @ret test mktime() test + * + * This macro is designed to make it easy to generate test vectors in + * Perl using + * + * print join ", ", gmtime ( $time ), $time."ULL"; + * + */ +#define MKTIME_TEST( name, SEC, MIN, HOUR, MDAY, MON, YEAR, WDAY, \ + YDAY, ISDST, TIME ) \ + static struct mktime_test name = { \ + .tm = { \ + .tm_sec = SEC, \ + .tm_min = MIN, \ + .tm_hour = HOUR, \ + .tm_mday = MDAY, \ + .tm_mon = MON, \ + .tm_year = YEAR, \ + .tm_isdst = ISDST, \ + }, \ + .wday = WDAY, \ + .yday = YDAY, \ + .time = TIME, \ + } + +/** + * Report mktime() test result + * + * @v test mktime() test + */ +#define mktime_ok( test ) do { \ + time_t time = mktime ( &(test)->tm ); \ + ok ( time == (test)->time ); \ + ok ( (test)->tm.tm_wday == (test)->wday ); \ + ok ( (test)->tm.tm_yday == (test)->yday ); \ + } while ( 0 ) + +/* Start of the Epoch */ +MKTIME_TEST ( mktime_epoch, 00, 00, 00, 01, 00, 70, 4, 0, 0, 0 ); + +/* Birth of iPXE as a new project */ +MKTIME_TEST ( mktime_ipxe, 01, 15, 20, 19, 03, 110, 1, 108, 0, 1271708101ULL ); + +/* Random test vectors generated using Perl's gmtime() */ +MKTIME_TEST ( mktime_0, 4, 17, 20, 1, 0, 150, 6, 0, 0, 2524681024ULL ); +MKTIME_TEST ( mktime_1, 22, 47, 21, 27, 11, 77, 2, 360, 0, 252107242ULL ); +MKTIME_TEST ( mktime_2, 26, 10, 0, 7, 2, 196, 3, 66, 0, 3981917426ULL ); +MKTIME_TEST ( mktime_3, 44, 44, 23, 15, 9, 261, 4, 287, 0, 6052319084ULL ); +MKTIME_TEST ( mktime_4, 3, 22, 18, 8, 9, 296, 6, 281, 0, 7156232523ULL ); +MKTIME_TEST ( mktime_5, 27, 26, 16, 18, 11, 338, 2, 351, 0, 8487649587ULL ); +MKTIME_TEST ( mktime_6, 31, 36, 22, 3, 3, 293, 3, 92, 0, 7045310191ULL ); +MKTIME_TEST ( mktime_7, 2, 0, 6, 25, 5, 289, 4, 175, 0, 6926191202ULL ); +MKTIME_TEST ( mktime_8, 43, 50, 1, 8, 0, 210, 3, 7, 0, 4418589043ULL ); +MKTIME_TEST ( mktime_9, 48, 14, 20, 23, 3, 86, 3, 112, 0, 514671288ULL ); +MKTIME_TEST ( mktime_10, 4, 43, 5, 29, 11, 173, 5, 362, 0, 3281751784ULL ); +MKTIME_TEST ( mktime_11, 47, 26, 21, 12, 7, 177, 4, 223, 0, 3396029207ULL ); +MKTIME_TEST ( mktime_12, 18, 55, 20, 26, 11, 88, 1, 360, 0, 599172918ULL ); +MKTIME_TEST ( mktime_13, 8, 32, 13, 15, 7, 314, 1, 226, 0, 7719456728ULL ); +MKTIME_TEST ( mktime_14, 0, 16, 11, 20, 6, 138, 2, 200, 0, 2163237360ULL ); +MKTIME_TEST ( mktime_15, 48, 0, 9, 31, 2, 202, 5, 89, 0, 4173238848ULL ); +MKTIME_TEST ( mktime_16, 51, 55, 0, 15, 1, 323, 6, 45, 0, 7987769751ULL ); +MKTIME_TEST ( mktime_17, 36, 10, 7, 11, 5, 301, 4, 161, 0, 7303590636ULL ); +MKTIME_TEST ( mktime_18, 22, 39, 11, 21, 9, 233, 3, 293, 0, 5169181162ULL ); +MKTIME_TEST ( mktime_19, 48, 29, 8, 31, 7, 207, 3, 242, 0, 4344222588ULL ); +MKTIME_TEST ( mktime_20, 4, 53, 22, 8, 8, 165, 2, 250, 0, 3019675984ULL ); +MKTIME_TEST ( mktime_21, 14, 16, 8, 10, 5, 298, 0, 160, 0, 7208900174ULL ); +MKTIME_TEST ( mktime_22, 10, 35, 3, 12, 3, 188, 1, 102, 0, 3732579310ULL ); +MKTIME_TEST ( mktime_23, 47, 12, 18, 22, 2, 103, 6, 80, 0, 1048356767ULL ); +MKTIME_TEST ( mktime_24, 23, 29, 17, 23, 10, 201, 3, 326, 0, 4162210163ULL ); +MKTIME_TEST ( mktime_25, 58, 35, 23, 24, 3, 111, 0, 113, 0, 1303688158ULL ); +MKTIME_TEST ( mktime_26, 34, 56, 15, 24, 11, 154, 4, 357, 0, 2681740594ULL ); +MKTIME_TEST ( mktime_27, 7, 11, 22, 28, 1, 243, 4, 58, 0, 5464447867ULL ); +MKTIME_TEST ( mktime_28, 25, 45, 23, 29, 11, 90, 6, 362, 0, 662514325ULL ); +MKTIME_TEST ( mktime_29, 31, 20, 12, 24, 1, 146, 6, 54, 0, 2403087631ULL ); +MKTIME_TEST ( mktime_30, 49, 7, 18, 16, 10, 271, 6, 319, 0, 6370596469ULL ); +MKTIME_TEST ( mktime_31, 31, 55, 2, 25, 5, 141, 2, 175, 0, 2255741731ULL ); + +/** + * Perform date and time self-tests + * + */ +static void time_test_exec ( void ) { + + mktime_ok ( &mktime_epoch ); + mktime_ok ( &mktime_ipxe ); + mktime_ok ( &mktime_0 ); + mktime_ok ( &mktime_1 ); + mktime_ok ( &mktime_2 ); + mktime_ok ( &mktime_3 ); + mktime_ok ( &mktime_4 ); + mktime_ok ( &mktime_5 ); + mktime_ok ( &mktime_6 ); + mktime_ok ( &mktime_7 ); + mktime_ok ( &mktime_8 ); + mktime_ok ( &mktime_9 ); + mktime_ok ( &mktime_10 ); + mktime_ok ( &mktime_11 ); + mktime_ok ( &mktime_12 ); + mktime_ok ( &mktime_13 ); + mktime_ok ( &mktime_14 ); + mktime_ok ( &mktime_15 ); + mktime_ok ( &mktime_16 ); + mktime_ok ( &mktime_17 ); + mktime_ok ( &mktime_18 ); + mktime_ok ( &mktime_19 ); + mktime_ok ( &mktime_20 ); + mktime_ok ( &mktime_21 ); + mktime_ok ( &mktime_22 ); + mktime_ok ( &mktime_23 ); + mktime_ok ( &mktime_24 ); + mktime_ok ( &mktime_25 ); + mktime_ok ( &mktime_26 ); + mktime_ok ( &mktime_27 ); + mktime_ok ( &mktime_28 ); + mktime_ok ( &mktime_29 ); + mktime_ok ( &mktime_30 ); + mktime_ok ( &mktime_31 ); +} + +/** Date and time self-test */ +struct self_test time_test __self_test = { + .name = "time", + .exec = time_test_exec, +}; diff --git a/src/tests/x509_test.c b/src/tests/x509_test.c new file mode 100644 index 00000000..3a3c9d00 --- /dev/null +++ b/src/tests/x509_test.c @@ -0,0 +1,947 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * X.509 self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <ipxe/x509.h> +#include <ipxe/asn1.h> +#include <ipxe/sha256.h> +#include <ipxe/test.h> + +/** Fingerprint algorithm used for X.509 test certificates */ +#define x509_test_algorithm sha256_algorithm + +/** An X.509 test certificate */ +struct x509_test_certificate { + /** Data */ + const void *data; + /** Length of data */ + size_t len; + /** Fingerprint */ + const void *fingerprint; + + /** Parsed certificate */ + struct x509_certificate *cert; +}; + +/** An X.509 test certificate chain */ +struct x509_test_chain { + /** Test certificates */ + struct x509_test_certificate **certs; + /** Number of certificates */ + unsigned int count; + + /** Parsed certificate chain */ + struct x509_chain *chain; +}; + +/** Define inline certificate data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define inline fingerprint data */ +#define FINGERPRINT(...) { __VA_ARGS__ } + +/** Define a test certificate */ +#define CERTIFICATE( name, DATA, FINGERPRINT ) \ + static const uint8_t name ## _data[] = DATA; \ + static const uint8_t name ## _fingerprint[] = FINGERPRINT; \ + static struct x509_test_certificate name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + .fingerprint = name ## _fingerprint, \ + } + +/** Define a test certificate chain */ +#define CHAIN( name, ... ) \ + static struct x509_test_certificate * name ## _certs[] = \ + { __VA_ARGS__ }; \ + static struct x509_test_chain name = { \ + .certs = name ## _certs, \ + .count = ( sizeof ( name ## _certs ) / \ + sizeof ( name ## _certs[0] ) ), \ + } + +/* + * subject iPXE self-test root CA + * issuer iPXE self-test root CA + */ +CERTIFICATE ( root_crt, + DATA ( 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xc6, 0xb8, 0x9c, 0x58, + 0xd2, 0xdc, 0xc9, 0x5d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, + 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, + 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, + 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, + 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x30, + 0x38, 0x30, 0x38, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, + 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, + 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, + 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, + 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaa, 0x72, + 0xb5, 0xc1, 0x73, 0xf4, 0x95, 0x76, 0xa4, 0x27, 0xab, 0x5e, + 0xeb, 0x1d, 0x9d, 0xd0, 0x04, 0xb2, 0x93, 0x05, 0xc7, 0xfa, + 0x75, 0x84, 0x66, 0xe6, 0x3a, 0x26, 0x1f, 0xbc, 0x2d, 0xfd, + 0x8f, 0x59, 0x64, 0xac, 0xcf, 0x65, 0x9d, 0x82, 0x23, 0xc3, + 0x72, 0x93, 0xf2, 0x40, 0x68, 0x32, 0xd1, 0xb8, 0xf1, 0x47, + 0x61, 0x50, 0xea, 0xbc, 0xcc, 0x3c, 0x6b, 0x74, 0x7a, 0xec, + 0x2b, 0x75, 0xa6, 0xc2, 0xa2, 0xb8, 0xbf, 0x23, 0x48, 0x97, + 0xd5, 0xaf, 0x77, 0xc1, 0x92, 0x88, 0xd7, 0x38, 0xb7, 0x9e, + 0xda, 0xee, 0x72, 0x04, 0xcb, 0x96, 0xe5, 0xdb, 0xfd, 0x9b, + 0x5d, 0x99, 0x4e, 0x7a, 0x60, 0x23, 0x34, 0xa4, 0x8d, 0xd7, + 0x6c, 0xe7, 0x5d, 0x93, 0x97, 0xe1, 0xab, 0x36, 0x2c, 0x24, + 0x16, 0x92, 0x66, 0xf6, 0x6a, 0x14, 0x23, 0x1d, 0x18, 0xb9, + 0x44, 0x24, 0x61, 0x6b, 0xd3, 0x75, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x94, 0x9e, 0xea, + 0x17, 0x8d, 0x27, 0xa9, 0x17, 0xe5, 0xa9, 0x19, 0xbe, 0x82, + 0x36, 0xbd, 0xac, 0x74, 0xf3, 0x6e, 0x75, 0x71, 0x30, 0x1c, + 0x05, 0x80, 0x6d, 0x1a, 0x69, 0x37, 0x86, 0x9c, 0x77, 0x75, + 0x29, 0xa1, 0xc6, 0xb7, 0x11, 0x0a, 0x63, 0x27, 0xee, 0xb1, + 0xc8, 0x94, 0xa9, 0x2e, 0x56, 0x8f, 0xca, 0x9d, 0xbe, 0xf4, + 0xdb, 0x63, 0x97, 0x68, 0x3b, 0x13, 0xf8, 0x6a, 0xa5, 0xd1, + 0x3d, 0xed, 0xbb, 0x86, 0x9d, 0x42, 0xfc, 0x15, 0x0a, 0x04, + 0xf8, 0x3c, 0x0e, 0xc4, 0x86, 0x05, 0x57, 0x56, 0x96, 0xf6, + 0xc0, 0x18, 0x53, 0xb0, 0xc5, 0xf0, 0xca, 0x72, 0x77, 0x77, + 0xc9, 0x8e, 0x90, 0xa5, 0x4b, 0xb6, 0x80, 0x4a, 0x4c, 0x34, + 0x6f, 0xc9, 0xe8, 0x6f, 0xc2, 0x28, 0xdf, 0x93, 0xa9, 0xf5, + 0x63, 0x18, 0xc0, 0xec, 0x9e, 0xd5, 0x19, 0x36, 0xc5, 0x94, + 0x10, 0xd4, 0x72, 0xd2, 0xb8 ), + FINGERPRINT ( 0x71, 0x5d, 0x51, 0x37, 0x5e, 0x18, 0xb3, 0xbc, + 0xbb, 0x30, 0x0e, 0x8f, 0x50, 0xc7, 0x55, 0xf5, + 0x96, 0xe7, 0xa8, 0x6d, 0x63, 0x2d, 0x32, 0x38, + 0xaf, 0x00, 0xc4, 0x1a, 0xfc, 0xd8, 0xac, 0xc3 ) ); + +/* + * subject iPXE self-test intermediate CA + * issuer iPXE self-test root CA + */ +CERTIFICATE ( intermediate_crt, + DATA ( 0x30, 0x82, 0x02, 0xb3, 0x30, 0x82, 0x02, 0x1c, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, + 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, + 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, + 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, + 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x33, 0x5a, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, + 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, + 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27, + 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69, + 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, + 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, + 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x3a, + 0xee, 0xc6, 0x3c, 0xac, 0x4d, 0x81, 0xc6, 0x98, 0x5e, 0xe1, + 0x48, 0x66, 0x1a, 0x1e, 0x60, 0x19, 0x41, 0xae, 0xca, 0x14, + 0x97, 0xc8, 0x3a, 0x50, 0xb6, 0x48, 0xf5, 0x42, 0xac, 0x0f, + 0xe1, 0xe3, 0x47, 0xf0, 0xbf, 0x7c, 0xd0, 0xee, 0x8f, 0xb7, + 0xa6, 0x19, 0xad, 0xbb, 0xc5, 0x1b, 0x34, 0x38, 0xc8, 0xbd, + 0x55, 0x84, 0x93, 0x72, 0xaf, 0x84, 0xfc, 0x9b, 0x97, 0x1d, + 0xb5, 0x54, 0x24, 0xd6, 0x5d, 0xb7, 0x31, 0xf4, 0xbd, 0x3b, + 0x40, 0x97, 0xc0, 0xa9, 0x5a, 0x2a, 0xcb, 0x6b, 0x98, 0x07, + 0xdb, 0xb5, 0x9f, 0xe8, 0x31, 0x3f, 0x01, 0x46, 0x46, 0x70, + 0x05, 0xa2, 0x0f, 0x8c, 0x7a, 0x61, 0xf3, 0xdf, 0xdb, 0xa1, + 0x37, 0x2c, 0x88, 0x6a, 0x81, 0x21, 0x12, 0x4c, 0xf5, 0xcd, + 0xaf, 0xc9, 0xd2, 0x36, 0x3d, 0x82, 0xd1, 0xca, 0x19, 0xaf, + 0x4e, 0xae, 0x50, 0x71, 0x44, 0xbf, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x5d, 0x3c, 0xb3, + 0x52, 0x19, 0xa6, 0x9e, 0x4a, 0x44, 0x98, 0xbf, 0x51, 0x20, + 0x47, 0x0a, 0xf3, 0x26, 0x1a, 0xcc, 0x35, 0x2f, 0xc9, 0xed, + 0xe0, 0x9d, 0x46, 0xeb, 0xbc, 0x7e, 0xc9, 0xb9, 0x1d, 0x76, + 0xa4, 0x1d, 0xc2, 0xd9, 0x16, 0x29, 0x77, 0x01, 0x40, 0xdd, + 0xe5, 0xcb, 0x28, 0x91, 0x3a, 0x0c, 0x13, 0x01, 0x1b, 0x72, + 0x62, 0x45, 0x27, 0xfd, 0xd7, 0x00, 0x47, 0x36, 0x09, 0x1e, + 0x7b, 0xd2, 0xcb, 0x95, 0x3d, 0x28, 0x82, 0xce, 0x83, 0x59, + 0x32, 0xf9, 0xe6, 0xec, 0x89, 0xac, 0x88, 0x45, 0x22, 0x88, + 0x6f, 0x5e, 0xa2, 0x79, 0x95, 0xba, 0xb9, 0xc9, 0xb6, 0x4c, + 0x7c, 0xb4, 0x29, 0xa1, 0x02, 0xf5, 0xac, 0x5d, 0x8e, 0x52, + 0xeb, 0xe8, 0xb1, 0x56, 0x49, 0xb3, 0x77, 0x62, 0x7d, 0x87, + 0x4d, 0x17, 0xf2, 0x62, 0x83, 0x08, 0x59, 0x21, 0x60, 0x0d, + 0x84, 0x8e, 0x5a, 0x84, 0xf6 ), + FINGERPRINT ( 0x88, 0x70, 0xbf, 0xf0, 0xd6, 0x09, 0x03, 0x3a, + 0xe1, 0x80, 0xa7, 0xa5, 0x5c, 0x3e, 0xe1, 0x05, + 0x38, 0x97, 0xde, 0xe1, 0xe9, 0x74, 0x55, 0xb1, + 0x1e, 0x59, 0x69, 0x44, 0x42, 0x1b, 0xc8, 0xff ) ); + +/* + * subject iPXE self-test leaf CA + * issuer iPXE self-test intermediate CA + */ +CERTIFICATE ( leaf_crt, + DATA ( 0x30, 0x82, 0x02, 0xb6, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, + 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, + 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x27, 0x30, + 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x69, 0x50, + 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, + 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, + 0x30, 0x31, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31, + 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33, 0x33, 0x5a, + 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, + 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, + 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, + 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x55, + 0xad, 0xdf, 0x7b, 0xd1, 0x48, 0xc3, 0xd3, 0x02, 0x54, 0x6c, + 0x92, 0x45, 0x22, 0x3d, 0x90, 0xd8, 0xc7, 0x13, 0xcd, 0xc1, + 0x59, 0xc6, 0xe0, 0xad, 0x0e, 0xe6, 0xdb, 0x3b, 0xe8, 0x63, + 0xea, 0x4e, 0xb6, 0xea, 0x50, 0xea, 0x6e, 0x33, 0x9d, 0x28, + 0x25, 0x42, 0x49, 0xd0, 0xf0, 0xed, 0xc5, 0x5b, 0x6b, 0x4a, + 0xe7, 0x45, 0xfa, 0xd3, 0x3f, 0xae, 0xde, 0x5a, 0x90, 0xab, + 0xf1, 0x61, 0x2f, 0x40, 0x5e, 0xcf, 0x8b, 0x0b, 0x10, 0x59, + 0xa9, 0xd0, 0x1e, 0x0f, 0x18, 0x6b, 0x92, 0xd8, 0x9f, 0x58, + 0x10, 0x84, 0xb6, 0x15, 0xe8, 0x5b, 0xc4, 0xa0, 0x3e, 0x49, + 0x8b, 0xea, 0xdd, 0xa9, 0x7e, 0x32, 0x26, 0x9a, 0x68, 0x44, + 0xf0, 0x30, 0xca, 0x2a, 0xd6, 0x19, 0x7a, 0x80, 0xfd, 0xd7, + 0xfc, 0xc7, 0x5d, 0xe7, 0x61, 0xd2, 0x3f, 0x1f, 0x2c, 0x40, + 0x70, 0x7b, 0x34, 0xcb, 0x08, 0xa9, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x26, 0x30, 0x24, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, + 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, + 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, + 0x40, 0xd2, 0x70, 0x02, 0x08, 0x19, 0xa0, 0xb8, 0x8d, 0x9d, + 0x3d, 0x62, 0x41, 0x90, 0x2a, 0x36, 0x4a, 0x8b, 0x21, 0x42, + 0x9a, 0xb4, 0xc5, 0xf8, 0x79, 0x17, 0xd7, 0x64, 0x4d, 0xbf, + 0x8f, 0x6a, 0x04, 0x54, 0x7a, 0x0b, 0xd4, 0xb5, 0x0e, 0xab, + 0xf7, 0xb7, 0x06, 0x2b, 0xf8, 0xde, 0x87, 0xb2, 0x37, 0x3b, + 0x95, 0x01, 0xba, 0x9f, 0x8f, 0xec, 0x0a, 0x86, 0xca, 0x51, + 0xb6, 0x25, 0x73, 0x2f, 0xa1, 0x66, 0xc8, 0x7a, 0x5e, 0x51, + 0xbd, 0x49, 0xb5, 0x75, 0xda, 0xea, 0xe5, 0xeb, 0x5d, 0xe3, + 0xb0, 0xad, 0x49, 0x9f, 0x8b, 0xfd, 0x89, 0xb3, 0xb7, 0xb2, + 0x4c, 0x7d, 0x8a, 0x29, 0xb2, 0xbe, 0x04, 0xef, 0x9c, 0x73, + 0x3c, 0xea, 0xa3, 0x9f, 0x07, 0x66, 0x5a, 0x2f, 0x38, 0xad, + 0x1a, 0xeb, 0xe1, 0xb0, 0x62, 0x14, 0x55, 0xdc, 0x8c, 0x83, + 0xbb, 0xc7, 0x13, 0x04, 0x41, 0x54, 0xf1, 0x45 ), + FINGERPRINT ( 0xca, 0xcf, 0xea, 0x98, 0x3d, 0x71, 0xb6, 0x9d, + 0x4f, 0x5b, 0x84, 0x5e, 0xaa, 0x8e, 0xae, 0x63, + 0x0e, 0xad, 0x52, 0xe8, 0xc7, 0x51, 0x81, 0x07, + 0xd1, 0xa1, 0x66, 0xdb, 0xd5, 0x62, 0xe1, 0xe6 ) ); + +/* + * subject iPXE self-test useless CA + * issuer iPXE self-test leaf CA + */ +CERTIFICATE ( useless_crt, + DATA ( 0x30, 0x82, 0x02, 0xae, 0x30, 0x82, 0x02, 0x17, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, + 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, + 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x69, 0x50, + 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, 0x65, + 0x73, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x43, 0x41, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31, + 0x34, 0x31, 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x34, 0x5a, 0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, + 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, + 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, + 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x69, + 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2d, 0x74, + 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x6c, 0x65, 0x73, + 0x73, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xbe, 0x7f, 0x5a, 0x07, 0x7c, 0x61, 0xc2, + 0x3a, 0x7e, 0xe3, 0x94, 0xcb, 0xe9, 0xc3, 0x4c, 0x6f, 0x8d, + 0x5c, 0x4a, 0xf0, 0xc2, 0x13, 0x54, 0x09, 0x39, 0xa8, 0xf9, + 0xc2, 0xc3, 0xdd, 0xbe, 0x42, 0x99, 0xa6, 0xe1, 0x58, 0x0a, + 0xd5, 0x89, 0x12, 0xa6, 0xd6, 0x4e, 0xfb, 0x6c, 0xe5, 0xab, + 0xff, 0x40, 0x52, 0xcc, 0x1e, 0x63, 0x10, 0xd7, 0xfe, 0x49, + 0xf3, 0x86, 0x29, 0x58, 0x6a, 0x90, 0xe4, 0xe2, 0x56, 0x85, + 0x14, 0x7d, 0xa5, 0xf8, 0xe0, 0x7e, 0x96, 0x88, 0xd9, 0x23, + 0xe5, 0x44, 0x72, 0xa9, 0x5a, 0xbb, 0x76, 0x6b, 0x59, 0x3e, + 0x85, 0xd4, 0xe7, 0xb2, 0x31, 0x32, 0xea, 0x40, 0x1f, 0xce, + 0xfb, 0xb1, 0x91, 0xee, 0x86, 0x91, 0x3e, 0xa4, 0x86, 0xa4, + 0xe9, 0x74, 0xd7, 0x14, 0x8c, 0xb6, 0xb4, 0xc0, 0x08, 0xbb, + 0xc8, 0x38, 0xc3, 0x96, 0x3d, 0x85, 0xcf, 0xef, 0x94, 0x52, + 0x29, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x23, 0x30, 0x21, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, + 0x02, 0x02, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x50, 0x59, 0xfb, 0x9d, 0x4d, 0xfe, 0x0e, 0x5b, + 0xc4, 0x51, 0xe9, 0xe8, 0xa4, 0xf5, 0x2f, 0x32, 0x8b, 0x06, + 0x78, 0xbe, 0xf1, 0x18, 0xc5, 0x6f, 0xd9, 0x20, 0xee, 0xb7, + 0x51, 0x40, 0xaf, 0xf3, 0x3c, 0xe4, 0x74, 0x00, 0xa4, 0x63, + 0x3b, 0x37, 0xe1, 0xef, 0x80, 0xdc, 0xd5, 0x90, 0xed, 0xba, + 0x91, 0x86, 0x7f, 0x97, 0x5d, 0x3e, 0x8f, 0x29, 0xcc, 0x57, + 0xee, 0x79, 0x15, 0x6b, 0xe3, 0xd1, 0x25, 0x14, 0x24, 0xdf, + 0xbf, 0x38, 0xee, 0xe3, 0x8a, 0x88, 0x19, 0x0f, 0xc8, 0x10, + 0xae, 0x27, 0x99, 0xa8, 0x35, 0x47, 0xc9, 0xfb, 0x92, 0x47, + 0xa2, 0x36, 0x2a, 0x8c, 0x26, 0x12, 0xb1, 0x0d, 0x46, 0xe2, + 0xdc, 0x33, 0x29, 0x0c, 0x32, 0xcf, 0x22, 0x49, 0xde, 0xc3, + 0x55, 0x2a, 0xba, 0xdd, 0xe3, 0x98, 0xc0, 0xe4, 0x9a, 0xa2, + 0xe5, 0x43, 0x04, 0x32, 0xd3, 0x50, 0x7d, 0x9c, 0x71, 0x23 ), + FINGERPRINT ( 0xda, 0xbf, 0xd3, 0x5e, 0x2e, 0x29, 0xa9, 0xfd, + 0x4d, 0x40, 0xba, 0xb8, 0xdd, 0x66, 0x93, 0x4c, + 0x10, 0xea, 0x5b, 0x07, 0xa6, 0xe2, 0x27, 0x63, + 0x2e, 0xfe, 0x01, 0x63, 0x7c, 0xea, 0xc6, 0xd0 ) ); + +/* + * subject boot.test.ipxe.org + * issuer iPXE self-test leaf CA + */ +CERTIFICATE ( server_crt, + DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01, + 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, + 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x84, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, + 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, 0xe0, 0x1d, 0x38, 0x41, + 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, 0xcb, 0x9c, 0x9c, 0x93, + 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, 0x39, 0xf6, 0x42, 0xe4, + 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, 0xba, 0x25, 0x58, 0xc8, + 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, 0x5b, 0xbc, 0x89, 0xca, + 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, 0x25, 0x67, 0x0a, 0x38, + 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, 0x02, 0x14, 0xd6, 0xf2, + 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, 0x4d, 0x47, 0xaf, 0x87, + 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, 0xf3, 0xb5, 0xd4, 0x15, + 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, 0x34, 0x8e, 0x50, 0x4b, + 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, 0x68, 0xdb, 0xa8, 0x17, + 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, 0xfc, 0xc3, 0x9b, 0x9d, + 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, 0x60, 0xef, 0xf7, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, 0xf3, 0x68, 0xe3, 0x75, + 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, 0xea, 0xd1, 0x26, 0x33, + 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, 0x20, 0x84, 0x08, 0x78, + 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, 0x4d, 0x6c, 0xbb, 0xd5, + 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, 0x4d, 0x10, 0x16, 0x9f, + 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, 0x9d, 0x57, 0x71, 0x45, + 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, 0x03, 0x9c, 0x2b, 0x25, + 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, 0x14, 0xbf, 0xcf, 0xf0, + 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, 0xd2, 0xe9, 0xed, 0xbf, + 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, 0xeb, 0xf7, 0xa8, 0x26, + 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, 0x42, 0xd1, 0xf1, 0xfd, + 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, 0x67, 0xf0, 0x16, 0x3a, + 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, 0x18, 0x1f, 0x09, 0x8e, + 0x4d ), + FINGERPRINT ( 0xe0, 0xdb, 0x60, 0x53, 0x7c, 0xf6, 0x25, 0x8f, + 0xa7, 0xba, 0xdf, 0xe2, 0x1a, 0xfc, 0x27, 0x49, + 0xf6, 0x83, 0x15, 0xbd, 0x1b, 0x4c, 0x3f, 0x36, + 0x6f, 0x33, 0xf2, 0x47, 0x8e, 0x8b, 0x38, 0xa8 ) ); + +/* + * subject not.a.ca.test.ipxe.org + * issuer boot.test.ipxe.org + */ +CERTIFICATE ( not_ca_crt, + DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01, + 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74, 0x65, + 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, + 0x67, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, + 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, + 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, + 0x33, 0x34, 0x5a, 0x30, 0x81, 0x88, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, + 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, + 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, + 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, + 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, + 0x6e, 0x6f, 0x74, 0x2e, 0x61, 0x2e, 0x63, 0x61, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, + 0x00, 0xc3, 0x5b, 0x6d, 0xb3, 0x8d, 0x74, 0x9c, 0x1d, 0xbd, + 0x94, 0x41, 0xa2, 0x42, 0x96, 0x3c, 0x41, 0x82, 0xc0, 0xf1, + 0x95, 0xbf, 0xc5, 0x34, 0x92, 0x92, 0xa3, 0xed, 0xed, 0x5c, + 0x07, 0xaa, 0xb4, 0xc1, 0x66, 0xbb, 0xa6, 0xd1, 0xd9, 0x78, + 0x93, 0xf1, 0x9c, 0x3e, 0x13, 0x3a, 0xee, 0x74, 0x31, 0xeb, + 0x55, 0x86, 0xa5, 0x43, 0x8a, 0x5d, 0x0c, 0x2c, 0x0d, 0xfb, + 0x91, 0x9e, 0x31, 0x22, 0xbe, 0x96, 0xb5, 0x0e, 0x44, 0xc8, + 0x5b, 0x65, 0xb2, 0xf5, 0xec, 0x2a, 0x51, 0xed, 0x8f, 0x28, + 0xd8, 0xb2, 0x4b, 0x45, 0x39, 0x31, 0x1f, 0x11, 0xb7, 0x12, + 0xe3, 0xc6, 0xb2, 0xd2, 0x8d, 0x50, 0xd5, 0xf4, 0xd2, 0x71, + 0x77, 0xc9, 0x4c, 0x67, 0xee, 0xf7, 0xdc, 0xdb, 0x68, 0xa6, + 0xac, 0x33, 0xd4, 0xb2, 0x12, 0x61, 0x5c, 0xae, 0x4c, 0x2e, + 0x26, 0xe8, 0xdf, 0x46, 0x3a, 0x05, 0xaf, 0xeb, 0x0d, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x90, 0x3e, 0x16, 0x27, 0x2f, 0x4e, 0x4b, + 0x31, 0x0e, 0xae, 0x31, 0x9d, 0x64, 0x88, 0x9f, 0xce, 0xd8, + 0x22, 0x51, 0x9d, 0xd9, 0x2b, 0xfe, 0xed, 0x75, 0xbe, 0xec, + 0x5a, 0x73, 0xaf, 0x6c, 0xa5, 0x5e, 0xd1, 0x15, 0x9a, 0x08, + 0xcf, 0x4d, 0x41, 0x78, 0x48, 0xb4, 0x29, 0xf1, 0xf7, 0x63, + 0x9b, 0x11, 0x91, 0x16, 0x94, 0x55, 0xff, 0xeb, 0xe9, 0x6f, + 0x0a, 0x34, 0x89, 0xed, 0xf2, 0xd1, 0x79, 0x91, 0x9d, 0xe5, + 0x73, 0x48, 0x68, 0x7f, 0x9b, 0xf4, 0x94, 0x80, 0x29, 0xbb, + 0x2f, 0xac, 0x6c, 0xf7, 0x6a, 0x43, 0xcc, 0x40, 0x34, 0x85, + 0xc8, 0xa1, 0x6d, 0x16, 0x36, 0x65, 0x3f, 0x93, 0x60, 0xc1, + 0x64, 0x33, 0x91, 0xa1, 0x8f, 0x86, 0x8c, 0xce, 0x14, 0x19, + 0x72, 0x28, 0xef, 0x94, 0x3d, 0x09, 0xb8, 0x3b, 0x39, 0xe8, + 0xd1, 0x66, 0x2b, 0x38, 0xb4, 0x46, 0x50, 0xf4, 0xcd, 0xc4, + 0x9a ), + FINGERPRINT ( 0x37, 0x6b, 0xc2, 0x20, 0xa9, 0xbc, 0xe2, 0x83, + 0x99, 0x60, 0x06, 0x2e, 0xaf, 0x94, 0xfe, 0xb0, + 0x1a, 0x2c, 0x17, 0x47, 0x1e, 0xc0, 0xd1, 0x66, + 0xb6, 0x76, 0xeb, 0x1c, 0x07, 0xae, 0x72, 0xf2 ) ); + +/* + * subject bad.path.len.test.ipxe.org + * issuer iPXE self-test useless CA + */ +CERTIFICATE ( bad_path_len_crt, + DATA ( 0x30, 0x82, 0x02, 0x88, 0x30, 0x82, 0x01, 0xf1, 0x02, 0x01, + 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x8b, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x19, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, + 0x65, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, + 0x30, 0x31, 0x33, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, + 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, + 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, + 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0f, 0x46, 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x73, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, + 0x78, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x23, 0x30, 0x21, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x62, 0x61, 0x64, + 0x2e, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x6c, 0x65, 0x6e, 0x2e, + 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xed, 0xf1, 0xe3, 0xb2, 0x61, 0x68, 0xa0, 0xd5, + 0x43, 0xfe, 0xad, 0xee, 0xfb, 0x8e, 0x2c, 0xf0, 0x44, 0xaf, + 0x0a, 0x3c, 0x87, 0xc2, 0x56, 0x9b, 0x66, 0x15, 0xc6, 0xbc, + 0x5b, 0x96, 0xef, 0xa1, 0x49, 0xd6, 0xe7, 0xeb, 0xb8, 0xf6, + 0x3d, 0x62, 0xf5, 0x51, 0xfd, 0xb1, 0xa5, 0x4e, 0x92, 0x7c, + 0x7a, 0x31, 0x1b, 0xb8, 0x21, 0x5c, 0xfe, 0x0b, 0x4e, 0x58, + 0xd6, 0xd0, 0x8b, 0x81, 0x00, 0x4a, 0xf8, 0xf7, 0x2a, 0xc9, + 0xea, 0xfa, 0x9c, 0xc9, 0x33, 0x0b, 0xc4, 0xce, 0x96, 0x4c, + 0x30, 0x6e, 0xf0, 0x07, 0xfa, 0x1b, 0x94, 0x1f, 0xe3, 0x3b, + 0xb2, 0x7d, 0x31, 0x1a, 0x37, 0x64, 0xe2, 0xc3, 0xf1, 0xe5, + 0xb9, 0xcc, 0xd1, 0x02, 0xae, 0x16, 0x39, 0x9b, 0xfc, 0x55, + 0xca, 0xdd, 0x33, 0x92, 0xe3, 0x12, 0x40, 0xc5, 0x32, 0x51, + 0x62, 0xac, 0x3a, 0xc0, 0x17, 0x36, 0xd0, 0x27, 0x3d, 0xbb, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x07, 0x53, 0x2a, 0x80, 0xd6, 0x25, + 0x10, 0x37, 0xce, 0x3b, 0x87, 0x87, 0xfc, 0xae, 0xe2, 0x2a, + 0x28, 0x3f, 0xf7, 0xa6, 0x32, 0x5b, 0x06, 0xbd, 0x4f, 0x34, + 0x6b, 0x47, 0x8a, 0x4b, 0x47, 0x51, 0xe8, 0x45, 0x69, 0xe3, + 0xf3, 0xdf, 0xa4, 0x25, 0x8f, 0x34, 0xbe, 0xe5, 0x2c, 0xa4, + 0x6c, 0x8c, 0x6e, 0x02, 0x74, 0x23, 0x43, 0x21, 0x4d, 0xe3, + 0x75, 0x93, 0x8e, 0xa8, 0x2c, 0x54, 0xba, 0x35, 0xe7, 0xab, + 0x44, 0xfa, 0x07, 0x7a, 0x18, 0xb4, 0xa7, 0xce, 0xfa, 0xa6, + 0x74, 0x5a, 0x45, 0x2c, 0x6f, 0x86, 0x34, 0x8f, 0x4a, 0x09, + 0xe0, 0xf3, 0x4f, 0x37, 0xbb, 0xa3, 0xa0, 0xcb, 0xad, 0x6b, + 0xc1, 0x16, 0x06, 0xdf, 0x83, 0x98, 0xaf, 0xa8, 0xc3, 0xa0, + 0x5f, 0x33, 0x09, 0x01, 0x12, 0xbd, 0xd3, 0x45, 0x9f, 0x5f, + 0x96, 0x93, 0xe9, 0x69, 0xe9, 0xb1, 0x8a, 0xe4, 0x94, 0xce, + 0xe4, 0x8d ), + FINGERPRINT ( 0xb6, 0x80, 0x84, 0xf1, 0x45, 0x55, 0x1f, 0xbc, + 0x15, 0xa6, 0xd8, 0x4b, 0xf3, 0x19, 0x65, 0xef, + 0x53, 0x5a, 0xc8, 0x99, 0xe5, 0xdf, 0x79, 0x07, + 0x00, 0x2c, 0x9f, 0x49, 0x91, 0x21, 0xeb, 0xfc ) ); + +/** Valid certificate chain up to boot.test.ipxe.org */ +CHAIN ( server_chain, &server_crt, &leaf_crt, &intermediate_crt, &root_crt ); + +/** Broken certificate chain up to boot.test.ipxe.org */ +CHAIN ( broken_server_chain, &server_crt, &leaf_crt, &root_crt ); + +/** Incomplete certificate chain up to boot.test.ipxe.org */ +CHAIN ( incomplete_server_chain, &server_crt, &leaf_crt, &intermediate_crt ); + +/** Non-functional certificate chain up to not_ca.test.ipxe.org */ +CHAIN ( not_ca_chain, + ¬_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/src/usr/autoboot.c b/src/usr/autoboot.c index 5bfadec0..da82f5e8 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -131,6 +131,7 @@ struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA ) = { */ int uriboot ( struct uri *filename, struct uri *root_path, int drive, unsigned int flags ) { + struct image *image; int rc; /* Hook SAN device, if applicable */ @@ -157,9 +158,10 @@ int uriboot ( struct uri *filename, struct uri *root_path, int drive, /* Attempt filename boot if applicable */ if ( filename ) { - if ( ( rc = imgdownload ( filename, NULL, NULL, - image_exec ) ) != 0 ) { - printf ( "\nCould not chain image: %s\n", + if ( ( rc = imgdownload ( filename, &image ) ) != 0 ) + goto err_download; + if ( ( rc = image_exec ( image ) ) != 0 ) { + printf ( "Could not boot image: %s\n", strerror ( rc ) ); /* Fall through to (possibly) attempt a SAN boot * as a fallback. If no SAN boot is attempted, @@ -190,6 +192,7 @@ int uriboot ( struct uri *filename, struct uri *root_path, int drive, } } + err_download: err_san_describe: /* Unhook SAN device, if applicable */ if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) { diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index 04985159..8ee311c0 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -113,6 +113,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/src/usr/imgmgmt.c b/src/usr/imgmgmt.c index e323dd0c..2c74f486 100644 --- a/src/usr/imgmgmt.c +++ b/src/usr/imgmgmt.c @@ -36,39 +36,25 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** - * 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, or NULL + * @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 ) { + *image = alloc_image ( uri ); + if ( ! *image ) { rc = -ENOMEM; goto err_alloc_image; } - /* 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 ); - /* Redact password portion of URI, if necessary */ password = uri->password; if ( password ) @@ -78,8 +64,9 @@ 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 ) { + printf ( "Could not start download: %s\n", strerror ( rc ) ); goto err_create_downloader; } @@ -88,49 +75,64 @@ int imgdownload ( struct uri *uri, const char *name, const char *cmdline, goto err_monojob_wait; /* Register image */ - if ( ( rc = register_image ( image ) ) != 0 ) + if ( ( rc = register_image ( *image ) ) != 0 ) { + printf ( "Could not register image: %s\n", strerror ( rc ) ); goto err_register_image; + } /* Drop local reference to image. Image is guaranteed to * remain in scope since it is registered. */ - image_put ( image ); + image_put ( *image ); - /* Carry out specified post-download action, if applicable */ - return ( action ? action ( image ) : 0 ); + return 0; err_register_image: err_monojob_wait: err_create_downloader: - image_put ( image ); + 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 * @@ -140,18 +142,11 @@ void imgstat ( struct image *image ) { printf ( "%s : %zd bytes", image->name, image->len ); if ( image->type ) printf ( " [%s]", image->type->name ); + if ( image->flags & IMAGE_TRUSTED ) + printf ( " [TRUSTED]" ); if ( image->flags & IMAGE_SELECTED ) printf ( " [SELECTED]" ); if ( image->cmdline ) printf ( " \"%s\"", image->cmdline ); printf ( "\n" ); } - -/** - * Free an image - * - * @v image Executable/loadable image - */ -void imgfree ( struct image *image ) { - unregister_image ( image ); -} diff --git a/src/usr/imgtrust.c b/src/usr/imgtrust.c new file mode 100644 index 00000000..651f0493 --- /dev/null +++ b/src/usr/imgtrust.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#include <syslog.h> +#include <ipxe/uaccess.h> +#include <ipxe/image.h> +#include <ipxe/cms.h> +#include <usr/imgtrust.h> + +/** @file + * + * Image trust management + * + */ + +/** + * Verify image using downloaded signature + * + * @v image Image to verify + * @v signature Image containing signature + * @v name Required common name, or NULL to allow any name + * @ret rc Return status code + */ +int imgverify ( struct image *image, struct image *signature, + const char *name ) { + size_t len; + void *data; + struct cms_signature *sig; + time_t now; + int rc; + + /* Mark image as untrusted */ + image_untrust ( image ); + + /* Copy signature to internal memory */ + len = signature->len; + data = malloc ( len ); + if ( ! data ) { + rc = -ENOMEM; + goto err_alloc; + } + copy_from_user ( data, signature->data, 0, len ); + + /* Parse signature */ + if ( ( rc = cms_signature ( data, len, &sig ) ) != 0 ) + goto err_parse; + + /* Free internal copy of signature */ + free ( data ); + data = NULL; + + /* Use signature to verify image */ + now = time ( NULL ); + if ( ( rc = cms_verify ( sig, image->data, image->len, + name, now, NULL ) ) != 0 ) + goto err_verify; + + /* Drop reference to signature */ + cms_put ( sig ); + sig = NULL; + + /* Mark image as trusted */ + image_trust ( image ); + syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name ); + + return 0; + + err_verify: + cms_put ( sig ); + err_parse: + free ( data ); + err_alloc: + syslog ( LOG_ERR, "Image \"%s\" signature bad: %s\n", + image->name, strerror ( rc ) ); + return rc; +} diff --git a/src/usr/iwmgmt.c b/src/usr/iwmgmt.c index 29f623c3..abcd63f4 100644 --- a/src/usr/iwmgmt.c +++ b/src/usr/iwmgmt.c @@ -19,7 +19,6 @@ 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/src/util/Makefile b/src/util/Makefile index d72661e2..4a6a7c7c 100644 --- a/src/util/Makefile +++ b/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/src/util/efirom.c b/src/util/efirom.c index d0bdace6..a65abfee 100644 --- a/src/util/efirom.c +++ b/src/util/efirom.c @@ -56,18 +56,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 +227,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/src/util/einfo.c b/src/util/einfo.c index 06736f21..15f920d0 100644 --- a/src/util/einfo.c +++ b/src/util/einfo.c @@ -20,6 +20,7 @@ #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 +50,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,9 +87,9 @@ 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 ) ); } } @@ -115,8 +117,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 +148,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/src/util/elf2efi.c b/src/util/elf2efi.c index e6629296..fc6bef37 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -405,6 +405,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 +463,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); @@ -637,7 +642,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 +791,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/src/util/genkeymap.pl b/src/util/genkeymap.pl index d556df27..6487cd79 100755 --- a/src/util/genkeymap.pl +++ b/src/util/genkeymap.pl @@ -124,8 +124,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/src/util/iccfix.c b/src/util/iccfix.c index 8b555c54..528bf4b2 100644 --- a/src/util/iccfix.c +++ b/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/src/util/niclist.pl b/src/util/niclist.pl new file mode 100755 index 00000000..0600c823 --- /dev/null +++ b/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/src/util/nrv2b.c b/src/util/nrv2b.c index 6bac4cdd..cbb94c0e 100644 --- a/src/util/nrv2b.c +++ b/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; @@ -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/src/util/parserom.pl b/src/util/parserom.pl old mode 100644 new mode 100755 index 5e55c6da..e278e633 --- a/src/util/parserom.pl +++ b/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 diff --git a/src/util/zbin.c b/src/util/zbin.c index f0df5ea0..a9195164 100644 --- a/src/util/zbin.c +++ b/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,9 +230,11 @@ 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,