From b41e38e4a2b329e14f830cf0d5235e78de8e8bfa Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Mon, 5 Mar 2007 21:29:45 +0000 Subject: [PATCH] This is odd, but try again. Comitting IP checksum code, and its usage in linuxbios table creation. Mods to the dts, so that the device ops for the domain are set to the proper structure. This change is important. It gets rid of the obscure, confusing use of the enable_dev function to pick the right ops for a device. It makes the ops initilization very clear at the top level, in the dts. This has been tested and works, linux boots on Bochs under this version. Signed-off-by: Ronald G. Minnich Acked-by: Stefan Reinauer git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@191 f3766cd6-281f-0410-b1cd-43a5c92072e9 --- arch/x86/Makefile | 2 +- arch/x86/linuxbios_table.c | 6 +-- include/ip_checksum.h | 8 ++++ lib/compute_ip_checksum.c | 53 ++++++++++++++++++++++ mainboard/emulation/qemu-x86/dts | 2 +- northbridge/intel/i440bxemulation/config.h | 1 + northbridge/intel/i440bxemulation/i440bx.c | 27 +++++------ 7 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 include/ip_checksum.h create mode 100644 lib/compute_ip_checksum.c diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 630c24d44c..f6f35f5bf1 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -108,7 +108,7 @@ $(obj)/stage0.init: $(STAGE0_OBJ) # STAGE2_LIB_OBJ = $(obj)/stage2.o $(obj)/clog2.o $(obj)/mem.o $(obj)/malloc.o \ - $(obj)/tables.o $(obj)/delay.o + $(obj)/tables.o $(obj)/delay.o $(obj)/compute_ip_checksum.o STAGE2_ARCH_X86_OBJ = $(obj)/archtables.o $(obj)/linuxbios_table.o $(obj)/udelay_io.o STAGE2_ARCH_X86_OBJ += $(obj)/pci_ops_auto.o $(obj)/pci_ops_conf1.o $(obj)/pci_ops_conf2.o STAGE2_MAINBOARD_OBJ = $(obj)/mainboard.o diff --git a/arch/x86/linuxbios_table.c b/arch/x86/linuxbios_table.c index 9fb8be9766..76f20a403d 100644 --- a/arch/x86/linuxbios_table.c +++ b/arch/x86/linuxbios_table.c @@ -19,7 +19,7 @@ */ #include -//#include +#include #include //#include //#include @@ -229,9 +229,9 @@ unsigned long lb_table_fini(struct lb_header *head) } lb_reserve_table_memory(head); first_rec = lb_first_record(head); - head->table_checksum = 0; //compute_ip_checksum(first_rec, head->table_bytes); + head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes); head->header_checksum = 0; - head->header_checksum = 0; //compute_ip_checksum(head, sizeof(*head)); + head->header_checksum = compute_ip_checksum(head, sizeof(*head)); printk(BIOS_DEBUG,"Wrote linuxbios table at: %p - %p checksum %lx\n", head, rec, head->table_checksum); return (unsigned long)rec; diff --git a/include/ip_checksum.h b/include/ip_checksum.h new file mode 100644 index 0000000000..485de2c371 --- /dev/null +++ b/include/ip_checksum.h @@ -0,0 +1,8 @@ +#ifndef IP_CHECKSUM_H +#define IP_CHECKSUM_H + +unsigned long compute_ip_checksum(void *addr, unsigned long length); +unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new); + +#endif /* IP_CHECKSUM_H */ + diff --git a/lib/compute_ip_checksum.c b/lib/compute_ip_checksum.c new file mode 100644 index 0000000000..0b8eb90f85 --- /dev/null +++ b/lib/compute_ip_checksum.c @@ -0,0 +1,53 @@ +#include +#include + +unsigned long compute_ip_checksum(void *addr, unsigned long length) +{ + uint8_t *ptr; + volatile union { + uint8_t byte[2]; + uint16_t word; + } value; + unsigned long sum; + unsigned long i; + /* In the most straight forward way possible, + * compute an ip style checksum. + */ + sum = 0; + ptr = addr; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } + } + value.byte[0] = sum & 0xff; + value.byte[1] = (sum >> 8) & 0xff; + return (~value.word) & 0xFFFF; +} + +unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new) +{ + unsigned long checksum; + sum = ~sum & 0xFFFF; + new = ~new & 0xFFFF; + if (offset & 1) { + /* byte swap the sum if it came from an odd offset + * since the computation is endian independant this + * works. + */ + new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00); + } + checksum = sum + new; + if (checksum > 0xFFFF) { + checksum -= 0xFFFF; + } + return (~checksum) & 0xFFFF; +} diff --git a/mainboard/emulation/qemu-x86/dts b/mainboard/emulation/qemu-x86/dts index 2322616cb4..c707429281 100644 --- a/mainboard/emulation/qemu-x86/dts +++ b/mainboard/emulation/qemu-x86/dts @@ -8,7 +8,7 @@ domain0{ enabled; config="northbridge,intel,i440bxemulation"; - ops="default_pci_ops_dev"; + ops="i440bxemulation_pcidomainops"; pcidomain = "0"; device0,0{ enabled; diff --git a/northbridge/intel/i440bxemulation/config.h b/northbridge/intel/i440bxemulation/config.h index 646555edb9..dacd1a1b51 100644 --- a/northbridge/intel/i440bxemulation/config.h +++ b/northbridge/intel/i440bxemulation/config.h @@ -19,6 +19,7 @@ */ extern struct chip_operations northbridge_intel_i440bxemulation_ops; +extern struct device_operations i440bxemulation_pcidomainops; struct northbridge_intel_i440bx_config { diff --git a/northbridge/intel/i440bxemulation/i440bx.c b/northbridge/intel/i440bxemulation/i440bx.c index 936496331e..5dacd606b3 100644 --- a/northbridge/intel/i440bxemulation/i440bx.c +++ b/northbridge/intel/i440bxemulation/i440bx.c @@ -27,29 +27,18 @@ #include "config.h" #include "i440bx.h" -/* This is the starting point. */ -struct device_operations i440bxemulation_pcidomainops; static void i440bxemulation_enable_dev(struct device *dev) { printk(BIOS_INFO, "%s: \n", __FUNCTION__); - /* just a test here. ... we don't want to do this in real life */ - dev->ops = &i440bxemulation_pcidomainops; - /* Set the operations if it is a special bus type */ -/* - if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) { - dev->ops = &pci_domain_ops; - pci_set_method(dev); - } - */ printk(BIOS_INFO, "%s: Done.\n", __FUNCTION__); } -struct chip_operations northbridge_intel_i440bxemulation_ops = { - .name="Intel 440BX Northbridge Emulation", - .enable_dev = i440bxemulation_enable_dev, -}; /* Here are the ops for 440BX as a PCI domain. */ +/* a PCI domain contains the I/O and memory resource address space below it. */ +/* Currently, the only functions in here are for the domain. If device functions are needed, + * they will come later. + */ static void pci_domain_read_resources(struct device * dev) { @@ -103,6 +92,14 @@ static unsigned int pci_domain_scan_bus(struct device * dev, unsigned int max) return max; } +/* here are the chip operations. These are for the chip-specific functions. */ +struct chip_operations northbridge_intel_i440bxemulation_ops = { + .name="Intel 440BX Northbridge Emulation", + .enable_dev = i440bxemulation_enable_dev, +}; + +/* here are the operations for when the northbridge is running a pci domain. */ +/* see emulation/qemu-x86 for an example of how these are used. */ struct device_operations i440bxemulation_pcidomainops = { .phase4_read_resources = pci_domain_read_resources, .phase4_set_resources = pci_domain_set_resources,