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,