- Initial checkin of the freebios2 tree
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@784 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
		
							
								
								
									
										182
									
								
								src/arch/i386/boot/boot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								src/arch/i386/boot/boot.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <ip_checksum.h> | ||||||
|  | #include <boot/elf.h> | ||||||
|  | #include <boot/elf_boot.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef CMD_LINE | ||||||
|  | #define CMD_LINE "" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define UPSZ(X) ((sizeof(X) + 3) &~3) | ||||||
|  |  | ||||||
|  | static struct { | ||||||
|  | 	Elf_Bhdr hdr; | ||||||
|  | 	Elf_Nhdr ft_hdr; | ||||||
|  | 	unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)]; | ||||||
|  | 	Elf_Nhdr bl_hdr; | ||||||
|  | 	unsigned char bl_desc[UPSZ(BOOTLOADER)]; | ||||||
|  | 	Elf_Nhdr blv_hdr; | ||||||
|  | 	unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; | ||||||
|  | 	Elf_Nhdr cmd_hdr; | ||||||
|  | 	unsigned char cmd_desc[UPSZ(CMD_LINE)]; | ||||||
|  | } elf_boot_notes = { | ||||||
|  | 	.hdr = { | ||||||
|  | 		.b_signature = 0x0E1FB007, | ||||||
|  | 		.b_size = sizeof(elf_boot_notes), | ||||||
|  | 		.b_checksum = 0, | ||||||
|  | 		.b_records = 4, | ||||||
|  | 	}, | ||||||
|  | 	.ft_hdr = { | ||||||
|  | 		.n_namesz = 0, | ||||||
|  | 		.n_descsz = sizeof(FIRMWARE_TYPE), | ||||||
|  | 		.n_type = EBN_FIRMWARE_TYPE, | ||||||
|  | 	}, | ||||||
|  | 	.ft_desc = FIRMWARE_TYPE, | ||||||
|  | 	.bl_hdr = { | ||||||
|  | 		.n_namesz = 0, | ||||||
|  | 		.n_descsz = sizeof(BOOTLOADER), | ||||||
|  | 		.n_type = EBN_BOOTLOADER_NAME, | ||||||
|  | 	}, | ||||||
|  | 	.bl_desc = BOOTLOADER, | ||||||
|  | 	.blv_hdr = { | ||||||
|  | 		.n_namesz = 0, | ||||||
|  | 		.n_descsz = sizeof(BOOTLOADER_VERSION), | ||||||
|  | 		.n_type = EBN_BOOTLOADER_VERSION, | ||||||
|  | 	}, | ||||||
|  | 	.blv_desc = BOOTLOADER_VERSION, | ||||||
|  | 	.cmd_hdr = { | ||||||
|  | 		.n_namesz = 0, | ||||||
|  | 		.n_descsz = sizeof(CMD_LINE), | ||||||
|  | 		.n_type = EBN_COMMAND_LINE, | ||||||
|  | 	}, | ||||||
|  | 	.cmd_desc = CMD_LINE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int elf_check_arch(Elf_ehdr *ehdr) | ||||||
|  | { | ||||||
|  | 	return ( | ||||||
|  | 		((ehdr->e_machine == EM_386) ||	(ehdr->e_machine == EM_486)) && | ||||||
|  | 		(ehdr->e_ident[EI_CLASS] == ELFCLASS32) && | ||||||
|  | 		(ehdr->e_ident[EI_DATA] == ELFDATA2LSB)  | ||||||
|  | 		); | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void jmp_to_elf_entry(void *entry, unsigned long buffer) | ||||||
|  | { | ||||||
|  | 	extern unsigned char _ram_seg, _eram_seg; | ||||||
|  | 	unsigned long lb_start, lb_size; | ||||||
|  | 	unsigned long adjust, adjusted_boot_notes; | ||||||
|  | 	unsigned long type; | ||||||
|  |  | ||||||
|  | 	elf_boot_notes.hdr.b_checksum =  | ||||||
|  | 		compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes)); | ||||||
|  |  | ||||||
|  | 	type = 0x0E1FB007; | ||||||
|  | 	lb_start = (unsigned long)&_ram_seg; | ||||||
|  | 	lb_size = (unsigned long)(&_eram_seg - &_ram_seg); | ||||||
|  | 	adjust = buffer + lb_size - lb_start; | ||||||
|  |  | ||||||
|  | 	adjusted_boot_notes = (unsigned long)&elf_boot_notes; | ||||||
|  | 	adjusted_boot_notes += adjust;  | ||||||
|  |  | ||||||
|  | 	printk_spew("entry    = 0x%08lx\n", (unsigned long)entry); | ||||||
|  | 	printk_spew("lb_start = 0x%08lx\n", lb_start); | ||||||
|  | 	printk_spew("lb_size  = 0x%08lx\n", lb_size); | ||||||
|  | 	printk_spew("adjust   = 0x%08lx\n", adjust); | ||||||
|  | 	printk_spew("buffer   = 0x%08lx\n", buffer); | ||||||
|  | 	printk_spew("     elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes); | ||||||
|  | 	printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes); | ||||||
|  | 	 | ||||||
|  | 	/* Jump to kernel */ | ||||||
|  | 	__asm__ __volatile__( | ||||||
|  | 		"	cld	\n\t" | ||||||
|  | 		/* Save the callee save registers... */ | ||||||
|  | 		"	pushl	%%esi\n\t" | ||||||
|  | 		"	pushl	%%edi\n\t" | ||||||
|  | 		"	pushl	%%ebx\n\t" | ||||||
|  | 		/* Save the parameters I was passed */ | ||||||
|  | 		"	pushl	$0\n\t" /* 20 adjust */ | ||||||
|  | 	        "	pushl	%0\n\t" /* 16 lb_start */ | ||||||
|  | 		"	pushl	%1\n\t" /* 12 buffer */ | ||||||
|  | 		"	pushl	%2\n\t" /*  8 lb_size */ | ||||||
|  | 		"	pushl	%3\n\t" /*  4 entry */ | ||||||
|  | 		"	pushl	%4\n\t" /*  0 elf_boot_notes */ | ||||||
|  | 		/* Compute the adjustment */ | ||||||
|  | 		"	xorl	%%eax, %%eax\n\t" | ||||||
|  | 		"	subl	16(%%esp), %%eax\n\t" | ||||||
|  | 		"	addl	12(%%esp), %%eax\n\t" | ||||||
|  | 		"	addl	 8(%%esp), %%eax\n\t" | ||||||
|  | 		"	movl	%%eax, 20(%%esp)\n\t" | ||||||
|  | 		/* Place a copy of linuxBIOS in it's new location */ | ||||||
|  | 		/* Move ``longs'' the linuxBIOS size is 4 byte aligned */ | ||||||
|  | 		"	movl	12(%%esp), %%edi\n\t" | ||||||
|  | 		"	addl	 8(%%esp), %%edi\n\t" | ||||||
|  | 		"	movl	16(%%esp), %%esi\n\t" | ||||||
|  | 		"	movl	 8(%%esp), %%ecx\n\n" | ||||||
|  | 		"	shrl	$2, %%ecx\n\t" | ||||||
|  | 		"	rep	movsl\n\t" | ||||||
|  |  | ||||||
|  | 		/* Adjust the stack pointer to point into the new linuxBIOS image */ | ||||||
|  | 		"	addl	20(%%esp), %%esp\n\t" | ||||||
|  | 		/* Adjust the instruction pointer to point into the new linuxBIOS image */ | ||||||
|  | 		"	movl	$1f, %%eax\n\t" | ||||||
|  | 		"	addl	20(%%esp), %%eax\n\t" | ||||||
|  | 		"	jmp	*%%eax\n\t" | ||||||
|  | 		"1:	\n\t" | ||||||
|  |  | ||||||
|  | 		/* Copy the linuxBIOS bounce buffer over linuxBIOS */ | ||||||
|  | 		/* Move ``longs'' the linuxBIOS size is 4 byte aligned */ | ||||||
|  | 		"	movl	16(%%esp), %%edi\n\t" | ||||||
|  | 		"	movl	12(%%esp), %%esi\n\t" | ||||||
|  | 		"	movl	 8(%%esp), %%ecx\n\t" | ||||||
|  | 		"	shrl	$2, %%ecx\n\t" | ||||||
|  | 		"	rep	movsl\n\t" | ||||||
|  |  | ||||||
|  | 		/* Now jump to the loaded image */ | ||||||
|  | 		"	movl	$0x0E1FB007, %%eax\n\t" | ||||||
|  | 		"	movl	 0(%%esp), %%ebx\n\t" | ||||||
|  | 		"	call	*4(%%esp)\n\t" | ||||||
|  |  | ||||||
|  | 		/* The loaded image returned? */ | ||||||
|  | 		"	cli	\n\t" | ||||||
|  | 		"	cld	\n\t" | ||||||
|  |  | ||||||
|  | 		/* Copy the saved copy of linuxBIOS where linuxBIOS runs */ | ||||||
|  | 		/* Move ``longs'' the linuxBIOS size is 4 byte aligned */ | ||||||
|  | 		"	movl	16(%%esp), %%edi\n\t" | ||||||
|  | 		"	movl	12(%%esp), %%esi\n\t" | ||||||
|  | 		"	addl	 8(%%esp), %%esi\n\t" | ||||||
|  | 		"	movl	 8(%%esp), %%ecx\n\t" | ||||||
|  | 		"	shrl	$2, %%ecx\n\t" | ||||||
|  | 		"	rep	movsl\n\t" | ||||||
|  |  | ||||||
|  | 		/* Adjust the stack pointer to point into the old linuxBIOS image */ | ||||||
|  | 		"	subl	20(%%esp), %%esp\n\t" | ||||||
|  |  | ||||||
|  | 		/* Adjust the instruction pointer to point into the old linuxBIOS image */ | ||||||
|  | 		"	movl	$1f, %%eax\n\t" | ||||||
|  | 		"	subl	20(%%esp), %%eax\n\t" | ||||||
|  | 		"	jmp	*%%eax\n\t" | ||||||
|  | 		"1:	\n\t" | ||||||
|  |  | ||||||
|  | 		/* Drop the parameters I was passed */ | ||||||
|  | 		"	addl	$24, %%esp\n\t" | ||||||
|  |  | ||||||
|  | 		/* Restore the callee save registers */ | ||||||
|  | 		"	popl	%%ebx\n\t" | ||||||
|  | 		"	popl	%%edi\n\t" | ||||||
|  | 		"	popl	%%esi\n\t" | ||||||
|  |  | ||||||
|  | 		::  | ||||||
|  | 		"g" (lb_start), "g" (buffer), "g" (lb_size), | ||||||
|  | 		"g" (entry), "g"(adjusted_boot_notes) | ||||||
|  | 		); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										281
									
								
								src/arch/i386/boot/linuxbios_table.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								src/arch/i386/boot/linuxbios_table.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <ip_checksum.h> | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  | #include "linuxbios_table.h" | ||||||
|  | #include <string.h> | ||||||
|  | #include <version.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct lb_header *lb_table_init(unsigned long addr) | ||||||
|  | { | ||||||
|  | 	struct lb_header *header; | ||||||
|  |  | ||||||
|  | 	/* 16 byte align the address */ | ||||||
|  | 	addr += 15; | ||||||
|  | 	addr &= ~15; | ||||||
|  |  | ||||||
|  | 	header = (void *)addr; | ||||||
|  | 	header->signature[0] = 'L'; | ||||||
|  | 	header->signature[1] = 'B'; | ||||||
|  | 	header->signature[2] = 'I'; | ||||||
|  | 	header->signature[3] = 'O'; | ||||||
|  | 	header->header_bytes = sizeof(*header); | ||||||
|  | 	header->header_checksum = 0; | ||||||
|  | 	header->table_bytes = 0; | ||||||
|  | 	header->table_checksum = 0; | ||||||
|  | 	header->table_entries = 0; | ||||||
|  | 	return header; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct lb_record *lb_first_record(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec; | ||||||
|  | 	rec = (void *)(((char *)header) + sizeof(*header)); | ||||||
|  | 	return rec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct lb_record *lb_last_record(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec; | ||||||
|  | 	rec = (void *)(((char *)header) + sizeof(*header) + header->table_bytes); | ||||||
|  | 	return rec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct lb_record *lb_next_record(struct lb_record *rec) | ||||||
|  | { | ||||||
|  | 	rec = (void *)(((char *)rec) + rec->size);	 | ||||||
|  | 	return rec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct lb_record *lb_new_record(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec; | ||||||
|  | 	rec = lb_last_record(header); | ||||||
|  | 	if (header->table_entries) { | ||||||
|  | 		header->table_bytes += rec->size; | ||||||
|  | 	} | ||||||
|  | 	rec = lb_last_record(header); | ||||||
|  | 	header->table_entries++; | ||||||
|  | 	rec->tag = LB_TAG_UNUSED; | ||||||
|  | 	rec->size = sizeof(*rec); | ||||||
|  | 	return rec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct lb_memory *lb_memory(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec; | ||||||
|  | 	struct lb_memory *mem; | ||||||
|  | 	rec = lb_new_record(header); | ||||||
|  | 	mem = (struct lb_memory *)rec; | ||||||
|  | 	mem->tag = LB_TAG_MEMORY; | ||||||
|  | 	mem->size = sizeof(*mem); | ||||||
|  | 	return mem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct lb_mainboard *lb_mainboard(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec; | ||||||
|  | 	struct lb_mainboard *mainboard; | ||||||
|  | 	rec = lb_new_record(header); | ||||||
|  | 	mainboard = (struct lb_mainboard *)rec; | ||||||
|  | 	mainboard->tag = LB_TAG_MAINBOARD; | ||||||
|  |  | ||||||
|  | 	mainboard->size = (sizeof(*mainboard) + | ||||||
|  | 		strlen(mainboard_vendor) + 1 +  | ||||||
|  | 		strlen(mainboard_part_number) + 1 + | ||||||
|  | 		3) & ~3; | ||||||
|  |  | ||||||
|  | 	mainboard->vendor_idx = 0; | ||||||
|  | 	mainboard->part_number_idx = strlen(mainboard_vendor) + 1; | ||||||
|  |  | ||||||
|  | 	memcpy(mainboard->strings + mainboard->vendor_idx, | ||||||
|  | 		mainboard_vendor,      strlen(mainboard_vendor) + 1); | ||||||
|  | 	memcpy(mainboard->strings + mainboard->part_number_idx, | ||||||
|  | 		mainboard_part_number, strlen(mainboard_part_number) + 1); | ||||||
|  |  | ||||||
|  | 	return mainboard; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void lb_strings(struct lb_header *header) | ||||||
|  | { | ||||||
|  | 	static const struct { | ||||||
|  | 		uint32_t tag; | ||||||
|  | 		const uint8_t *string; | ||||||
|  | 	} strings[] = { | ||||||
|  | 		{ LB_TAG_VERSION,        linuxbios_version,        }, | ||||||
|  | 		{ LB_TAG_EXTRA_VERSION,  linuxbios_extra_version,  }, | ||||||
|  | 		{ LB_TAG_BUILD,          linuxbios_build,          }, | ||||||
|  | 		{ LB_TAG_COMPILE_TIME,   linuxbios_compile_time,   }, | ||||||
|  | 		{ LB_TAG_COMPILE_BY,     linuxbios_compile_by,     }, | ||||||
|  | 		{ LB_TAG_COMPILE_HOST,   linuxbios_compile_host,   }, | ||||||
|  | 		{ LB_TAG_COMPILE_DOMAIN, linuxbios_compile_domain, }, | ||||||
|  | 		{ LB_TAG_COMPILER,       linuxbios_compiler,       }, | ||||||
|  | 		{ LB_TAG_LINKER,         linuxbios_linker,         }, | ||||||
|  | 		{ LB_TAG_ASSEMBLER,      linuxbios_assembler,      }, | ||||||
|  | 	}; | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { | ||||||
|  | 		struct lb_string *rec; | ||||||
|  | 		size_t len; | ||||||
|  | 		rec = (struct lb_string *)lb_new_record(header); | ||||||
|  | 		len = strlen(strings[i].string); | ||||||
|  | 		rec->tag = strings[i].tag; | ||||||
|  | 		rec->size = (sizeof(*rec) + len + 1 + 3) & ~3; | ||||||
|  | 		memcpy(rec->string, strings[i].string, len+1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Some version of gcc have problems with 64 bit types so | ||||||
|  |  * take an unsigned long instead of a uint64_t for now. | ||||||
|  |  */ | ||||||
|  | void lb_memory_range(struct lb_memory *mem, | ||||||
|  | 	uint32_t type, unsigned long start, unsigned long size) | ||||||
|  | { | ||||||
|  | 	int entries; | ||||||
|  | 	entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); | ||||||
|  | 	mem->map[entries].start = start; | ||||||
|  | 	mem->map[entries].size = size; | ||||||
|  | 	mem->map[entries].type = type; | ||||||
|  | 	mem->size += sizeof(mem->map[0]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lb_memory_rangek(struct lb_memory *mem, | ||||||
|  | 	uint32_t type, unsigned long startk, unsigned long endk) | ||||||
|  | { | ||||||
|  | 	int entries; | ||||||
|  | 	entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); | ||||||
|  | 	mem->map[entries].start = startk; | ||||||
|  | 	mem->map[entries].start <<= 10; | ||||||
|  | 	mem->map[entries].size = endk - startk; | ||||||
|  | 	mem->map[entries].size <<= 10; | ||||||
|  | 	mem->map[entries].type = type; | ||||||
|  | 	mem->size += sizeof(mem->map[0]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lb_reserve_table_memory(struct lb_header *head) | ||||||
|  | { | ||||||
|  | 	struct lb_record *last_rec; | ||||||
|  | 	struct lb_memory *mem; | ||||||
|  | 	uint64_t start; | ||||||
|  | 	uint64_t end; | ||||||
|  | 	int i, entries; | ||||||
|  |  | ||||||
|  | 	last_rec = lb_last_record(head); | ||||||
|  | 	mem = get_lb_mem(); | ||||||
|  | 	start = (unsigned long)head; | ||||||
|  | 	end = (unsigned long)last_rec; | ||||||
|  | 	entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); | ||||||
|  | 	/* Resize the right two memory areas so this table is in | ||||||
|  | 	 * a reserved area of memory.  Everything has been carefully | ||||||
|  | 	 * setup so that is all we need to do. | ||||||
|  | 	 */ | ||||||
|  | 	for(i = 0; i < entries; i++ ) { | ||||||
|  | 		uint64_t map_start = mem->map[i].start; | ||||||
|  | 		uint64_t map_end = map_start + mem->map[i].size; | ||||||
|  | 		/* Does this area need to be expanded? */ | ||||||
|  | 		if (map_end == start) { | ||||||
|  | 			mem->map[i].size = end - map_start; | ||||||
|  | 		} | ||||||
|  | 		/* Does this area need to be contracted? */ | ||||||
|  | 		else if (map_start == start) { | ||||||
|  | 			mem->map[i].start = end; | ||||||
|  | 			mem->map[i].size = map_end - end; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | unsigned long lb_table_fini(struct lb_header *head) | ||||||
|  | { | ||||||
|  | 	struct lb_record *rec, *first_rec; | ||||||
|  | 	rec = lb_last_record(head); | ||||||
|  | 	if (head->table_entries) { | ||||||
|  | 		head->table_bytes += rec->size; | ||||||
|  | 	} | ||||||
|  | 	lb_reserve_table_memory(head); | ||||||
|  | 	first_rec = lb_first_record(head); | ||||||
|  | 	head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes); | ||||||
|  | 	head->header_checksum = 0; | ||||||
|  | 	head->header_checksum = compute_ip_checksum(head, sizeof(*head)); | ||||||
|  | 	printk_debug("Wrote linuxbios table at: %p - %p  checksum %lx\n", | ||||||
|  | 		head, rec, head->table_checksum); | ||||||
|  | 	return (unsigned long)rec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Routines to extract part so the linuxBIOS table or  | ||||||
|  |  * information from the linuxBIOS table after we have written it. | ||||||
|  |  * Currently get_lb_mem relies on a global we can change the | ||||||
|  |  * implementaiton. | ||||||
|  |  */ | ||||||
|  | static struct lb_memory *mem_ranges = 0; | ||||||
|  | struct lb_memory *get_lb_mem(void) | ||||||
|  | { | ||||||
|  | 	return mem_ranges; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unsigned long write_linuxbios_table(  | ||||||
|  | 	unsigned long *processor_map,  | ||||||
|  | 	struct mem_range *ram, | ||||||
|  | 	unsigned long low_table_start, unsigned long low_table_end, | ||||||
|  | 	unsigned long rom_table_startk, unsigned long rom_table_endk) | ||||||
|  | { | ||||||
|  | 	unsigned long table_size; | ||||||
|  | 	struct mem_range *ramp; | ||||||
|  | 	struct lb_header *head; | ||||||
|  | 	struct lb_memory *mem; | ||||||
|  | 	struct lb_record *rec_dest, *rec_src; | ||||||
|  |  | ||||||
|  | 	head = lb_table_init(low_table_end); | ||||||
|  | 	low_table_end = (unsigned long)head; | ||||||
|  | #if HAVE_OPTION_TABLE == 1 | ||||||
|  | 	/* Write the option config table... */ | ||||||
|  | 	rec_dest = lb_new_record(head); | ||||||
|  | 	rec_src = (struct lb_record *)&option_table; | ||||||
|  | 	memcpy(rec_dest,  rec_src, rec_src->size); | ||||||
|  | #endif	 | ||||||
|  | 	mem = lb_memory(head); | ||||||
|  | 	mem_ranges = mem; | ||||||
|  | 	/* I assume there is always ram at address 0 */ | ||||||
|  | 	/* Reserve our tables in low memory */ | ||||||
|  | 	table_size = (low_table_end - low_table_start); | ||||||
|  | 	lb_memory_range(mem, LB_MEM_TABLE, 0, table_size); | ||||||
|  | 	lb_memory_range(mem, LB_MEM_RAM, table_size, (ram[0].sizek << 10) - table_size); | ||||||
|  | 	/* Reserving pci memory mapped  space will keep the kernel from booting seeing | ||||||
|  | 	 * any pci resources. | ||||||
|  | 	 */ | ||||||
|  | 	for(ramp = &ram[1]; ramp->sizek; ramp++) { | ||||||
|  | 		unsigned long startk, endk; | ||||||
|  | 		startk = ramp->basek; | ||||||
|  | 		endk = startk + ramp->sizek; | ||||||
|  | 		if ((startk < rom_table_startk) && (endk > rom_table_startk)) { | ||||||
|  | 			lb_memory_rangek(mem, LB_MEM_RAM, startk, rom_table_startk); | ||||||
|  | 			startk = rom_table_startk; | ||||||
|  | 		} | ||||||
|  | 		if ((startk == rom_table_startk) && (endk > startk)) { | ||||||
|  | 			unsigned long tend; | ||||||
|  | 			tend = rom_table_endk; | ||||||
|  | 			if (tend > endk) { | ||||||
|  | 				tend = endk; | ||||||
|  | 			} | ||||||
|  | 			lb_memory_rangek(mem, LB_MEM_TABLE, rom_table_startk, tend); | ||||||
|  | 			startk = tend; | ||||||
|  | 		} | ||||||
|  | 		if (endk > startk) { | ||||||
|  | 			lb_memory_rangek(mem, LB_MEM_RAM, startk, endk); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Record our motheboard */ | ||||||
|  | 	lb_mainboard(head); | ||||||
|  | 	/* Record our various random string information */ | ||||||
|  | 	lb_strings(head); | ||||||
|  |  | ||||||
|  | 	low_table_end = lb_table_fini(head); | ||||||
|  |  | ||||||
|  | 	/* Remember where my valid memory ranges are */ | ||||||
|  | 	return low_table_end; | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								src/arch/i386/boot/linuxbios_table.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/arch/i386/boot/linuxbios_table.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | #ifndef LINUXBIOS_TABLE_H | ||||||
|  | #define LINUXBIOS_TABLE_H | ||||||
|  |  | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  |  | ||||||
|  | struct mem_range; | ||||||
|  |  | ||||||
|  | /* This file holds function prototypes for building the linuxbios table. */ | ||||||
|  | unsigned long write_linuxbios_table( | ||||||
|  | 	unsigned long *processor_map,  | ||||||
|  | 	struct mem_range *ram, | ||||||
|  | 	unsigned long low_table_start, unsigned long low_table_end, | ||||||
|  | 	unsigned long rom_table_start, unsigned long rom_table_end); | ||||||
|  |  | ||||||
|  | struct lb_header *lb_table_init(unsigned long addr); | ||||||
|  | struct lb_record *lb_first_record(struct lb_header *header); | ||||||
|  | struct lb_record *lb_last_record(struct lb_header *header); | ||||||
|  | struct lb_record *lb_next_record(struct lb_record *rec); | ||||||
|  | struct lb_record *lb_new_record(struct lb_header *header); | ||||||
|  | struct lb_memory *lb_memory(struct lb_header *header); | ||||||
|  | void lb_memory_range(struct lb_memory *mem,  | ||||||
|  | 	uint32_t type, unsigned long startk, unsigned long sizek); | ||||||
|  | struct lb_mainboard *lb_mainboard(struct lb_header *header); | ||||||
|  | unsigned long lb_table_fini(struct lb_header *header); | ||||||
|  |  | ||||||
|  | /* Routines to extract part so the linuxBIOS table or information | ||||||
|  |  * from the linuxBIOS table. | ||||||
|  |  */ | ||||||
|  | struct lb_memory *get_lb_mem(void); | ||||||
|  |  | ||||||
|  | extern struct cmos_option_table option_table; | ||||||
|  |  | ||||||
|  | #endif /* LINUXBIOS_TABLE_H */ | ||||||
							
								
								
									
										93
									
								
								src/arch/i386/boot/pirq_routing.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/arch/i386/boot/pirq_routing.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <arch/pirq_routing.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #ifdef DEBUG | ||||||
|  | void check_pirq_routing_table(void) | ||||||
|  | { | ||||||
|  | 	const u8 *addr; | ||||||
|  | 	const struct irq_routing_table *rt; | ||||||
|  | 	int i; | ||||||
|  | 	u8 sum; | ||||||
|  |  | ||||||
|  | 	printk_info("Checking IRQ routing tables...\n"); | ||||||
|  |  | ||||||
|  | #ifdef(IRQ_SLOT_COUNT) | ||||||
|  | 	if (sizeof(intel_irq_routing_table) != intel_irq_routing_table.size) { | ||||||
|  | 		printk_warning("Inconsistent IRQ routing table size\n"); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	rt = &intel_irq_routing_table; | ||||||
|  | 	addr = (u8 *)rt; | ||||||
|  |  | ||||||
|  | 	sum = 0; | ||||||
|  | 	for (i = 0; i < rt->size; i++) | ||||||
|  | 		sum += addr[i]; | ||||||
|  |  | ||||||
|  | 	printk_debug("%s:%6d:%s() - irq_routing_table located at: 0x%p\n", | ||||||
|  | 	    __FILE__, __LINE__, __FUNCTION__, addr); | ||||||
|  |  | ||||||
|  | 	sum = (unsigned char)(rt->checksum-sum); | ||||||
|  |  | ||||||
|  | 	if (sum != rt->checksum) { | ||||||
|  | 		printk_warning("%s:%6d:%s() - " | ||||||
|  | 		       "checksum is: 0x%02x but should be: 0x%02x\n", | ||||||
|  | 		       __FILE__, __LINE__, __FUNCTION__, rt->checksum, sum); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION || | ||||||
|  | 	    rt->size % 16 || rt->size < sizeof(struct irq_routing_table)) { | ||||||
|  | 		printk_warning("%s:%6d:%s() - " | ||||||
|  | 		       "Interrupt Routing Table not valid\n", | ||||||
|  | 		       __FILE__, __LINE__, __FUNCTION__); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sum = 0; | ||||||
|  | 	for (i=0; i<rt->size; i++) | ||||||
|  | 		sum += addr[i]; | ||||||
|  |  | ||||||
|  | 	if (sum) { | ||||||
|  | 		printk_warning("%s:%6d:%s() - " | ||||||
|  | 		       "checksum error in irq routing table\n", | ||||||
|  | 		       __FILE__, __LINE__, __FUNCTION__); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int verify_copy_pirq_routing_table(unsigned long addr) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	u8 *rt_orig, *rt_curr; | ||||||
|  |  | ||||||
|  | 	rt_curr = (u8*)addr; | ||||||
|  | 	rt_orig = (u8*)&intel_irq_routing_table; | ||||||
|  | 	printk_info("Verifing priq routing tables copy at 0x%x...", addr); | ||||||
|  | 	for (i = 0; i < intel_irq_routing_table.size; i++) { | ||||||
|  | 		if (*(rt_curr + i) != *(rt_orig + i)) { | ||||||
|  | 			printk_info("failed\n"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	printk_info("succeed\n"); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | #define verify_copy_pirq_routing_table(addr) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | unsigned long copy_pirq_routing_table(unsigned long addr) | ||||||
|  | { | ||||||
|  | 	/* Align the table to be 16 byte aligned. */ | ||||||
|  | 	addr += 15; | ||||||
|  | 	addr &= ~15; | ||||||
|  |  | ||||||
|  | 	/* This table must be betweeen 0xf0000 & 0x100000 */ | ||||||
|  | 	printk_info("Copying IRQ routing tables to 0x%x...", addr); | ||||||
|  | 	memcpy((void *)addr, &intel_irq_routing_table, intel_irq_routing_table.size); | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | 	verify_copy_pirq_routing_table(addr); | ||||||
|  | 	return addr + intel_irq_routing_table.size; | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								src/arch/i386/boot/tables.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/arch/i386/boot/tables.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <cpu/cpu.h> | ||||||
|  | #include <boot/tables.h> | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  | #include <arch/pirq_routing.h> | ||||||
|  | #include <arch/smp/mpspec.h> | ||||||
|  | #include "linuxbios_table.h" | ||||||
|  |  | ||||||
|  | #if CONFIG_SMP && CONFIG_MAX_PHYSICAL_CPUS && (CONFIG_MAX_PHYSICAL_CPUS < CONFIG_MAX_CPUS) | ||||||
|  | static void remove_logical_cpus(unsigned long *processor_map) | ||||||
|  | { | ||||||
|  | 	/* To turn off hyperthreading just remove the logical | ||||||
|  | 	 * cpus from the processor map. | ||||||
|  | 	 */ | ||||||
|  | 	int disable_logical_cpus = !CONFIG_LOGICAL_CPUS; | ||||||
|  | 	if (get_option(&disable_logical_cpus,"hyper_threading")) { | ||||||
|  | 		disable_logical_cpus = !CONFIG_LOGICAL_CPUS; | ||||||
|  | 	} | ||||||
|  | 	if (disable_logical_cpus) { | ||||||
|  | 		/* disable logical cpus */ | ||||||
|  | 		int cnt; | ||||||
|  | 		for(cnt=MAX_PHYSICAL_CPUS;cnt<MAX_CPUS;cnt++) | ||||||
|  | 			processor_map[cnt]=0; | ||||||
|  | 		printk_debug("logical cpus disabled\n"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | #define remove_logical_cpus(processor_map) do {} while(0)  | ||||||
|  |  | ||||||
|  | #endif /* CONFIG_SMP && CONFIG_MAX_PHYSICAL_CPUS */ | ||||||
|  |  | ||||||
|  | struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_map) | ||||||
|  | { | ||||||
|  | 	unsigned long low_table_start, low_table_end; | ||||||
|  | 	unsigned long rom_table_start, rom_table_end; | ||||||
|  |  | ||||||
|  | 	rom_table_start = 0xf0000; | ||||||
|  | 	rom_table_end =   0xf0000; | ||||||
|  | 	/* Start low addr at 16 bytes instead of 0 because of a buglet | ||||||
|  | 	 * in the generic linux unzip code, as it tests for the a20 line. | ||||||
|  | 	 */ | ||||||
|  | 	low_table_start = 0; | ||||||
|  | 	low_table_end = 16; | ||||||
|  |  | ||||||
|  | 	post_code(0x9a); | ||||||
|  | 	check_pirq_routing_table(); | ||||||
|  | 	/* This table must be betweeen 0xf0000 & 0x100000 */ | ||||||
|  | 	rom_table_end = copy_pirq_routing_table(rom_table_end); | ||||||
|  | 	rom_table_end = (rom_table_end + 1023) & ~1023; | ||||||
|  |  | ||||||
|  | 	/* copy the smp block to address 0 */ | ||||||
|  | 	post_code(0x96); | ||||||
|  | 	/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ | ||||||
|  | 	remove_logical_cpus(processor_map); | ||||||
|  | 	low_table_end = write_smp_table(low_table_end, processor_map); | ||||||
|  |  | ||||||
|  | 	/* Don't write anything in the traditional x86 BIOS data segment */ | ||||||
|  | 	if (low_table_end < 0x500) { | ||||||
|  | 		low_table_end = 0x500; | ||||||
|  | 	} | ||||||
|  | 	/* The linuxbios table must be in 0-4K or 960K-1M */ | ||||||
|  | 	write_linuxbios_table(processor_map, mem, | ||||||
|  | 			      low_table_start, low_table_end, | ||||||
|  | 			      rom_table_start >> 10, rom_table_end >> 10); | ||||||
|  |  | ||||||
|  | 	return get_lb_mem(); | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/arch/i386/include/arch/asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/arch/i386/include/arch/asm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | #ifndef ASM_H | ||||||
|  | #define	ASM_H | ||||||
|  |  | ||||||
|  | #define ASSEMBLER | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Bootstrap code for the STPC Consumer | ||||||
|  |  * Copyright (c) 1999 by Net Insight AB. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define	I386_ALIGN_TEXT	0 | ||||||
|  | #define	I386_ALIGN_DATA	0 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *	XXX | ||||||
|  |  */ | ||||||
|  | #ifdef __ELF__ | ||||||
|  | #define	EXT(x)		x | ||||||
|  | #else | ||||||
|  | #define	EXT(x)		_ ## x | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define	STATIC(x)	.align I386_ALIGN_TEXT; EXT(x):  | ||||||
|  | #define	GLOBAL(x)	.globl EXT(x); STATIC(x) | ||||||
|  | #define	ENTRY(x)	.text; GLOBAL(x) | ||||||
|  |  | ||||||
|  | #endif /* ASM_H */ | ||||||
							
								
								
									
										8
									
								
								src/arch/i386/include/arch/boot/boot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/arch/i386/include/arch/boot/boot.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | #ifndef ASM_I386_BOOT_H | ||||||
|  | #define ASM_I386_BOOT_H | ||||||
|  |  | ||||||
|  | #define ELF_CLASS	ELFCLASS32 | ||||||
|  | #define ELF_DATA	ELFDATA2LSB | ||||||
|  | #define ELF_ARCH	EM_386 | ||||||
|  |  | ||||||
|  | #endif /* ASM_I386_BOOT_H */ | ||||||
							
								
								
									
										369
									
								
								src/arch/i386/include/arch/intel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								src/arch/i386/include/arch/intel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,369 @@ | |||||||
|  | /* | ||||||
|  | This software and ancillary information (herein called SOFTWARE ) | ||||||
|  | called LinuxBIOS          is made available under the terms described | ||||||
|  | here.  The SOFTWARE has been approved for release with associated | ||||||
|  | LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has | ||||||
|  | been authored by an employee or employees of the University of | ||||||
|  | California, operator of the Los Alamos National Laboratory under | ||||||
|  | Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The | ||||||
|  | U.S. Government has rights to use, reproduce, and distribute this | ||||||
|  | SOFTWARE.  The public may copy, distribute, prepare derivative works | ||||||
|  | and publicly display this SOFTWARE without charge, provided that this | ||||||
|  | Notice and any statement of authorship are reproduced on all copies. | ||||||
|  | Neither the Government nor the University makes any warranty, express | ||||||
|  | or implied, or assumes any liability or responsibility for the use of | ||||||
|  | this SOFTWARE.  If SOFTWARE is modified to produce derivative works, | ||||||
|  | such modified SOFTWARE should be clearly marked, so as not to confuse | ||||||
|  | it with the version available from LANL. | ||||||
|  |  */ | ||||||
|  | /* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL | ||||||
|  |  * rminnich@lanl.gov | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef ROM_INTEL_H | ||||||
|  | #define	ROM_INTEL_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Bootstrap code for the Intel | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /*  | ||||||
|  |  *	Config registers.  | ||||||
|  |  */ | ||||||
|  | /* yeah, yeah, I know these are macros, which is bad. Don't forget:  | ||||||
|  |  * we have almost no assembly, so I am not worrying just yet about this.  | ||||||
|  |  * we'll fix it someday if we care. My guess is we won't. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* well we want functions. But first we want to see it work at all. */ | ||||||
|  | #undef FUNCTIONS | ||||||
|  | #ifndef FUNCTIONS | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define RET_LABEL(label)	\ | ||||||
|  | 	jmp label##_done | ||||||
|  |  | ||||||
|  | #define CALL_LABEL(label)	\ | ||||||
|  | 	jmp label		;\ | ||||||
|  | label##_done: | ||||||
|  |  | ||||||
|  | #define CALLSP(func) \ | ||||||
|  | 	lea	0f, %esp	; \ | ||||||
|  | 	jmp func		; \ | ||||||
|  | 0: | ||||||
|  |  | ||||||
|  | #define RETSP \ | ||||||
|  | 	jmp *%esp | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define DELAY(x) mov x, %ecx ;\ | ||||||
|  |         1: loop 1b ;\ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_WRITE_CONFIG_BYTE | ||||||
|  | 	 * Arguments:	%eax address to write to (includes bus, device, function, &offset) | ||||||
|  | 	 *              %dl byte to write | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	none | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%eax, %edx | ||||||
|  | 	 * Effects:	writes a single byte to pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *              And the tricks it does cannot scale beyond writing a single byte. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the data byte | ||||||
|  | 	 *              in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[3] it stores the byte to write. | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_WRITE_CONFIG_BYTE \ | ||||||
|  | 	shll $8,   %edx		; \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andb $0x3, %dl		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	movb %dh,  %al		; \ | ||||||
|  | 	movb $0,   %dh		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	outb %al,  %dx | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_WRITE_CONFIG_WORD | ||||||
|  | 	 * Arguments:	%eax address to write to (includes bus, device, function, &offset) | ||||||
|  | 	 *              %ecx word to write | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	none | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%eax, %edx | ||||||
|  | 	 * Preserved:   %ecx | ||||||
|  | 	 * Effects:	writes a single byte to pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the least significant | ||||||
|  | 	 *              bits of the address in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_WRITE_CONFIG_WORD \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andl $0x3, %edx		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	movl %ecx, %eax		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	outw %ax,  %dx | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_WRITE_CONFIG_DWORD | ||||||
|  | 	 * Arguments:	%eax address to write to (includes bus, device, function, &offset) | ||||||
|  | 	 *              %ecx dword to write | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	none | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%eax, %edx | ||||||
|  | 	 * Preserved:   %ecx | ||||||
|  | 	 * Effects:	writes a single byte to pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the least significant | ||||||
|  | 	 *              bits of the address in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_WRITE_CONFIG_DWORD \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andl $0x3, %edx		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	movl %ecx, %eax		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	outl %eax,  %dx | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_READ_CONFIG_BYTE | ||||||
|  | 	 * Arguments:	%eax address to read from (includes bus, device, function, &offset) | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	%al Byte read | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%eax, %edx | ||||||
|  | 	 * Effects:	reads a single byte from pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the least significant | ||||||
|  | 	 *              bits of the address in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_READ_CONFIG_BYTE \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andl $0x3, %edx		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	inb  %dx,  %al | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_READ_CONFIG_WORD | ||||||
|  | 	 * Arguments:	%eax address to read from (includes bus, device, function, &offset) | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	%ax word read | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%eax, %edx | ||||||
|  | 	 * Effects:	reads a 2 bytes from pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the least significant | ||||||
|  | 	 *              bits of the address in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_READ_CONFIG_WORD \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andl $0x3, %edx		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	inw  %dx,  %ax | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Macro:	PCI_READ_CONFIG_DWORD | ||||||
|  | 	 * Arguments:	%eax address to read from (includes bus, device, function, &offset) | ||||||
|  | 	 * | ||||||
|  | 	 * Results:	%eax | ||||||
|  | 	 * | ||||||
|  | 	 * Trashed:	%edx | ||||||
|  | 	 * Effects:	reads 4 bytes from pci config space | ||||||
|  | 	 * | ||||||
|  | 	 * Notes:	This routine is optimized for minimal register usage. | ||||||
|  | 	 *                | ||||||
|  | 	 *              What it does is almost simple. | ||||||
|  | 	 *              It preserves %eax (baring special bits) until it is written | ||||||
|  | 	 *              out to the appropriate port.  And hides the least significant | ||||||
|  | 	 *              bits of the address in the high half of edx. | ||||||
|  | 	 * | ||||||
|  | 	 *              In %edx[2] it stores the lower three bits of the address. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define PCI_READ_CONFIG_DWORD \ | ||||||
|  | 	movb %al,  %dl		; \ | ||||||
|  | 	andl $0x3, %edx		; \ | ||||||
|  | 	shll $16,  %edx		; \ | ||||||
|  | 	\ | ||||||
|  | 	orl  $0x80000000, %eax	; \ | ||||||
|  | 	andl $0xfffffffc, %eax	; \ | ||||||
|  | 	movw $0xcf8, %dx	; \ | ||||||
|  | 	outl %eax,  %dx		; \ | ||||||
|  | 	\ | ||||||
|  | 	shrl $16,  %edx		; \ | ||||||
|  | 	addl $0xcfc, %edx	; \ | ||||||
|  | 	inl  %dx,  %eax | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define CS_READ(which)  \ | ||||||
|  |                  mov  $0x80000000,%eax ; \ | ||||||
|  |                  mov  which,%ax ; \ | ||||||
|  |                  and  $0xfc,%al            /* clear bits 1-0 */ ; \ | ||||||
|  |                  mov  $0xcf8,%dx           /* port 0xcf8 ?*/ ; \ | ||||||
|  |                  outl  %eax,%dx             /* open up CS config */ ; \ | ||||||
|  |                  add  $0x4,%dl             /* 0xcfc data port 0 */ ; \ | ||||||
|  |                  mov  which,%al ; \ | ||||||
|  |                  and  $0x3,%al             /* only bits 1-0 */ ; \ | ||||||
|  |                  add  %al,%dl ; \ | ||||||
|  |                  inb   %dx,%al              /* read  */ ; \ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define CS_WRITE(which, data)  \ | ||||||
|  |                  mov  $0x80000000,%eax       /* 32bit word with bit 31 set */ ; \ | ||||||
|  |                  mov  which,%ax             /* put the reg# in the low part */ ; \ | ||||||
|  |                  and  $0xfc,%al             /* dword align the reg# */ ; \ | ||||||
|  |                  mov  $0xcf8,%dx            /* enable port  */ ; \ | ||||||
|  |                  outl  %eax,%dx ; \ | ||||||
|  |                  add  $0x4,%dl             /* 1st data port */ ; \ | ||||||
|  |                  mov  which,%ax             /* register# */ ; \ | ||||||
|  |                  and  $0x3,%ax ; \ | ||||||
|  |                  add  %al,%dl ; \ | ||||||
|  | 		 mov  data, %al ; \ | ||||||
|  |                  outb  %al,%dx                /* write to reg */  | ||||||
|  |  | ||||||
|  | #define REGBIS(which, bis) \ | ||||||
|  | 	CS_READ(which) ;\ | ||||||
|  | 	movb bis, %cl ;\ | ||||||
|  | 	orb %al, %cl ;\ | ||||||
|  | 	CS_WRITE(which, %cl) | ||||||
|  |  | ||||||
|  | #define REGBIC(which, bic) \ | ||||||
|  | 	CS_READ(which) ;\ | ||||||
|  | 	movb bic, %cl ;\ | ||||||
|  | 	notb %cl ;\ | ||||||
|  | 	andb %al, %cl ;\ | ||||||
|  | 	CS_WRITE(which, %cl) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* macro to BIC and BIS a reg. calls read a reg, | ||||||
|  |  * does a BIC and then a BIS on it. | ||||||
|  |  * to clear no bits, make BIC 0. | ||||||
|  |  * to set no bits, make BIS 0 | ||||||
|  |  */ | ||||||
|  | #define REGBICBIS(which, bic, bis) \ | ||||||
|  | 	CS_READ(which) ;\ | ||||||
|  | 	movb bic, %cl ;\ | ||||||
|  | 	notb %cl ;\ | ||||||
|  | 	andb %cl, %al ;\ | ||||||
|  | 	movb bis, %cl ;\ | ||||||
|  | 	orb %al, %cl ;\ | ||||||
|  | 	CS_WRITE(which, %cl) | ||||||
|  |  | ||||||
|  | #else | ||||||
|  | NO FUNCTIONS YET! | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* originally this macro was from STPC BIOS */ | ||||||
|  | #define	intel_chip_post_macro(value)			 \ | ||||||
|  | 	movb	$value, %al				; \ | ||||||
|  | 	outb	%al, $0x80 | ||||||
|  |  | ||||||
|  | #define INTEL_PDATA_MAGIC 0xdeadbeef | ||||||
|  |  | ||||||
|  | /* SLOW_DOWN_IO is a delay we can use that is roughly cpu neutral, | ||||||
|  |  * and can be used before memory or timer chips come up. | ||||||
|  |  * Since this hits the isa bus it's roughly | ||||||
|  |  */ | ||||||
|  | #define SLOW_DOWN_IO inb $0x80, %al | ||||||
|  |  | ||||||
|  | #endif /* ROM_INTEL_H */ | ||||||
							
								
								
									
										76
									
								
								src/arch/i386/include/arch/io.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/arch/i386/include/arch/io.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | #ifndef _ASM_IO_H | ||||||
|  | #define _ASM_IO_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This file contains the definitions for the x86 IO instructions | ||||||
|  |  * inb/inw/inl/outb/outw/outl and the "string versions" of the same | ||||||
|  |  * (insb/insw/insl/outsb/outsw/outsl). | ||||||
|  |  * | ||||||
|  |  * This file is not meant to be obfuscating: it's just complicated | ||||||
|  |  * to (a) handle it all in a way that makes gcc able to optimize it | ||||||
|  |  * as well as possible and (b) trying to avoid writing the same thing | ||||||
|  |  * over and over again with slight variations and possibly making a | ||||||
|  |  * mistake somewhere. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  /* | ||||||
|  |   *  Bit simplified and optimized by Jan Hubicka | ||||||
|  |   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. | ||||||
|  |   */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Talk about misusing macros.. | ||||||
|  |  */ | ||||||
|  | #define __OUT1(s,x) \ | ||||||
|  | extern inline void out##s(unsigned x value, unsigned short port) { | ||||||
|  |  | ||||||
|  | #define __OUT2(s,s1,s2) \ | ||||||
|  | __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" | ||||||
|  |  | ||||||
|  | #define __OUT(s,s1,x) \ | ||||||
|  | __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); }  | ||||||
|  |  | ||||||
|  | #define __IN1(s) \ | ||||||
|  | extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; | ||||||
|  |  | ||||||
|  | #define __IN2(s,s1,s2) \ | ||||||
|  | __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" | ||||||
|  |  | ||||||
|  | #define __IN(s,s1,i...) \ | ||||||
|  | __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; }  | ||||||
|  |  | ||||||
|  | #define __INS(s) \ | ||||||
|  | extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ | ||||||
|  | { __asm__ __volatile__ ("cld ; rep ; ins" #s \ | ||||||
|  | : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } | ||||||
|  |  | ||||||
|  | #define __OUTS(s) \ | ||||||
|  | extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ | ||||||
|  | { __asm__ __volatile__ ("cld ; rep ; outs" #s \ | ||||||
|  | : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } | ||||||
|  |  | ||||||
|  | #define RETURN_TYPE unsigned char | ||||||
|  | __IN(b,"") | ||||||
|  | #undef RETURN_TYPE | ||||||
|  | #define RETURN_TYPE unsigned short | ||||||
|  | __IN(w,"") | ||||||
|  | #undef RETURN_TYPE | ||||||
|  | #define RETURN_TYPE unsigned int | ||||||
|  | __IN(l,"") | ||||||
|  | #undef RETURN_TYPE | ||||||
|  |  | ||||||
|  | __OUT(b,"b",char) | ||||||
|  | __OUT(w,"w",short) | ||||||
|  | __OUT(l,,int) | ||||||
|  |  | ||||||
|  | __INS(b) | ||||||
|  | __INS(w) | ||||||
|  | __INS(l) | ||||||
|  |  | ||||||
|  | __OUTS(b) | ||||||
|  | __OUTS(w) | ||||||
|  | __OUTS(l) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								src/arch/i386/include/arch/pciconf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/arch/i386/include/arch/pciconf.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | #ifndef PCI_CONF_REG_INDEX | ||||||
|  |  | ||||||
|  | // These are defined in the PCI spec, and hence are theoretically | ||||||
|  | // inclusive of ANYTHING that uses a PCI bus.  | ||||||
|  | #define	PCI_CONF_REG_INDEX	0xcf8 | ||||||
|  | #define	PCI_CONF_REG_DATA	0xcfc | ||||||
|  | #define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where)) | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										54
									
								
								src/arch/i386/include/arch/pirq_routing.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/arch/i386/include/arch/pirq_routing.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | #ifndef ARCH_PIRQ_ROUTING_H | ||||||
|  | #define ARCH_PIRQ_ROUTING_H | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | #define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) | ||||||
|  | #define PIRQ_VERSION 0x0100 | ||||||
|  |  | ||||||
|  | struct irq_info { | ||||||
|  | 	uint8_t bus, devfn;			/* Bus, device and function */ | ||||||
|  | 	struct { | ||||||
|  | 		uint8_t link;			/* IRQ line ID, chipset dependent, 0=not routed */ | ||||||
|  | 		uint16_t bitmap;		/* Available IRQs */ | ||||||
|  | 	} __attribute__((packed)) irq[4]; | ||||||
|  | 	uint8_t slot;				/* Slot number, 0=onboard */ | ||||||
|  | 	uint8_t rfu; | ||||||
|  | } __attribute__((packed)); | ||||||
|  |  | ||||||
|  | #if defined(IRQ_SLOT_COUNT) | ||||||
|  | #define IRQ_SLOTS_COUNT IRQ_SLOT_COUNT | ||||||
|  | #elif (__GNUC__ < 3) | ||||||
|  | #define IRQ_SLOTS_COUNT 1 | ||||||
|  | #else | ||||||
|  | #define IRQ_SLOTS_COUNT | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct irq_routing_table { | ||||||
|  | 	uint32_t signature;			/* PIRQ_SIGNATURE should be here */ | ||||||
|  | 	uint16_t version;			/* PIRQ_VERSION */ | ||||||
|  | 	uint16_t size;				/* Table size in bytes */ | ||||||
|  | 	uint8_t  rtr_bus, rtr_devfn;		/* Where the interrupt router lies */ | ||||||
|  | 	uint16_t exclusive_irqs;		/* IRQs devoted exclusively to PCI usage */ | ||||||
|  | 	uint16_t rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */ | ||||||
|  | 	uint32_t miniport_data;			/* Crap */ | ||||||
|  | 	uint8_t  rfu[11]; | ||||||
|  | 	uint8_t  checksum;			/* Modulo 256 checksum must give zero */ | ||||||
|  | 	struct irq_info slots[IRQ_SLOTS_COUNT]; | ||||||
|  | } __attribute__((packed)); | ||||||
|  |  | ||||||
|  | extern const struct irq_routing_table intel_irq_routing_table; | ||||||
|  |  | ||||||
|  | #if defined(DEBUG) && defined(HAVE_PIRQ_TABLE) | ||||||
|  | void check_pirq_routing_table(void); | ||||||
|  | #else | ||||||
|  | #define check_pirq_routing_table() do {} while(0) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(HAVE_PIRQ_TABLE) | ||||||
|  | unsigned long copy_pirq_routing_table(unsigned long start); | ||||||
|  | #else | ||||||
|  | #define copy_pirq_routing_table(start) (start) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* ARCH_PIRQ_ROUTING_H */ | ||||||
							
								
								
									
										10
									
								
								src/arch/i386/include/arch/rom_segs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/arch/i386/include/arch/rom_segs.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | #ifndef ROM_SEGS_H | ||||||
|  | #define ROM_SEGS_H | ||||||
|  |  | ||||||
|  | #define ROM_CODE_SEG 0x08 | ||||||
|  | #define ROM_DATA_SEG 0x10 | ||||||
|  |  | ||||||
|  | #define CACHE_RAM_CODE_SEG 0x18 | ||||||
|  | #define CACHE_RAM_DATA_SEG 0x20 | ||||||
|  |  | ||||||
|  | #endif /* ROM_SEGS_H */ | ||||||
							
								
								
									
										84
									
								
								src/arch/i386/include/arch/romcc_io.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/arch/i386/include/arch/romcc_io.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | static void outb(unsigned char value, unsigned short port) | ||||||
|  | { | ||||||
|  | 	__builtin_outb(value, port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void outw(unsigned short value, unsigned short port) | ||||||
|  | { | ||||||
|  | 	__builtin_outw(value, port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void outl(unsigned int value, unsigned short port) | ||||||
|  | { | ||||||
|  | 	__builtin_outl(value, port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static unsigned char inb(unsigned short port) | ||||||
|  | { | ||||||
|  | 	return __builtin_inb(port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static unsigned char inw(unsigned short port) | ||||||
|  | { | ||||||
|  | 	return __builtin_inw(port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned char inl(unsigned short port) | ||||||
|  | { | ||||||
|  | 	return __builtin_inl(port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void hlt(void) | ||||||
|  | { | ||||||
|  | 	__builtin_hlt(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where) | ||||||
|  | { | ||||||
|  | 	return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned char pcibios_read_config_byte( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	return inb(0xCFC + (where & 3)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned short pcibios_read_config_word( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	return inw(0xCFC + (where & 2)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned int pcibios_read_config_dword( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	return inl(0xCFC); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void pcibios_write_config_byte( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where, unsigned char value) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	outb(value, 0xCFC + (where & 3)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pcibios_write_config_word( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where, unsigned short value) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	outw(value, 0xCFC + (where & 2)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pcibios_write_config_dword( | ||||||
|  | 	unsigned char bus, unsigned devfn, unsigned where, unsigned int value) | ||||||
|  | { | ||||||
|  | 	outl(config_cmd(bus, devfn, where), 0xCF8); | ||||||
|  | 	outl(value, 0xCFC); | ||||||
|  | } | ||||||
							
								
								
									
										282
									
								
								src/arch/i386/include/arch/smp/mpspec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								src/arch/i386/include/arch/smp/mpspec.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,282 @@ | |||||||
|  | #ifndef __ASM_MPSPEC_H | ||||||
|  | #define __ASM_MPSPEC_H | ||||||
|  |  | ||||||
|  | #ifdef HAVE_MP_TABLE | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Structure definitions for SMP machines following the | ||||||
|  |  * Intel Multiprocessing Specification 1.1 and 1.4. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This tag identifies where the SMP configuration | ||||||
|  |  * information is.  | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  | #define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_') | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * a maximum of 16 APICs with the current APIC ID architecture. | ||||||
|  |  */ | ||||||
|  | #define MAX_APICS 16 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating) | ||||||
|  |  | ||||||
|  | struct intel_mp_floating | ||||||
|  | { | ||||||
|  | 	char mpf_signature[4];		/* "_MP_" 			*/ | ||||||
|  | 	unsigned long mpf_physptr;	/* Configuration table address	*/ | ||||||
|  | 	unsigned char mpf_length;	/* Our length (paragraphs)	*/ | ||||||
|  | 	unsigned char mpf_specification;/* Specification version	*/ | ||||||
|  | 	unsigned char mpf_checksum;	/* Checksum (makes sum 0)	*/ | ||||||
|  | 	unsigned char mpf_feature1;	/* Standard or configuration ? 	*/ | ||||||
|  | 	unsigned char mpf_feature2;	/* Bit7 set for IMCR|PIC	*/ | ||||||
|  | 	unsigned char mpf_feature3;	/* Unused (0)			*/ | ||||||
|  | 	unsigned char mpf_feature4;	/* Unused (0)			*/ | ||||||
|  | 	unsigned char mpf_feature5;	/* Unused (0)			*/ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mp_config_table | ||||||
|  | { | ||||||
|  | 	char mpc_signature[4]; | ||||||
|  | #define MPC_SIGNATURE "PCMP" | ||||||
|  | 	unsigned short mpc_length;	/* Size of table */ | ||||||
|  | 	char  mpc_spec;			/* 0x01 */ | ||||||
|  | 	char  mpc_checksum; | ||||||
|  | 	char  mpc_oem[8]; | ||||||
|  | 	char  mpc_productid[12]; | ||||||
|  | 	unsigned long mpc_oemptr;	/* 0 if not present */ | ||||||
|  | 	unsigned short mpc_oemsize;	/* 0 if not present */ | ||||||
|  | 	unsigned short mpc_entry_count; | ||||||
|  | 	unsigned long mpc_lapic;	/* APIC address */ | ||||||
|  | 	unsigned short mpe_length;	/* Extended Table size */ | ||||||
|  | 	unsigned char mpe_checksum;	/* Extended Table checksum */ | ||||||
|  | 	unsigned char reserved; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Followed by entries */ | ||||||
|  |  | ||||||
|  | #define	MP_PROCESSOR	0 | ||||||
|  | #define	MP_BUS		1 | ||||||
|  | #define	MP_IOAPIC	2 | ||||||
|  | #define	MP_INTSRC	3 | ||||||
|  | #define	MP_LINTSRC	4 | ||||||
|  |  | ||||||
|  | struct mpc_config_processor | ||||||
|  | { | ||||||
|  | 	unsigned char mpc_type; | ||||||
|  | 	unsigned char mpc_apicid;	/* Local APIC number */ | ||||||
|  | 	unsigned char mpc_apicver;	/* Its versions */ | ||||||
|  | 	unsigned char mpc_cpuflag; | ||||||
|  | #define MPC_CPU_ENABLED		1	/* Processor is available */ | ||||||
|  | #define MPC_CPU_BOOTPROCESSOR	2	/* Processor is the BP */ | ||||||
|  | 	unsigned long mpc_cpufeature;		 | ||||||
|  | #define MPC_CPU_STEPPING_MASK 0x0F | ||||||
|  | #define MPC_CPU_MODEL_MASK	0xF0 | ||||||
|  | #define MPC_CPU_FAMILY_MASK	0xF00 | ||||||
|  | 	unsigned long mpc_featureflag;	/* CPUID feature value */ | ||||||
|  | 	unsigned long mpc_reserved[2]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mpc_config_bus | ||||||
|  | { | ||||||
|  | 	unsigned char mpc_type; | ||||||
|  | 	unsigned char mpc_busid; | ||||||
|  | 	unsigned char mpc_bustype[6] __attribute((packed)); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define BUSTYPE_EISA	"EISA" | ||||||
|  | #define BUSTYPE_ISA	"ISA" | ||||||
|  | #define BUSTYPE_INTERN	"INTERN"	/* Internal BUS */ | ||||||
|  | #define BUSTYPE_MCA	"MCA" | ||||||
|  | #define BUSTYPE_VL	"VL"		/* Local bus */ | ||||||
|  | #define BUSTYPE_PCI	"PCI" | ||||||
|  | #define BUSTYPE_PCMCIA	"PCMCIA" | ||||||
|  |  | ||||||
|  | struct mpc_config_ioapic | ||||||
|  | { | ||||||
|  | 	unsigned char mpc_type; | ||||||
|  | 	unsigned char mpc_apicid; | ||||||
|  | 	unsigned char mpc_apicver; | ||||||
|  | 	unsigned char mpc_flags; | ||||||
|  | #define MPC_APIC_USABLE		0x01 | ||||||
|  | 	unsigned long mpc_apicaddr; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mpc_config_intsrc | ||||||
|  | { | ||||||
|  | 	unsigned char mpc_type; | ||||||
|  | 	unsigned char mpc_irqtype; | ||||||
|  | 	unsigned short mpc_irqflag; | ||||||
|  | 	unsigned char mpc_srcbus; | ||||||
|  | 	unsigned char mpc_srcbusirq; | ||||||
|  | 	unsigned char mpc_dstapic; | ||||||
|  | 	unsigned char mpc_dstirq; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum mp_irq_source_types { | ||||||
|  | 	mp_INT = 0, | ||||||
|  | 	mp_NMI = 1, | ||||||
|  | 	mp_SMI = 2, | ||||||
|  | 	mp_ExtINT = 3 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define MP_IRQ_POLARITY_DEFAULT	0x0 | ||||||
|  | #define MP_IRQ_POLARITY_HIGH	0x1 | ||||||
|  | #define MP_IRQ_POLARITY_LOW	0x3 | ||||||
|  | #define MP_IRQ_POLARITY_MASK    0x3 | ||||||
|  | #define MP_IRQ_TRIGGER_DEFAULT	0x0 | ||||||
|  | #define MP_IRQ_TRIGGER_EDGE	0x4 | ||||||
|  | #define MP_IRQ_TRIGGER_LEVEL	0xc | ||||||
|  | #define MP_IRQ_TRIGGER_MASK     0xc | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct mpc_config_lintsrc | ||||||
|  | { | ||||||
|  | 	unsigned char mpc_type; | ||||||
|  | 	unsigned char mpc_irqtype; | ||||||
|  | 	unsigned short mpc_irqflag; | ||||||
|  | 	unsigned char mpc_srcbusid; | ||||||
|  | 	unsigned char mpc_srcbusirq; | ||||||
|  | 	unsigned char mpc_destapic;	 | ||||||
|  | #define MP_APIC_ALL	0xFF | ||||||
|  | 	unsigned char mpc_destapiclint; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *	Default configurations | ||||||
|  |  * | ||||||
|  |  *	1	2 CPU ISA 82489DX | ||||||
|  |  *	2	2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining | ||||||
|  |  *	3	2 CPU EISA 82489DX | ||||||
|  |  *	4	2 CPU MCA 82489DX | ||||||
|  |  *	5	2 CPU ISA+PCI | ||||||
|  |  *	6	2 CPU EISA+PCI | ||||||
|  |  *	7	2 CPU MCA+PCI | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define MAX_IRQ_SOURCES 128 | ||||||
|  | #define MAX_MP_BUSSES 32 | ||||||
|  | enum mp_bustype { | ||||||
|  | 	MP_BUS_ISA, | ||||||
|  | 	MP_BUS_EISA, | ||||||
|  | 	MP_BUS_PCI, | ||||||
|  | 	MP_BUS_MCA | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Followed by entries */ | ||||||
|  |  | ||||||
|  | #define	MPE_SYSTEM_ADDRESS_SPACE	0x80 | ||||||
|  | #define	MPE_BUS_HIERARCHY		0x81 | ||||||
|  | #define	MPE_COMPATIBILITY_ADDRESS_SPACE	0x82 | ||||||
|  |  | ||||||
|  | struct mp_exten_config { | ||||||
|  | 	unsigned char mpe_type; | ||||||
|  | 	unsigned char mpe_length; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct mp_exten_config *mpe_t; | ||||||
|  |  | ||||||
|  | struct mp_exten_system_address_space { | ||||||
|  | 	unsigned char mpe_type; | ||||||
|  | 	unsigned char mpe_length; | ||||||
|  | 	unsigned char mpe_busid; | ||||||
|  | 	unsigned char mpe_address_type; | ||||||
|  | #define ADDRESS_TYPE_IO       0 | ||||||
|  | #define ADDRESS_TYPE_MEM      1 | ||||||
|  | #define ADDRESS_TYPE_PREFETCH 2 | ||||||
|  | 	unsigned int  mpe_address_base_low; | ||||||
|  | 	unsigned int  mpe_address_base_high; | ||||||
|  | 	unsigned int  mpe_address_length_low; | ||||||
|  | 	unsigned int  mpe_address_length_high; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mp_exten_bus_hierarchy { | ||||||
|  | 	unsigned char mpe_type; | ||||||
|  | 	unsigned char mpe_length; | ||||||
|  | 	unsigned char mpe_busid; | ||||||
|  | 	unsigned char mpe_bus_info; | ||||||
|  | #define BUS_SUBTRACTIVE_DECODE 1 | ||||||
|  | 	unsigned char mpe_parent_busid; | ||||||
|  | 	unsigned char reserved[3]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct mp_exten_compatibility_address_space { | ||||||
|  | 	unsigned char mpe_type; | ||||||
|  | 	unsigned char mpe_length; | ||||||
|  | 	unsigned char mpe_busid; | ||||||
|  | 	unsigned char mpe_address_modifier; | ||||||
|  | #define ADDRESS_RANGE_SUBTRACT 1 | ||||||
|  | #define ADDRESS_RANGE_ADD      0 | ||||||
|  | 	unsigned int  mpe_range_list; | ||||||
|  | #define RANGE_LIST_IO_ISA	0	 | ||||||
|  | 	/* X100 - X3FF | ||||||
|  | 	 * X500 - X7FF | ||||||
|  | 	 * X900 - XBFF | ||||||
|  | 	 * XD00 - XFFF | ||||||
|  | 	 */ | ||||||
|  | #define RANGE_LIST_IO_VGA	1 | ||||||
|  | 	/* X3B0 - X3BB | ||||||
|  | 	 * X3C0 - X3DF | ||||||
|  | 	 * X7B0 - X7BB | ||||||
|  | 	 * X7C0 - X7DF | ||||||
|  | 	 * XBB0 - XBBB | ||||||
|  | 	 * XBC0 - XBDF | ||||||
|  | 	 * XFB0 - XFBB | ||||||
|  | 	 * XFC0 - XCDF | ||||||
|  | 	 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Default local apic addr */ | ||||||
|  | #define LAPIC_ADDR 0xFEE00000 | ||||||
|  |  | ||||||
|  | void *smp_next_mpc_entry(struct mp_config_table *mc); | ||||||
|  | void *smp_next_mpe_entry(struct mp_config_table *mc); | ||||||
|  |  | ||||||
|  | void smp_write_processor(struct mp_config_table *mc, | ||||||
|  | 	unsigned char apicid, unsigned char apicver, | ||||||
|  | 	unsigned char cpuflag, unsigned int cpufeature, | ||||||
|  | 	unsigned int featureflag); | ||||||
|  | void smp_write_processors(struct mp_config_table *mc,  | ||||||
|  | 	unsigned long *processor_map); | ||||||
|  | void smp_write_bus(struct mp_config_table *mc, | ||||||
|  | 	unsigned char id, unsigned char *bustype); | ||||||
|  | void smp_write_ioapic(struct mp_config_table *mc, | ||||||
|  | 	unsigned char id, unsigned char ver,  | ||||||
|  | 	unsigned long apicaddr); | ||||||
|  | void smp_write_intsrc(struct mp_config_table *mc, | ||||||
|  | 	unsigned char irqtype, unsigned short irqflag, | ||||||
|  | 	unsigned char srcbus, unsigned char srcbusirq, | ||||||
|  | 	unsigned char dstapic, unsigned char dstirq); | ||||||
|  | void smp_write_lintsrc(struct mp_config_table *mc, | ||||||
|  | 	unsigned char irqtype, unsigned short irqflag, | ||||||
|  | 	unsigned char srcbusid, unsigned char srcbusirq, | ||||||
|  | 	unsigned char destapic, unsigned char destapiclint); | ||||||
|  | void smp_write_address_space(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char address_type, | ||||||
|  | 	unsigned int address_base_low, unsigned int address_base_high, | ||||||
|  | 	unsigned int address_length_low, unsigned int address_length_high); | ||||||
|  | void smp_write_bus_hierarchy(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char bus_info, | ||||||
|  | 	unsigned char parent_busid); | ||||||
|  | void smp_write_compatibility_address_space(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char address_modifier, | ||||||
|  | 	unsigned int range_list); | ||||||
|  | unsigned char smp_compute_checksum(void *v, int len); | ||||||
|  | void *smp_write_floating_table(unsigned long addr); | ||||||
|  | unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map); | ||||||
|  |  | ||||||
|  | /* A table (per mainboard) listing the initial apicid of each cpu. */ | ||||||
|  | extern unsigned long initial_apicid[MAX_CPUS]; | ||||||
|  |  | ||||||
|  | #else /* HAVE_MP_TABLE */ | ||||||
|  | static inline  | ||||||
|  | unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map) | ||||||
|  | { | ||||||
|  | 	return addr; | ||||||
|  | } | ||||||
|  | #endif /* HAVE_MP_TABLE */ | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								src/arch/i386/include/bitops.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/arch/i386/include/bitops.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | #ifndef I386_BITOPS_H | ||||||
|  | #define I386_BITOPS_H | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * log2 - Find the truncated log base 2 of x | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | static inline unsigned long log2(unsigned long x) | ||||||
|  | { | ||||||
|  | 	unsigned long r = 0; | ||||||
|  | 	__asm__( | ||||||
|  | 		"bsrl %1, %0\n\t" | ||||||
|  | 		"jnz 1f\n\t" | ||||||
|  | 		"movl $-1, %0\n\t" | ||||||
|  | 		"1:\n\t" | ||||||
|  | 		: "=r" (r) : "r" (x)); | ||||||
|  | 	return r; | ||||||
|  | 		 | ||||||
|  | } | ||||||
|  | #endif /* I386_BITOPS_H */ | ||||||
							
								
								
									
										15
									
								
								src/arch/i386/include/stddef.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/arch/i386/include/stddef.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | #ifndef I386_STDDEF_H | ||||||
|  | #define I386_STDDEF_H | ||||||
|  |  | ||||||
|  | typedef long ptrdiff_t; | ||||||
|  | typedef unsigned long size_t; | ||||||
|  | typedef long ssize_t; | ||||||
|  |  | ||||||
|  | typedef int wchar_t; | ||||||
|  | typedef unsigned int wint_t; | ||||||
|  |  | ||||||
|  | #define NULL 0 | ||||||
|  |  | ||||||
|  | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | ||||||
|  |  | ||||||
|  | #endif /* I386_STDDEF_H */ | ||||||
							
								
								
									
										52
									
								
								src/arch/i386/include/stdint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/arch/i386/include/stdint.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | #ifndef I386_STDINT_H | ||||||
|  | #define I386_STDINT_H | ||||||
|  |  | ||||||
|  | /* Exact integral types */ | ||||||
|  | typedef unsigned char      uint8_t; | ||||||
|  | typedef signed char        int8_t;  | ||||||
|  |  | ||||||
|  | typedef unsigned short     uint16_t; | ||||||
|  | typedef signed short       int16_t; | ||||||
|  |  | ||||||
|  | typedef unsigned int       uint32_t; | ||||||
|  | typedef signed int         int32_t; | ||||||
|  |  | ||||||
|  | typedef unsigned long long uint64_t; | ||||||
|  | typedef signed long long   int64_t; | ||||||
|  |  | ||||||
|  | /* Small types */ | ||||||
|  | typedef unsigned char      uint_least8_t; | ||||||
|  | typedef signed char        int_least8_t;  | ||||||
|  |  | ||||||
|  | typedef unsigned short     uint_least16_t; | ||||||
|  | typedef signed short       int_least16_t; | ||||||
|  |  | ||||||
|  | typedef unsigned int       uint_least32_t; | ||||||
|  | typedef signed int         int_least32_t; | ||||||
|  |  | ||||||
|  | typedef unsigned long long uint_least64_t; | ||||||
|  | typedef signed long long   int_least64_t; | ||||||
|  |  | ||||||
|  | /* Fast Types */ | ||||||
|  | typedef unsigned char      uint_fast8_t; | ||||||
|  | typedef signed char        int_fast8_t;  | ||||||
|  |  | ||||||
|  | typedef unsigned int       uint_fast16_t; | ||||||
|  | typedef signed int         int_fast16_t; | ||||||
|  |  | ||||||
|  | typedef unsigned int       uint_fast32_t; | ||||||
|  | typedef signed int         int_fast32_t; | ||||||
|  |  | ||||||
|  | typedef unsigned long long uint_fast64_t; | ||||||
|  | typedef signed long long   int_fast64_t; | ||||||
|  |  | ||||||
|  | /* Types for `void *' pointers.  */ | ||||||
|  | typedef int                intptr_t; | ||||||
|  | typedef unsigned int       uintptr_t; | ||||||
|  |  | ||||||
|  | /* Largest integral types */ | ||||||
|  | typedef long long int      intmax_t; | ||||||
|  | typedef unsigned long long uintmax_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* I386_STDINT_H */ | ||||||
							
								
								
									
										135
									
								
								src/arch/i386/lib/c_start.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/arch/i386/lib/c_start.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | |||||||
|  | #include <arch/asm.h> | ||||||
|  | #include <arch/intel.h> | ||||||
|  | #ifdef SMP | ||||||
|  | #include <cpu/p6/apic.h> | ||||||
|  | #endif | ||||||
|  | 	.section ".text" | ||||||
|  | 	.code32 | ||||||
|  | 	.globl _start | ||||||
|  | _start: | ||||||
|  | 	cli | ||||||
|  | 	lgdt	%cs:gdtaddr | ||||||
|  | 	ljmp	$0x10, $1f | ||||||
|  | 1:	movl	$0x18, %eax | ||||||
|  | 	movl	%eax, %ds | ||||||
|  | 	movl	%eax, %es | ||||||
|  | 	movl	%eax, %ss | ||||||
|  | 	movl	%eax, %fs | ||||||
|  | 	movl	%eax, %gs | ||||||
|  |  | ||||||
|  | 	intel_chip_post_macro(0x13)		/* post 12 */ | ||||||
|  |  | ||||||
|  | 	/** clear stack */ | ||||||
|  | 	leal	EXT(_stack), %edi | ||||||
|  | 	movl	$EXT(_estack), %ecx | ||||||
|  | 	subl	%edi, %ecx | ||||||
|  | 	xorl	%eax, %eax | ||||||
|  | 	rep | ||||||
|  | 	stosb | ||||||
|  |  | ||||||
|  | 	/** clear bss */ | ||||||
|  | 	leal	EXT(_bss), %edi | ||||||
|  | 	movl	$EXT(_ebss), %ecx | ||||||
|  | 	subl	%edi, %ecx | ||||||
|  | 	jz	.Lnobss | ||||||
|  | 	xorl	%eax, %eax | ||||||
|  | 	rep | ||||||
|  | 	stosb | ||||||
|  | .Lnobss: | ||||||
|  |  | ||||||
|  | 	/* set new stack */ | ||||||
|  | 	movl	$_estack, %esp | ||||||
|  | #ifdef SMP | ||||||
|  | 	/* Get the cpu id */ | ||||||
|  | 	movl	$APIC_DEFAULT_BASE, %edi | ||||||
|  | 	movl	APIC_ID(%edi), %eax | ||||||
|  | 	shrl	$24, %eax | ||||||
|  |  | ||||||
|  | 	/* Get the cpu index (MAX_CPUS on error) */ | ||||||
|  | 	movl	$-4, %ebx | ||||||
|  | 1:	addl	$4, %ebx | ||||||
|  | 	cmpl	$(MAX_CPUS << 2), %ebx | ||||||
|  | 	je	2 | ||||||
|  | 	cmpl	%eax, EXT(initial_apicid)(%ebx) | ||||||
|  | 	jne	1b | ||||||
|  | 2:	shrl	$2, %ebx | ||||||
|  |  | ||||||
|  | 	/* Now compute the appropriate stack */ | ||||||
|  | 	movl	%ebx, %eax | ||||||
|  | 	movl	$STACK_SIZE, %ebx | ||||||
|  | 	mull	%ebx | ||||||
|  | 	subl	%eax, %esp | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	/* push the boot_complete flag */ | ||||||
|  | 	pushl	%ebp | ||||||
|  |  | ||||||
|  | 	/* Save the stack location */ | ||||||
|  | 	movl	%esp, %ebp | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 *	Now we are finished. Memory is up, data is copied and | ||||||
|  | 	 *	bss is cleared.   Now we call the main routine and | ||||||
|  | 	 *	let it do the rest. | ||||||
|  | 	 */  | ||||||
|  | 	intel_chip_post_macro(0xfe)	/* post fe */ | ||||||
|  |  | ||||||
|  | 	/* Resort the stack location */ | ||||||
|  | 	movl	%ebp, %esp | ||||||
|  | 	 | ||||||
|  | 	/* The boot_complete flag has already been pushed */ | ||||||
|  | 	call	EXT(hardwaremain) | ||||||
|  | 	/*NOTREACHED*/ | ||||||
|  | .Lhlt: | ||||||
|  | 	intel_chip_post_macro(0xee)	/* post fe */ | ||||||
|  | 	hlt | ||||||
|  | 	jmp	.Lhlt | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	.globl gdt, gdt_end, gdt_limit | ||||||
|  |  | ||||||
|  | gdt_limit = gdt_end - gdt - 1 /* compute the table limit */ | ||||||
|  | gdtaddr: | ||||||
|  | 	.word	gdt_limit | ||||||
|  | 	.long	gdt                /* we know the offset */ | ||||||
|  |  | ||||||
|  | gdt: | ||||||
|  | // selgdt 0 | ||||||
|  | 	.word	0x0000, 0x0000		/* dummy */ | ||||||
|  | 	.byte	0x00, 0x00, 0x00, 0x00 | ||||||
|  |  | ||||||
|  | // selgdt 8 | ||||||
|  | 	.word	0x0000, 0x0000		/* dummy */ | ||||||
|  | 	.byte	0x00, 0x00, 0x00, 0x00 | ||||||
|  |  | ||||||
|  | // selgdt 0x10  | ||||||
|  | /* flat code segment */ | ||||||
|  | 	.word	0xffff, 0x0000		 | ||||||
|  | 	.byte	0x00, 0x9b, 0xcf, 0x00	 | ||||||
|  | 	 | ||||||
|  | //selgdt 0x18 | ||||||
|  | /* flat data segment */ | ||||||
|  | 	.word	0xffff, 0x0000		 | ||||||
|  | 	.byte	0x00, 0x93, 0xcf, 0x00	 | ||||||
|  |  | ||||||
|  | //selgdt 0x20 | ||||||
|  | 	.word	0x0000, 0x0000		/* dummy */ | ||||||
|  | 	.byte	0x00, 0x00, 0x00, 0x00 | ||||||
|  |  | ||||||
|  | #if defined(CONFIG_VGABIOS) && (CONFIG_VGABIOS == 1) | ||||||
|  | 	// from monty: | ||||||
|  | 	/* 0x00009a00,0000ffffULL,   20h: 16-bit 64k code at 0x00000000 */ | ||||||
|  |         /* 0x00009200,0000ffffULL    28h: 16-bit 64k data at 0x00000000 */ | ||||||
|  | // selgdt 0x28 | ||||||
|  | /*16-bit 64k code at 0x00000000 */ | ||||||
|  | 	.word 0xffff, 0x0000 | ||||||
|  | 	.byte 0, 0x9a, 0, 0 | ||||||
|  |  | ||||||
|  | // selgdt 0x30 | ||||||
|  | /*16-bit 64k data at 0x00000000 */ | ||||||
|  | 	.word 0xffff, 0x0000 | ||||||
|  | 	.byte 0, 0x92, 0, 0 | ||||||
|  | #endif // defined(CONFIG_VGABIOS) && (CONFIG_VGABIOS == 1) | ||||||
|  | gdt_end: | ||||||
|  |  | ||||||
|  | .code32 | ||||||
							
								
								
									
										119
									
								
								src/arch/i386/lib/console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/arch/i386/lib/console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | #include <console/loglevel.h> | ||||||
|  |  | ||||||
|  | static void __console_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	uart_tx_byte(byte); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_nibble(unsigned nibble) | ||||||
|  | { | ||||||
|  | 	unsigned char digit; | ||||||
|  | 	digit = nibble + '0'; | ||||||
|  | 	if (digit > '9') { | ||||||
|  | 		digit += 39; | ||||||
|  | 	} | ||||||
|  | 	__console_tx_byte(digit); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_char(int loglevel, unsigned char byte) | ||||||
|  | { | ||||||
|  | 	if (ASM_CONSOLE_LOGLEVEL > loglevel) { | ||||||
|  | 		uart_tx_byte(byte); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_hex8(int loglevel, unsigned char byte) | ||||||
|  | { | ||||||
|  | 	if (ASM_CONSOLE_LOGLEVEL > loglevel) { | ||||||
|  | 		__console_tx_nibble(byte >> 4U); | ||||||
|  | 		__console_tx_nibble(byte & 0x0fU); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_hex32(int loglevel, unsigned int value) | ||||||
|  | { | ||||||
|  | 	if (ASM_CONSOLE_LOGLEVEL > loglevel) { | ||||||
|  | 		__console_tx_nibble((value >> 28U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >> 24U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >> 20U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >> 16U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >> 12U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >>  8U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble((value >>  4U) & 0x0fU); | ||||||
|  | 		__console_tx_nibble(value & 0x0fU); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_string(int loglevel, const char *str) | ||||||
|  | { | ||||||
|  | 	if (ASM_CONSOLE_LOGLEVEL > loglevel) { | ||||||
|  | 		unsigned char ch; | ||||||
|  | 		while((ch = *str++) != '\0') { | ||||||
|  | 			__console_tx_byte(ch); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void print_emerg_char(unsigned char byte) { __console_tx_char(BIOS_EMERG, byte); } | ||||||
|  | static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(BIOS_EMERG, value); } | ||||||
|  | static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(BIOS_EMERG, value); } | ||||||
|  | static void print_emerg(const char *str) { __console_tx_string(BIOS_EMERG, str); } | ||||||
|  |  | ||||||
|  | static void print_alert_char(unsigned char byte) { __console_tx_char(BIOS_ALERT, byte); } | ||||||
|  | static void print_alert_hex8(unsigned char value) { __console_tx_hex8(BIOS_ALERT, value); } | ||||||
|  | static void print_alert_hex32(unsigned int value) { __console_tx_hex32(BIOS_ALERT, value); } | ||||||
|  | static void print_alert(const char *str) { __console_tx_string(BIOS_ALERT, str); } | ||||||
|  |  | ||||||
|  | static void print_crit_char(unsigned char byte) { __console_tx_char(BIOS_CRIT, byte); } | ||||||
|  | static void print_crit_hex8(unsigned char value) { __console_tx_hex8(BIOS_CRIT, value); } | ||||||
|  | static void print_crit_hex32(unsigned int value) { __console_tx_hex32(BIOS_CRIT, value); } | ||||||
|  | static void print_crit(const char *str) { __console_tx_string(BIOS_CRIT, str); } | ||||||
|  |  | ||||||
|  | static void print_err_char(unsigned char byte) { __console_tx_char(BIOS_ERR, byte); } | ||||||
|  | static void print_err_hex8(unsigned char value) { __console_tx_hex8(BIOS_ERR, value); } | ||||||
|  | static void print_err_hex32(unsigned int value) { __console_tx_hex32(BIOS_ERR, value); } | ||||||
|  | static void print_err(const char *str) { __console_tx_string(BIOS_ERR, str); } | ||||||
|  |  | ||||||
|  | static void print_warning_char(unsigned char byte) { __console_tx_char(BIOS_WARNING, byte); } | ||||||
|  | static void print_warning_hex8(unsigned char value) { __console_tx_hex8(BIOS_WARNING, value); } | ||||||
|  | static void print_warning_hex32(unsigned int value) { __console_tx_hex32(BIOS_WARNING, value); } | ||||||
|  | static void print_warning(const char *str) { __console_tx_string(BIOS_WARNING, str); } | ||||||
|  |  | ||||||
|  | static void print_notice_char(unsigned char byte) { __console_tx_char(BIOS_NOTICE, byte); } | ||||||
|  | static void print_notice_hex8(unsigned char value) { __console_tx_hex8(BIOS_NOTICE, value); } | ||||||
|  | static void print_notice_hex32(unsigned int value) { __console_tx_hex32(BIOS_NOTICE, value); } | ||||||
|  | static void print_notice(const char *str) { __console_tx_string(BIOS_NOTICE, str); } | ||||||
|  |  | ||||||
|  | static void print_info_char(unsigned char byte) { __console_tx_char(BIOS_INFO, byte); } | ||||||
|  | static void print_info_hex8(unsigned char value) { __console_tx_hex8(BIOS_INFO, value); } | ||||||
|  | static void print_info_hex32(unsigned int value) { __console_tx_hex32(BIOS_INFO, value); } | ||||||
|  | static void print_info(const char *str) { __console_tx_string(BIOS_INFO, str); } | ||||||
|  |  | ||||||
|  | static void print_debug_char(unsigned char byte) { __console_tx_char(BIOS_DEBUG, byte); } | ||||||
|  | static void print_debug_hex8(unsigned char value) { __console_tx_hex8(BIOS_DEBUG, value); } | ||||||
|  | static void print_debug_hex32(unsigned int value) { __console_tx_hex32(BIOS_DEBUG, value); } | ||||||
|  | static void print_debug(const char *str) { __console_tx_string(BIOS_DEBUG, str); } | ||||||
|  |  | ||||||
|  | static void print_spew_char(unsigned char byte) { __console_tx_char(BIOS_SPEW, byte); } | ||||||
|  | static void print_spew_hex8(unsigned char value) { __console_tx_hex8(BIOS_SPEW, value); } | ||||||
|  | static void print_spew_hex32(unsigned int value) { __console_tx_hex32(BIOS_SPEW, value); } | ||||||
|  | static void print_spew(const char *str) { __console_tx_string(BIOS_SPEW, str); } | ||||||
|  |  | ||||||
|  | #define __STR(X) #X | ||||||
|  | #define STR(X) __STR(X) | ||||||
|  |  | ||||||
|  | #ifndef LINUXBIOS_EXTRA_VERSION | ||||||
|  | #define LINUXBIOS_EXTRA_VERSION | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static void console_init(void) | ||||||
|  | { | ||||||
|  | 	static const char console_test[] =  | ||||||
|  | 		"\r\n\r\nLinuxBIOS-" | ||||||
|  | 		STR(LINUXBIOS_VERSION) | ||||||
|  | 		STR(LINUXBIOS_EXTRA_VERSION) | ||||||
|  | 		" " | ||||||
|  | 		STR(LINUXBIOS_BUILD) | ||||||
|  | 		" starting...\r\n"; | ||||||
|  | 	print_info(console_test); | ||||||
|  | } | ||||||
							
								
								
									
										527
									
								
								src/arch/i386/lib/console.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								src/arch/i386/lib/console.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,527 @@ | |||||||
|  | #include <console/loglevel.h> | ||||||
|  |  | ||||||
|  | jmp	console0 | ||||||
|  |  | ||||||
|  | #define __STR(X) #X | ||||||
|  | #define STR(X) __STR(X) | ||||||
|  |  | ||||||
|  | #ifndef  LINUXBIOS_EXTRA_VERSION | ||||||
|  | #define LINUXBIOS_EXTRA_VERSION | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | console_test: | ||||||
|  | 	.ascii	"\r\n\r\nLinuxBIOS-" | ||||||
|  | 	.ascii	STR(LINUXBIOS_VERSION) | ||||||
|  | 	.ascii	STR(LINUXBIOS_EXTRA_VERSION) | ||||||
|  | 	.ascii	" " | ||||||
|  | 	.ascii	STR(LINUXBIOS_BUILD) | ||||||
|  | 	.asciz	" starting...\r\n" | ||||||
|  |  | ||||||
|  | #undef STR | ||||||
|  | 	/* uses:	ax, dx */ | ||||||
|  | #if CONFIG_CONSOLE_SERIAL8250 | ||||||
|  | #define __CONSOLE_INLINE_TX_AL TTYS0_TX_AL | ||||||
|  | #else | ||||||
|  | #define __CONSOLE_INLINE_TX_AL | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	/* uses:	esp, ax, dx */ | ||||||
|  | #define __CONSOLE_TX_CHAR(byte)	\ | ||||||
|  | 	mov	byte, %al	; \ | ||||||
|  | 	CALLSP(console_tx_al) | ||||||
|  |  | ||||||
|  | 	/* uses:	 ax, dx */ | ||||||
|  | #define __CONSOLE_INLINE_TX_CHAR(byte)	\ | ||||||
|  | 	mov	byte, %al	; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	/* uses:	esp, ax, edx */ | ||||||
|  | #define __CONSOLE_TX_HEX8(byte)	\ | ||||||
|  | 	mov	byte, %al	; \ | ||||||
|  | 	CALLSP(console_tx_hex8) | ||||||
|  |  | ||||||
|  | 	/* uses:	 byte, ax, dx */ | ||||||
|  | #define __CONSOLE_INLINE_TX_HEX8(byte)	\ | ||||||
|  | 	movb	byte, %dl	; \ | ||||||
|  | 	shll	$16, %edx	; \ | ||||||
|  | 	shr	$4, %al		; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL	; \ | ||||||
|  | 	shrl	$16, %edx	; \ | ||||||
|  | 	movb	%dl, %al	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	/* uses:	esp, eax, ebx, dx */ | ||||||
|  | #define __CONSOLE_TX_HEX32(lword)	\ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	CALLSP(console_tx_hex32) | ||||||
|  |  | ||||||
|  | 	/* uses:	eax, lword, dx */ | ||||||
|  | #define __CONSOLE_INLINE_TX_HEX32(lword)	\ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$28, %eax	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$24, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$20, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$16, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$12, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$8, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	shr	$4, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL		; \ | ||||||
|  | 				; \ | ||||||
|  | 	mov	lword, %eax	; \ | ||||||
|  | 	and	$0x0f, %al	; \ | ||||||
|  | 	add	$'0', %al	; \ | ||||||
|  | 	cmp	$'9', %al	; \ | ||||||
|  | 	jle	9f		; \ | ||||||
|  | 	add	$39, %al	; \ | ||||||
|  | 9:				; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* uses:	 esp, ebx, ax, dx */ | ||||||
|  | #define __CONSOLE_TX_STRING(string)	\ | ||||||
|  | 	mov	string, %ebx	; \ | ||||||
|  | 	CALLSP(console_tx_string) | ||||||
|  |  | ||||||
|  | 	/* uses:	 ebx, ax, dx */ | ||||||
|  | #define __CONSOLE_INLINE_TX_STRING(string)	\ | ||||||
|  | 	movl	string, %ebx	; \ | ||||||
|  | 10:	movb	(%ebx), %al	; \ | ||||||
|  | 	incl	%ebx		; \ | ||||||
|  | 	testb	%al, %al	; \ | ||||||
|  | 	jz	11f		; \ | ||||||
|  | 	__CONSOLE_INLINE_TX_AL	; \ | ||||||
|  | 	jmp	10b		; \ | ||||||
|  | 11:	 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define CONSOLE_EMERG_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_EMERG_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_EMERG_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_EMERG_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_ALERT_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_ALERT_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_ALERT_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_ALERT_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_CRIT_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_CRIT_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_CRIT_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_CRIT_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_ERR_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_ERR_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_ERR_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_ERR_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_WARNING_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_WARNING_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_WARNING_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_WARNING_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_NOTICE_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_NOTICE_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_NOTICE_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_NOTICE_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_INFO_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_INFO_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_INFO_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_INFO_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_DEBUG_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_DEBUG_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_DEBUG_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_DEBUG_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #define CONSOLE_SPEW_TX_CHAR(byte)            __CONSOLE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_CHAR(byte)     __CONSOLE_INLINE_TX_CHAR(byte) | ||||||
|  | #define CONSOLE_SPEW_TX_HEX8(byte)            __CONSOLE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_HEX8(byte)     __CONSOLE_INLINE_TX_HEX8(byte) | ||||||
|  | #define CONSOLE_SPEW_TX_HEX32(lword)          __CONSOLE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_HEX32(lword)   __CONSOLE_INLINE_TX_HEX32(lword) | ||||||
|  | #define CONSOLE_SPEW_TX_STRING(string)        __CONSOLE_TX_STRING(string) | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_EMERG | ||||||
|  | #undef  CONSOLE_EMERG_TX_CHAR | ||||||
|  | #undef  CONSOLE_EMERG_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_EMERG_TX_HEX8 | ||||||
|  | #undef  CONSOLE_EMERG_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_EMERG_TX_HEX32 | ||||||
|  | #undef  CONSOLE_EMERG_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_EMERG_TX_STRING | ||||||
|  | #undef  CONSOLE_EMERG_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_EMERG_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_EMERG_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_EMERG_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_EMERG_TX_STRING(string)         | ||||||
|  | #define CONSOLE_EMERG_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_ALERT | ||||||
|  | #undef  CONSOLE_ALERT_TX_CHAR | ||||||
|  | #undef  CONSOLE_ALERT_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_ALERT_TX_HEX8 | ||||||
|  | #undef  CONSOLE_ALERT_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_ALERT_TX_HEX32 | ||||||
|  | #undef  CONSOLE_ALERT_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_ALERT_TX_STRING | ||||||
|  | #undef  CONSOLE_ALERT_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_ALERT_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_ALERT_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_ALERT_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_ALERT_TX_STRING(string)         | ||||||
|  | #define CONSOLE_ALERT_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_CRIT | ||||||
|  | #undef  CONSOLE_CRIT_TX_CHAR | ||||||
|  | #undef  CONSOLE_CRIT_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_CRIT_TX_HEX8 | ||||||
|  | #undef  CONSOLE_CRIT_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_CRIT_TX_HEX32 | ||||||
|  | #undef  CONSOLE_CRIT_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_CRIT_TX_STRING | ||||||
|  | #undef  CONSOLE_CRIT_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_CRIT_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_CRIT_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_CRIT_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_CRIT_TX_STRING(string)         | ||||||
|  | #define CONSOLE_CRIT_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_ERR | ||||||
|  | #undef  CONSOLE_ERR_TX_CHAR | ||||||
|  | #undef  CONSOLE_ERR_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_ERR_TX_HEX8 | ||||||
|  | #undef  CONSOLE_ERR_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_ERR_TX_HEX32 | ||||||
|  | #undef  CONSOLE_ERR_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_ERR_TX_STRING | ||||||
|  | #undef  CONSOLE_ERR_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_ERR_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_ERR_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_ERR_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_ERR_TX_STRING(string)         | ||||||
|  | #define CONSOLE_ERR_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_WARNING | ||||||
|  | #undef  CONSOLE_WARNING_TX_CHAR | ||||||
|  | #undef  CONSOLE_WARNING_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_WARNING_TX_HEX8 | ||||||
|  | #undef  CONSOLE_WARNING_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_WARNING_TX_HEX32 | ||||||
|  | #undef  CONSOLE_WARNING_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_WARNING_TX_STRING | ||||||
|  | #undef  CONSOLE_WARNING_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_WARNING_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_WARNING_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_WARNING_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_WARNING_TX_STRING(string)         | ||||||
|  | #define CONSOLE_WARNING_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_NOTICE | ||||||
|  | #undef  CONSOLE_NOTICE_TX_CHAR | ||||||
|  | #undef  CONSOLE_NOTICE_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_NOTICE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_NOTICE_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_NOTICE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_NOTICE_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_NOTICE_TX_STRING | ||||||
|  | #undef  CONSOLE_NOTICE_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_NOTICE_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_NOTICE_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_NOTICE_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_NOTICE_TX_STRING(string)         | ||||||
|  | #define CONSOLE_NOTICE_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_INFO | ||||||
|  | #undef  CONSOLE_INFO_TX_CHAR | ||||||
|  | #undef  CONSOLE_INFO_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_INFO_TX_HEX8 | ||||||
|  | #undef  CONSOLE_INFO_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_INFO_TX_HEX32 | ||||||
|  | #undef  CONSOLE_INFO_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_INFO_TX_STRING | ||||||
|  | #undef  CONSOLE_INFO_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_INFO_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_INFO_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_INFO_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_INFO_TX_STRING(string)         | ||||||
|  | #define CONSOLE_INFO_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_DEBUG | ||||||
|  | #undef  CONSOLE_DEBUG_TX_CHAR | ||||||
|  | #undef  CONSOLE_DEBUG_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_DEBUG_TX_HEX8 | ||||||
|  | #undef  CONSOLE_DEBUG_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_DEBUG_TX_HEX32 | ||||||
|  | #undef  CONSOLE_DEBUG_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_DEBUG_TX_STRING | ||||||
|  | #undef  CONSOLE_DEBUG_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_DEBUG_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_DEBUG_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_DEBUG_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_DEBUG_TX_STRING(string)         | ||||||
|  | #define CONSOLE_DEBUG_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ASM_CONSOLE_LOGLEVEL <= BIOS_SPEW | ||||||
|  | #undef  CONSOLE_SPEW_TX_CHAR | ||||||
|  | #undef  CONSOLE_SPEW_INLINE_TX_CHAR | ||||||
|  | #undef  CONSOLE_SPEW_TX_HEX8 | ||||||
|  | #undef  CONSOLE_SPEW_INLINE_TX_HEX8 | ||||||
|  | #undef  CONSOLE_SPEW_TX_HEX32 | ||||||
|  | #undef  CONSOLE_SPEW_INLINE_TX_HEX32 | ||||||
|  | #undef  CONSOLE_SPEW_TX_STRING | ||||||
|  | #undef  CONSOLE_SPEW_INLINE_TX_STRING | ||||||
|  | #define CONSOLE_SPEW_TX_CHAR(byte)             | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_CHAR(byte)      | ||||||
|  | #define CONSOLE_SPEW_TX_HEX8(byte)             | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_HEX8(byte)      | ||||||
|  | #define CONSOLE_SPEW_TX_HEX32(lword)           | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_HEX32(lword)    | ||||||
|  | #define CONSOLE_SPEW_TX_STRING(string)         | ||||||
|  | #define CONSOLE_SPEW_INLINE_TX_STRING(string)  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* uses:	esp, ax, dx */ | ||||||
|  | console_tx_al:	 | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  | 	RETSP | ||||||
|  |  | ||||||
|  | 	/* uses:	 esp, ax, edx */ | ||||||
|  | console_tx_hex8: | ||||||
|  | 	__CONSOLE_INLINE_TX_HEX8(%al) | ||||||
|  | 	RETSP | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* uses:	 esp, ebx, eax, dx */ | ||||||
|  | console_tx_hex32: | ||||||
|  | 	mov	%eax, %ebx | ||||||
|  | 	shr	$28, %eax | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$24, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$20, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$16, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$12, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$8, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	shr	$4, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  |  | ||||||
|  | 	mov	%ebx, %eax | ||||||
|  | 	and	$0x0f, %al | ||||||
|  | 	add	$'0', %al | ||||||
|  | 	cmp	$'9', %al | ||||||
|  | 	jle	9f | ||||||
|  | 	add	$39, %al | ||||||
|  | 9: | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  | 	RETSP | ||||||
|  |  | ||||||
|  | 	/* Uses esp, ebx, ax, dx  */ | ||||||
|  |  | ||||||
|  | console_tx_string: | ||||||
|  | 	mov	(%ebx), %al | ||||||
|  | 	inc	%ebx | ||||||
|  | 	cmp	$0, %al | ||||||
|  | 	jne	9f | ||||||
|  | 	RETSP | ||||||
|  | 9:	 | ||||||
|  | 	__CONSOLE_INLINE_TX_AL | ||||||
|  | 	jmp	console_tx_string | ||||||
|  |  | ||||||
|  | console0: | ||||||
|  | 	CONSOLE_INFO_TX_STRING($console_test) | ||||||
|  |  | ||||||
							
								
								
									
										139
									
								
								src/arch/i386/lib/cpu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/arch/i386/lib/cpu.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <cpu/cpu.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <cpu/cpufixup.h> | ||||||
|  | #include <smp/start_stop.h> | ||||||
|  | #include <cpu/cpufixup.h> | ||||||
|  | #include <cpu/p6/mtrr.h> | ||||||
|  | #include <cpu/p6/msr.h> | ||||||
|  | #include <cpu/p6/apic.h> | ||||||
|  | #include <cpu/p5/cpuid.h> | ||||||
|  | #if 0 | ||||||
|  | #include <cpu/l2_cache.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CONFIG_SMP || CONFIG_IOAPIC | ||||||
|  | #define APIC 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static void cache_on(struct mem_range *mem) | ||||||
|  | { | ||||||
|  | 	post_code(0x60); | ||||||
|  | 	printk_info("Enabling cache..."); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* we need an #ifdef i586 here at some point ... */ | ||||||
|  | 	__asm__ __volatile__("mov %cr0, %eax\n\t" | ||||||
|  | 			     "and $0x9fffffff,%eax\n\t" | ||||||
|  | 			     "mov %eax, %cr0\n\t"); | ||||||
|  | 	/* turns out cache isn't really on until you set MTRR registers on  | ||||||
|  | 	 * 686 and later.  | ||||||
|  | 	 * NOTHING FANCY. Linux does a much better job anyway.  | ||||||
|  | 	 * so absolute minimum needed to get it going.  | ||||||
|  | 	 */ | ||||||
|  | 	/* OK, linux it turns out does nothing. We have to do it ... */ | ||||||
|  | #if defined(i686)  | ||||||
|  | 	// totalram here is in linux sizing, i.e. units of KB.  | ||||||
|  | 	// set_mtrr is responsible for getting it into the right units! | ||||||
|  | 	setup_mtrrs(mem); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	post_code(0x6A); | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void interrupts_on() | ||||||
|  | { | ||||||
|  | 	/* this is so interrupts work. This is very limited scope --  | ||||||
|  | 	 * linux will do better later, we hope ... | ||||||
|  | 	 */ | ||||||
|  | 	/* this is the first way we learned to do it. It fails on real SMP  | ||||||
|  | 	 * stuff. So we have to do things differently ...  | ||||||
|  | 	 * see the Intel mp1.4 spec, page A-3 | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  | #if defined(APIC) | ||||||
|  | 	/* Only Pentium Pro and later have those MSR stuff */ | ||||||
|  | 	unsigned long low, high; | ||||||
|  |  | ||||||
|  | 	printk_info("Setting up local apic..."); | ||||||
|  |  | ||||||
|  | 	/* Enable the local apic */ | ||||||
|  | 	rdmsr(APIC_BASE_MSR, low, high); | ||||||
|  | 	low |= APIC_BASE_MSR_ENABLE; | ||||||
|  | 	low &= ~APIC_BASE_MSR_ADDR_MASK; | ||||||
|  | 	low |= APIC_DEFAULT_BASE; | ||||||
|  | 	wrmsr(APIC_BASE_MSR, low, high); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/* Put the local apic in virtual wire mode */ | ||||||
|  | 	apic_write_around(APIC_SPIV,  | ||||||
|  | 		(apic_read_around(APIC_SPIV) & ~(APIC_VECTOR_MASK)) | ||||||
|  | 		| APIC_SPIV_ENABLE); | ||||||
|  | 	apic_write_around(APIC_LVT0,  | ||||||
|  | 		(apic_read_around(APIC_LVT0) &  | ||||||
|  | 			~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER |  | ||||||
|  | 				APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY |  | ||||||
|  | 				APIC_SEND_PENDING |APIC_LVT_RESERVED_1 | | ||||||
|  | 				APIC_DELIVERY_MODE_MASK)) | ||||||
|  | 		| (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING |  | ||||||
|  | 			APIC_DELIVERY_MODE_EXTINT) | ||||||
|  | 		); | ||||||
|  | 	apic_write_around(APIC_LVT1,  | ||||||
|  | 		(apic_read_around(APIC_LVT1) &  | ||||||
|  | 			~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER |  | ||||||
|  | 				APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY |  | ||||||
|  | 				APIC_SEND_PENDING |APIC_LVT_RESERVED_1 | | ||||||
|  | 				APIC_DELIVERY_MODE_MASK)) | ||||||
|  | 		| (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING |  | ||||||
|  | 			APIC_DELIVERY_MODE_NMI) | ||||||
|  | 		); | ||||||
|  | #else /* APIC */ | ||||||
|  | #ifdef i686 | ||||||
|  | 	/* Only Pentium Pro and later have those MSR stuff */ | ||||||
|  | 	unsigned long low, high; | ||||||
|  |  | ||||||
|  | 	printk_info("Disabling local apic..."); | ||||||
|  |  | ||||||
|  | 	rdmsr(APIC_BASE_MSR, low, high); | ||||||
|  | 	low &= ~APIC_BASE_MSR_ENABLE; | ||||||
|  | 	wrmsr(APIC_BASE_MSR, low, high); | ||||||
|  | #endif /* i686 */ | ||||||
|  | #endif /* APIC */ | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | 	post_code(0x9b); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unsigned long cpu_initialize(struct mem_range *mem) | ||||||
|  | { | ||||||
|  | 	/* Because we busy wait at the printk spinlock. | ||||||
|  | 	 * It is important to keep the number of printed messages | ||||||
|  | 	 * from secondary cpus to a minimum, when debugging is | ||||||
|  | 	 * disabled. | ||||||
|  | 	 */ | ||||||
|  | 	unsigned long processor_id = this_processors_id(); | ||||||
|  | 	printk_notice("Initializing CPU #%d\n", processor_id); | ||||||
|  | 	 | ||||||
|  | 	/* some cpus need a fixup done. This is the hook for doing that. */ | ||||||
|  | 	cpufixup(mem); | ||||||
|  |  | ||||||
|  | 	/* Turn on caching if we haven't already */ | ||||||
|  | 	cache_on(mem); | ||||||
|  |  | ||||||
|  | 	display_cpuid(); | ||||||
|  | 	mtrr_check(); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	/* now that everything is really up, enable the l2 cache if desired.  | ||||||
|  | 	 * The enable can wait until this point, because linuxbios and it's | ||||||
|  | 	 * data areas are tiny, easily fitting into the L1 cache.  | ||||||
|  | 	 */ | ||||||
|  | 	configure_l2_cache(); | ||||||
|  | #endif | ||||||
|  | 	interrupts_on(); | ||||||
|  | 	printk_info("CPU #%d Initialized\n", processor_id); | ||||||
|  | 	return processor_id; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								src/arch/i386/lib/cpu_reset.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/arch/i386/lib/cpu_reset.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | jmp cpu_reset_out | ||||||
|  |  | ||||||
|  | __cpu_reset: | ||||||
|  | 	movl	$0xffffffff, %ebp | ||||||
|  | 	jmp	__main | ||||||
|  |  | ||||||
|  | cpu_reset_out: | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								src/arch/i386/lib/failover.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/arch/i386/lib/failover.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | 	__normal_image = (ZKERNEL_START & 0xfffffff0) - 8; | ||||||
							
								
								
									
										21
									
								
								src/arch/i386/lib/id.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/arch/i386/lib/id.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | 	.section ".id", "a", @progbits | ||||||
|  |  | ||||||
|  | #define __STR(X) #X | ||||||
|  | #define STR(X) __STR(X) | ||||||
|  |  | ||||||
|  | 	.globl __id_start | ||||||
|  | __id_start: | ||||||
|  | vendor:	 | ||||||
|  | 	.asciz STR(MAINBOARD_VENDOR) | ||||||
|  | part:		 | ||||||
|  | 	.asciz STR(MAINBOARD_PART_NUMBER) | ||||||
|  | .long __id_end + 0x10 - vendor  /* Reverse offset to the vendor id */ | ||||||
|  | .long __id_end + 0x10 - part    /* Reverse offset to the part number */ | ||||||
|  | .long PAYLOAD_SIZE + ROM_IMAGE_SIZE  /* Size of this romimage */ | ||||||
|  | 	.globl __id_end | ||||||
|  |  | ||||||
|  | #undef __STR | ||||||
|  | #undef STR | ||||||
|  |  | ||||||
|  | __id_end: | ||||||
|  | .previous | ||||||
							
								
								
									
										6
									
								
								src/arch/i386/lib/id.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/arch/i386/lib/id.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | SECTIONS { | ||||||
|  | 	. = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start); | ||||||
|  | 	.id (.): { | ||||||
|  | 		*(.id) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								src/arch/i386/lib/noop_failover.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/arch/i386/lib/noop_failover.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | /* Step 1:  Test for cpu reset | ||||||
|  |  *     That is, did I just boot or is this a later boot since power on. | ||||||
|  |  *     The result of this test in %al | ||||||
|  |  *     %al == 1 -- We are rebooting | ||||||
|  |  *     %al == 0 -- This is the initial boot | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 	testb	%al, %al | ||||||
|  | 	jnz	__cpu_reset | ||||||
							
								
								
									
										281
									
								
								src/arch/i386/lib/pci_ops.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								src/arch/i386/lib/pci_ops.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <arch/pciconf.h> | ||||||
|  | #include <pci.h> | ||||||
|  | #include <pci_ids.h> | ||||||
|  | #include <pci_ops.h> | ||||||
|  |  | ||||||
|  | static const struct pci_ops *conf; | ||||||
|  | struct pci_ops { | ||||||
|  | 	int (*read_byte) (uint8_t bus, int devfn, int where, uint8_t * val); | ||||||
|  | 	int (*read_word) (uint8_t bus, int devfn, int where, uint16_t * val); | ||||||
|  | 	int (*read_dword) (uint8_t bus, int devfn, int where, uint32_t * val); | ||||||
|  | 	int (*write_byte) (uint8_t bus, int devfn, int where, uint8_t val); | ||||||
|  | 	int (*write_word) (uint8_t bus, int devfn, int where, uint16_t val); | ||||||
|  | 	int (*write_dword) (uint8_t bus, int devfn, int where, uint32_t val); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Direct access to PCI hardware... | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Functions for accessing PCI configuration space with type 1 accesses | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define CONFIG_CMD(bus,devfn, where)   (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3)) | ||||||
|  |  | ||||||
|  | static int pci_conf1_read_config_byte(unsigned char bus, int devfn, int where, uint8_t * value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	*value = inb(0xCFC + (where & 3)); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf1_read_config_word(unsigned char bus, int devfn, int where, uint16_t * value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	*value = inw(0xCFC + (where & 2)); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf1_read_config_dword(unsigned char bus, int devfn, int where, uint32_t * value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	*value = inl(0xCFC); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf1_write_config_byte(unsigned char bus, int devfn, int where, uint8_t value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	outb(value, 0xCFC + (where & 3)); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf1_write_config_word(unsigned char bus, int devfn, int where, uint16_t value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	outw(value, 0xCFC + (where & 2)); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf1_write_config_dword(unsigned char bus, int devfn, int where, uint32_t value) | ||||||
|  | { | ||||||
|  | 	outl(CONFIG_CMD(bus, devfn, where), 0xCF8); | ||||||
|  | 	outl(value, 0xCFC); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #undef CONFIG_CMD | ||||||
|  |  | ||||||
|  | static const struct pci_ops pci_direct_conf1 = | ||||||
|  | { | ||||||
|  | 	pci_conf1_read_config_byte, | ||||||
|  | 	pci_conf1_read_config_word, | ||||||
|  | 	pci_conf1_read_config_dword, | ||||||
|  | 	pci_conf1_write_config_byte, | ||||||
|  | 	pci_conf1_write_config_word, | ||||||
|  | 	pci_conf1_write_config_dword | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Functions for accessing PCI configuration space with type 2 accesses | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define IOADDR(devfn, where)	((0xC000 | ((devfn & 0x78) << 5)) + where) | ||||||
|  | #define FUNC(devfn)		(((devfn & 7) << 1) | 0xf0) | ||||||
|  | #define SET(bus,devfn)		if (devfn & 0x80) return -1;outb(FUNC(devfn), 0xCF8); outb(bus, 0xCFA); | ||||||
|  |  | ||||||
|  | static int pci_conf2_read_config_byte(unsigned char bus, int devfn, int where, uint8_t * value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	*value = inb(IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf2_read_config_word(unsigned char bus, int devfn, int where, uint16_t * value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	*value = inw(IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf2_read_config_dword(unsigned char bus, int devfn, int where, uint32_t * value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	*value = inl(IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf2_write_config_byte(unsigned char bus, int devfn, int where, uint8_t value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	outb(value, IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf2_write_config_word(unsigned char bus, int devfn, int where, uint16_t value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	outw(value, IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int pci_conf2_write_config_dword(unsigned char bus, int devfn, int where, uint32_t value) | ||||||
|  | { | ||||||
|  | 	SET(bus, devfn); | ||||||
|  | 	outl(value, IOADDR(devfn, where)); | ||||||
|  | 	outb(0, 0xCF8); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #undef SET | ||||||
|  | #undef IOADDR | ||||||
|  | #undef FUNC | ||||||
|  |  | ||||||
|  | static const struct pci_ops pci_direct_conf2 = | ||||||
|  | { | ||||||
|  | 	pci_conf2_read_config_byte, | ||||||
|  | 	pci_conf2_read_config_word, | ||||||
|  | 	pci_conf2_read_config_dword, | ||||||
|  | 	pci_conf2_write_config_byte, | ||||||
|  | 	pci_conf2_write_config_word, | ||||||
|  | 	pci_conf2_write_config_dword | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Before we decide to use direct hardware access mechanisms, we try to do some | ||||||
|  |  * trivial checks to ensure it at least _seems_ to be working -- we just test | ||||||
|  |  * whether bus 00 contains a host bridge (this is similar to checking | ||||||
|  |  * techniques used in XFree86, but ours should be more reliable since we | ||||||
|  |  * attempt to make use of direct access hints provided by the PCI BIOS). | ||||||
|  |  * | ||||||
|  |  * This should be close to trivial, but it isn't, because there are buggy | ||||||
|  |  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID. | ||||||
|  |  */ | ||||||
|  | static int pci_sanity_check(const struct pci_ops *o) | ||||||
|  | { | ||||||
|  | 	uint16_t x; | ||||||
|  | 	uint8_t bus; | ||||||
|  | 	int devfn; | ||||||
|  | #define PCI_CLASS_BRIDGE_HOST		0x0600 | ||||||
|  | #define PCI_CLASS_DISPLAY_VGA		0x0300 | ||||||
|  | #define PCI_VENDOR_ID_COMPAQ		0x0e11 | ||||||
|  | #define PCI_VENDOR_ID_INTEL		0x8086 | ||||||
|  | #define PCI_VENDOR_ID_MOTOROLA		0x1057 | ||||||
|  |  | ||||||
|  | 	for (bus = 0, devfn = 0; devfn < 0x100; devfn++) | ||||||
|  | 		if ((!o->read_word(bus, devfn, PCI_CLASS_DEVICE, &x) && | ||||||
|  | 		     (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || | ||||||
|  | 		    (!o->read_word(bus, devfn, PCI_VENDOR_ID, &x) && | ||||||
|  | 		     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ || x == PCI_VENDOR_ID_MOTOROLA))) | ||||||
|  | 			return 1; | ||||||
|  | 	printk_err("PCI: Sanity check failed\n"); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const struct pci_ops *pci_check_direct(void) | ||||||
|  | { | ||||||
|  | 	unsigned int tmp; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Check if configuration type 1 works. | ||||||
|  | 	 */ | ||||||
|  | 	{ | ||||||
|  | 		outb(0x01, 0xCFB); | ||||||
|  | 		tmp = inl(0xCF8); | ||||||
|  | 		outl(0x80000000, 0xCF8); | ||||||
|  | 		if (inl(0xCF8) == 0x80000000 && | ||||||
|  | 		    pci_sanity_check(&pci_direct_conf1)) { | ||||||
|  | 			outl(tmp, 0xCF8); | ||||||
|  | 			printk_debug("PCI: Using configuration type 1\n"); | ||||||
|  | 			return &pci_direct_conf1; | ||||||
|  | 		} | ||||||
|  | 		outl(tmp, 0xCF8); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Check if configuration type 2 works. | ||||||
|  | 	 */ | ||||||
|  | 	{ | ||||||
|  | 		outb(0x00, 0xCFB); | ||||||
|  | 		outb(0x00, 0xCF8); | ||||||
|  | 		outb(0x00, 0xCFA); | ||||||
|  | 		if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && | ||||||
|  | 		    pci_sanity_check(&pci_direct_conf2)) { | ||||||
|  | 			printk_debug("PCI: Using configuration type 2\n"); | ||||||
|  | 			return &pci_direct_conf2; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk_debug("pci_check_direct failed\n"); | ||||||
|  |      | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_read_config_byte(struct device *dev, uint8_t where, uint8_t * val) | ||||||
|  | { | ||||||
|  | 	int res;  | ||||||
|  | 	res = conf->read_byte(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	printk_spew("Read config byte bus %d,devfn 0x%x,reg 0x%x,val 0x%x,res 0x%x\n", | ||||||
|  | 		    dev->bus->secondary, dev->devfn, where, *val, res); | ||||||
|  | 	return res; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_read_config_word(struct device *dev, uint8_t where, uint16_t * val) | ||||||
|  | { | ||||||
|  | 	int res;  | ||||||
|  | 	res = conf->read_word(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	printk_spew( "Read config word bus %d,devfn 0x%x,reg 0x%x,val 0x%x,res 0x%x\n", | ||||||
|  | 		     dev->bus->secondary, dev->devfn, where, *val, res); | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_read_config_dword(struct device *dev, uint8_t where, uint32_t * val) | ||||||
|  | { | ||||||
|  | 	int res;  | ||||||
|  | 	res = conf->read_dword(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	printk_spew( "Read config dword bus %d,devfn 0x%x,reg 0x%x,val 0x%x,res 0x%x\n", | ||||||
|  | 		     dev->bus->secondary, dev->devfn, where, *val, res); | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_write_config_byte(struct device *dev, uint8_t where, uint8_t val) | ||||||
|  | { | ||||||
|  | 	printk_spew( "Write config byte bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n", | ||||||
|  | 		     dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	return conf->write_byte(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_write_config_word(struct device *dev, uint8_t where, uint16_t val) | ||||||
|  | { | ||||||
|  | 	printk_spew( "Write config word bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n", | ||||||
|  | 		     dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	return conf->write_word(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int pci_write_config_dword(struct device *dev, uint8_t where, uint32_t val) | ||||||
|  | { | ||||||
|  | 	printk_spew( "Write config dword bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n", | ||||||
|  | 		     dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | 	return conf->write_dword(dev->bus->secondary, dev->devfn, where, val); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Set the method to be used for PCI, type I or type II | ||||||
|  |  */ | ||||||
|  | void pci_set_method(void) | ||||||
|  | { | ||||||
|  | 	conf = &pci_direct_conf1; | ||||||
|  | 	conf = pci_check_direct(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										245
									
								
								src/arch/i386/smp/mpspec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/arch/i386/smp/mpspec.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <cpu/cpu.h> | ||||||
|  | #include <smp/start_stop.h> | ||||||
|  | #include <arch/smp/mpspec.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <cpu/p5/cpuid.h> | ||||||
|  | #include <cpu/p6/apic.h> | ||||||
|  |  | ||||||
|  | unsigned char smp_compute_checksum(void *v, int len) | ||||||
|  | { | ||||||
|  | 	unsigned char *bytes; | ||||||
|  | 	unsigned char checksum; | ||||||
|  | 	int i; | ||||||
|  | 	bytes = v; | ||||||
|  | 	checksum = 0; | ||||||
|  | 	for(i = 0; i < len; i++) { | ||||||
|  | 		checksum -= bytes[i]; | ||||||
|  | 	} | ||||||
|  | 	return checksum; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *smp_write_floating_table(unsigned long addr) | ||||||
|  | { | ||||||
|  | 	struct intel_mp_floating *mf; | ||||||
|  | 	void *v; | ||||||
|  | 	 | ||||||
|  | 	/* 16 byte align the table address */ | ||||||
|  | 	addr += 15; | ||||||
|  | 	addr &= ~15; | ||||||
|  | 	v = (void *)addr; | ||||||
|  |  | ||||||
|  | 	mf = v; | ||||||
|  | 	mf->mpf_signature[0] = '_'; | ||||||
|  | 	mf->mpf_signature[1] = 'M'; | ||||||
|  | 	mf->mpf_signature[2] = 'P'; | ||||||
|  | 	mf->mpf_signature[3] = '_'; | ||||||
|  | 	mf->mpf_physptr = (unsigned long)(((char *)v) + SMP_FLOATING_TABLE_LEN); | ||||||
|  | 	mf->mpf_length = 1; | ||||||
|  | 	mf->mpf_specification = 4; | ||||||
|  | 	mf->mpf_checksum = 0; | ||||||
|  | 	mf->mpf_feature1 = 0; | ||||||
|  | 	mf->mpf_feature2 = 0; | ||||||
|  | 	mf->mpf_feature3 = 0; | ||||||
|  | 	mf->mpf_feature4 = 0; | ||||||
|  | 	mf->mpf_feature5 = 0; | ||||||
|  | 	mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16); | ||||||
|  | 	return v; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *smp_next_mpc_entry(struct mp_config_table *mc) | ||||||
|  | { | ||||||
|  | 	void *v; | ||||||
|  | 	v = (void *)(((char *)mc) + mc->mpc_length); | ||||||
|  | 	return v; | ||||||
|  | } | ||||||
|  | static void smp_add_mpc_entry(struct mp_config_table *mc, unsigned length) | ||||||
|  | { | ||||||
|  | 	mc->mpc_length += length; | ||||||
|  | 	mc->mpc_entry_count++; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *smp_next_mpe_entry(struct mp_config_table *mc) | ||||||
|  | { | ||||||
|  | 	void *v; | ||||||
|  | 	v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length); | ||||||
|  | 	return v; | ||||||
|  | } | ||||||
|  | static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe) | ||||||
|  | { | ||||||
|  | 	mc->mpe_length += mpe->mpe_length; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_processor(struct mp_config_table *mc, | ||||||
|  | 	unsigned char apicid, unsigned char apicver, | ||||||
|  | 	unsigned char cpuflag, unsigned int cpufeature, | ||||||
|  | 	unsigned int featureflag) | ||||||
|  | { | ||||||
|  | 	struct mpc_config_processor *mpc; | ||||||
|  | 	mpc = smp_next_mpc_entry(mc); | ||||||
|  | 	memset(mpc, '\0', sizeof(*mpc)); | ||||||
|  | 	mpc->mpc_type = MP_PROCESSOR; | ||||||
|  | 	mpc->mpc_apicid = apicid; | ||||||
|  | 	mpc->mpc_apicver = apicver; | ||||||
|  | 	mpc->mpc_cpuflag = cpuflag; | ||||||
|  | 	mpc->mpc_cpufeature = cpufeature; | ||||||
|  | 	mpc->mpc_featureflag = featureflag; | ||||||
|  | 	smp_add_mpc_entry(mc, sizeof(*mpc)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* If we assume a symmetric processor configuration we can | ||||||
|  |  * get all of the information we need to write the processor | ||||||
|  |  * entry from the bootstrap processor. | ||||||
|  |  * Plus I don't think linux really even cares. | ||||||
|  |  * Having the proper apicid's in the table so the non-bootstrap | ||||||
|  |  *  processors can be woken up should be enough. | ||||||
|  |  */ | ||||||
|  | void smp_write_processors(struct mp_config_table *mc,  | ||||||
|  | 			unsigned long *processor_map) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	int processor_id; | ||||||
|  | 	unsigned apic_version; | ||||||
|  | 	unsigned cpu_features; | ||||||
|  | 	unsigned cpu_feature_flags; | ||||||
|  | 	int eax, ebx, ecx, edx; | ||||||
|  | 	processor_id = this_processors_id(); | ||||||
|  | 	apic_version = apic_read(APIC_LVR) & 0xff; | ||||||
|  | 	cpuid(1, &eax, &ebx, &ecx, &edx); | ||||||
|  | 	cpu_features = eax; | ||||||
|  | 	cpu_feature_flags = edx; | ||||||
|  | 	for(i = 0; i < MAX_CPUS; i++) { | ||||||
|  | 		unsigned long cpu_apicid = initial_apicid[i]; | ||||||
|  | 		unsigned long cpu_flag; | ||||||
|  | 		if(initial_apicid[i]==-1) | ||||||
|  | 			continue; | ||||||
|  | 		cpu_flag = MPC_CPU_ENABLED | ||||||
|  | 		if (processor_map[i] & CPU_BOOTPROCESSOR) { | ||||||
|  | 			cpu_flag |= MPC_CPU_BOOTPROCESSOR; | ||||||
|  | 		} | ||||||
|  | 		smp_write_processor(mc, cpu_apicid, apic_version, | ||||||
|  | 			cpu_flag, cpu_features, cpu_feature_flags | ||||||
|  | 		); | ||||||
|  | 	 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_bus(struct mp_config_table *mc, | ||||||
|  | 	unsigned char id, unsigned char *bustype) | ||||||
|  | { | ||||||
|  | 	struct mpc_config_bus *mpc; | ||||||
|  | 	mpc = smp_next_mpc_entry(mc); | ||||||
|  | 	memset(mpc, '\0', sizeof(*mpc)); | ||||||
|  | 	mpc->mpc_type = MP_BUS; | ||||||
|  | 	mpc->mpc_busid = id; | ||||||
|  | 	memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype)); | ||||||
|  | 	smp_add_mpc_entry(mc, sizeof(*mpc)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_ioapic(struct mp_config_table *mc, | ||||||
|  | 	unsigned char id, unsigned char ver,  | ||||||
|  | 	unsigned long apicaddr) | ||||||
|  | { | ||||||
|  | 	struct mpc_config_ioapic *mpc; | ||||||
|  | 	mpc = smp_next_mpc_entry(mc); | ||||||
|  | 	memset(mpc, '\0', sizeof(*mpc)); | ||||||
|  | 	mpc->mpc_type = MP_IOAPIC; | ||||||
|  | 	mpc->mpc_apicid = id; | ||||||
|  | 	mpc->mpc_apicver = ver; | ||||||
|  | 	mpc->mpc_flags = MPC_APIC_USABLE; | ||||||
|  | 	mpc->mpc_apicaddr = apicaddr; | ||||||
|  | 	smp_add_mpc_entry(mc, sizeof(*mpc)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_intsrc(struct mp_config_table *mc, | ||||||
|  | 	unsigned char irqtype, unsigned short irqflag, | ||||||
|  | 	unsigned char srcbus, unsigned char srcbusirq, | ||||||
|  | 	unsigned char dstapic, unsigned char dstirq) | ||||||
|  | { | ||||||
|  | 	struct mpc_config_intsrc *mpc; | ||||||
|  | 	mpc = smp_next_mpc_entry(mc); | ||||||
|  | 	memset(mpc, '\0', sizeof(*mpc)); | ||||||
|  | 	mpc->mpc_type = MP_INTSRC; | ||||||
|  | 	mpc->mpc_irqtype = irqtype; | ||||||
|  | 	mpc->mpc_irqflag = irqflag; | ||||||
|  | 	mpc->mpc_srcbus = srcbus; | ||||||
|  | 	mpc->mpc_srcbusirq = srcbusirq; | ||||||
|  | 	mpc->mpc_dstapic = dstapic; | ||||||
|  | 	mpc->mpc_dstirq = dstirq; | ||||||
|  | 	smp_add_mpc_entry(mc, sizeof(*mpc)); | ||||||
|  | #if CONFIG_DEBUG_MPTABLE == 1 | ||||||
|  | 	printk_info("add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n", | ||||||
|  | 				srcbus, srcbusirq, dstapic, dstirq); | ||||||
|  | 	hexdump(__FUNCTION__, mpc, sizeof(*mpc)); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void smp_write_lintsrc(struct mp_config_table *mc, | ||||||
|  | 	unsigned char irqtype, unsigned short irqflag, | ||||||
|  | 	unsigned char srcbusid, unsigned char srcbusirq, | ||||||
|  | 	unsigned char destapic, unsigned char destapiclint) | ||||||
|  | { | ||||||
|  | 	struct mpc_config_lintsrc *mpc; | ||||||
|  | 	mpc = smp_next_mpc_entry(mc); | ||||||
|  | 	memset(mpc, '\0', sizeof(*mpc)); | ||||||
|  | 	mpc->mpc_type = MP_LINTSRC; | ||||||
|  | 	mpc->mpc_irqtype = irqtype; | ||||||
|  | 	mpc->mpc_irqflag = irqflag; | ||||||
|  | 	mpc->mpc_srcbusid = srcbusid; | ||||||
|  | 	mpc->mpc_srcbusirq = srcbusirq; | ||||||
|  | 	mpc->mpc_destapic = destapic; | ||||||
|  | 	mpc->mpc_destapiclint = destapiclint; | ||||||
|  | 	smp_add_mpc_entry(mc, sizeof(*mpc)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_address_space(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char address_type, | ||||||
|  | 	unsigned int address_base_low, unsigned int address_base_high, | ||||||
|  | 	unsigned int address_length_low, unsigned int address_length_high) | ||||||
|  | { | ||||||
|  | 	struct mp_exten_system_address_space *mpe; | ||||||
|  | 	mpe = smp_next_mpe_entry(mc); | ||||||
|  | 	memset(mpe, '\0', sizeof(*mpe)); | ||||||
|  | 	mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE; | ||||||
|  | 	mpe->mpe_length = sizeof(*mpe); | ||||||
|  | 	mpe->mpe_busid = busid; | ||||||
|  | 	mpe->mpe_address_type = address_type; | ||||||
|  | 	mpe->mpe_address_base_low  = address_base_low; | ||||||
|  | 	mpe->mpe_address_base_high = address_base_high; | ||||||
|  | 	mpe->mpe_address_length_low  = address_length_low; | ||||||
|  | 	mpe->mpe_address_length_high = address_length_high; | ||||||
|  | 	smp_add_mpe_entry(mc, (mpe_t)mpe); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void smp_write_bus_hierarchy(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char bus_info, | ||||||
|  | 	unsigned char parent_busid) | ||||||
|  | { | ||||||
|  | 	struct mp_exten_bus_hierarchy *mpe; | ||||||
|  | 	mpe = smp_next_mpe_entry(mc); | ||||||
|  | 	memset(mpe, '\0', sizeof(*mpe)); | ||||||
|  | 	mpe->mpe_type = MPE_BUS_HIERARCHY; | ||||||
|  | 	mpe->mpe_length = sizeof(*mpe); | ||||||
|  | 	mpe->mpe_busid = busid; | ||||||
|  | 	mpe->mpe_bus_info = bus_info; | ||||||
|  | 	mpe->mpe_parent_busid = parent_busid; | ||||||
|  | 	smp_add_mpe_entry(mc, (mpe_t)mpe); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void smp_write_compatibility_address_space(struct mp_config_table *mc, | ||||||
|  | 	unsigned char busid, unsigned char address_modifier, | ||||||
|  | 	unsigned int range_list) | ||||||
|  | { | ||||||
|  | 	struct mp_exten_compatibility_address_space *mpe; | ||||||
|  | 	mpe = smp_next_mpe_entry(mc); | ||||||
|  | 	memset(mpe, '\0', sizeof(*mpe)); | ||||||
|  | 	mpe->mpe_type = MPE_COMPATIBILITY_ADDRESS_SPACE; | ||||||
|  | 	mpe->mpe_length = sizeof(*mpe); | ||||||
|  | 	mpe->mpe_busid = busid; | ||||||
|  | 	mpe->mpe_address_modifier = address_modifier; | ||||||
|  | 	mpe->mpe_range_list = range_list; | ||||||
|  | 	smp_add_mpe_entry(mc, (mpe_t)mpe); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										663
									
								
								src/boot/elfboot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										663
									
								
								src/boot/elfboot.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,663 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <part/fallback_boot.h> | ||||||
|  | #include <boot/elf.h> | ||||||
|  | #include <boot/elf_boot.h> | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  | #include <ip_checksum.h> | ||||||
|  | #include <stream/read_bytes.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | /* Maximum physical address we can use for the linuxBIOS bounce buffer. | ||||||
|  |  */ | ||||||
|  | #ifndef MAX_ADDR | ||||||
|  | #define MAX_ADDR -1UL | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | extern unsigned char _ram_seg; | ||||||
|  | extern unsigned char _eram_seg; | ||||||
|  |  | ||||||
|  | struct segment { | ||||||
|  | 	struct segment *next; | ||||||
|  | 	struct segment *prev; | ||||||
|  | 	struct segment *phdr_next; | ||||||
|  | 	struct segment *phdr_prev; | ||||||
|  | 	unsigned long s_addr; | ||||||
|  | 	unsigned long s_memsz; | ||||||
|  | 	unsigned long s_offset; | ||||||
|  | 	unsigned long s_filesz; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct verify_callback { | ||||||
|  | 	struct verify_callback *next; | ||||||
|  | 	int (*callback)(struct verify_callback *vcb,  | ||||||
|  | 		Elf_ehdr *ehdr, Elf_phdr *phdr, struct segment *head); | ||||||
|  | 	unsigned long desc_offset; | ||||||
|  | 	unsigned long desc_addr; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct ip_checksum_vcb { | ||||||
|  | 	struct verify_callback data; | ||||||
|  | 	unsigned short ip_checksum; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int verify_ip_checksum( | ||||||
|  | 	struct verify_callback *vcb,  | ||||||
|  | 	Elf_ehdr *ehdr, Elf_phdr *phdr, struct segment *head) | ||||||
|  | { | ||||||
|  | 	struct ip_checksum_vcb *cb; | ||||||
|  | 	struct segment *ptr; | ||||||
|  | 	unsigned long bytes; | ||||||
|  | 	unsigned long checksum; | ||||||
|  | 	unsigned char buff[2], *n_desc; | ||||||
|  | 	cb = (struct ip_checksum_vcb *)vcb; | ||||||
|  | 	/* zero the checksum so it's value won't | ||||||
|  | 	 * get in the way of verifying the checksum. | ||||||
|  | 	 */ | ||||||
|  | 	n_desc = 0; | ||||||
|  | 	if (vcb->desc_addr) { | ||||||
|  | 		n_desc = (unsigned char *)(vcb->desc_addr); | ||||||
|  | 		memcpy(buff, n_desc, 2); | ||||||
|  | 		memset(n_desc, 0, 2); | ||||||
|  | 	} | ||||||
|  | 	bytes = 0; | ||||||
|  | 	checksum = compute_ip_checksum(ehdr, sizeof(*ehdr)); | ||||||
|  | 	bytes += sizeof(*ehdr); | ||||||
|  | 	checksum = add_ip_checksums(bytes, checksum,  | ||||||
|  | 		compute_ip_checksum(phdr, ehdr->e_phnum*sizeof(*phdr))); | ||||||
|  | 	bytes += ehdr->e_phnum*sizeof(*phdr); | ||||||
|  | 	for(ptr = head->phdr_next; ptr != head; ptr = ptr->phdr_next) { | ||||||
|  | 		checksum = add_ip_checksums(bytes, checksum, | ||||||
|  | 			compute_ip_checksum((void *)ptr->s_addr, ptr->s_memsz)); | ||||||
|  | 		bytes += ptr->s_memsz; | ||||||
|  | 	} | ||||||
|  | 	if (n_desc != 0) { | ||||||
|  | 		memcpy(n_desc, buff, 2); | ||||||
|  | 	} | ||||||
|  | 	if (checksum != cb->ip_checksum) { | ||||||
|  | 		printk_err("Image checksum: %04x != computed checksum: %04x\n", | ||||||
|  | 			cb->ip_checksum, checksum); | ||||||
|  | 	} | ||||||
|  | 	return checksum == cb->ip_checksum; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* The problem:   | ||||||
|  |  * Static executables all want to share the same addresses | ||||||
|  |  * in memory because only a few addresses are reliably present on | ||||||
|  |  * a machine, and implementing general relocation is hard. | ||||||
|  |  * | ||||||
|  |  * The solution: | ||||||
|  |  * - Allocate a buffer twice the size of the linuxBIOS image. | ||||||
|  |  * - Anything that would overwrite linuxBIOS copy into the lower half of | ||||||
|  |  *   the buffer.  | ||||||
|  |  * - After loading an ELF image copy linuxBIOS to the upper half of the | ||||||
|  |  *   buffer. | ||||||
|  |  * - Then jump to the loaded image. | ||||||
|  |  *  | ||||||
|  |  * Benefits: | ||||||
|  |  * - Nearly arbitrary standalone executables can be loaded. | ||||||
|  |  * - LinuxBIOS is preserved, so it can be returned to. | ||||||
|  |  * - The implementation is still relatively simple, | ||||||
|  |  *   and much simpler then the general case implemented in kexec. | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | static unsigned long get_bounce_buffer(struct lb_memory *mem) | ||||||
|  | { | ||||||
|  | 	unsigned long lb_size; | ||||||
|  | 	unsigned long mem_entries; | ||||||
|  | 	unsigned long buffer; | ||||||
|  | 	int i; | ||||||
|  | 	lb_size = (unsigned long)(&_eram_seg - &_ram_seg); | ||||||
|  | 	/* Double linuxBIOS size so I have somewhere to place a copy to return to */ | ||||||
|  | 	lb_size = lb_size + lb_size; | ||||||
|  | 	mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); | ||||||
|  | 	buffer = 0; | ||||||
|  | 	for(i = 0; i < mem_entries; i++) { | ||||||
|  | 		unsigned long mstart, mend; | ||||||
|  | 		unsigned long msize; | ||||||
|  | 		unsigned long tbuffer; | ||||||
|  | 		if (mem->map[i].type != LB_MEM_RAM) | ||||||
|  | 			continue; | ||||||
|  | 		if (mem->map[i].start > MAX_ADDR) | ||||||
|  | 			continue; | ||||||
|  | 		if (mem->map[i].size < lb_size) | ||||||
|  | 			continue; | ||||||
|  | 		mstart = mem->map[i].start; | ||||||
|  | 		msize = MAX_ADDR - mstart +1; | ||||||
|  | 		if (msize > mem->map[i].size) | ||||||
|  | 			msize = mem->map[i].size; | ||||||
|  | 		mend = mstart + msize; | ||||||
|  | 		tbuffer = mend - lb_size; | ||||||
|  | 		if (tbuffer < buffer)  | ||||||
|  | 			continue; | ||||||
|  | 		buffer = tbuffer; | ||||||
|  | 	} | ||||||
|  | 	return buffer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static struct verify_callback *process_elf_notes( | ||||||
|  | 	unsigned char *header,  | ||||||
|  | 	unsigned long offset, unsigned long length) | ||||||
|  | { | ||||||
|  | 	struct verify_callback *cb_chain; | ||||||
|  | 	unsigned char *note, *end; | ||||||
|  | 	char *program, *version; | ||||||
|  |  | ||||||
|  | 	cb_chain = 0; | ||||||
|  | 	note = header + offset; | ||||||
|  | 	end = note + length; | ||||||
|  | 	program = version = 0; | ||||||
|  | 	while(note < end) { | ||||||
|  | 		Elf_Nhdr *hdr; | ||||||
|  | 		unsigned char *n_name, *n_desc, *next; | ||||||
|  | 		hdr = (Elf_Nhdr *)note; | ||||||
|  | 		n_name = note + sizeof(*hdr); | ||||||
|  | 		n_desc = n_name + ((hdr->n_namesz + 3) & ~3); | ||||||
|  | 		next = n_desc + ((hdr->n_descsz + 3) & ~3); | ||||||
|  | 		if (next > end) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if ((hdr->n_namesz == sizeof(ELF_NOTE_BOOT)) &&  | ||||||
|  | 			(memcmp(n_name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT)) == 0)) { | ||||||
|  | 			switch(hdr->n_type) { | ||||||
|  | 			case EIN_PROGRAM_NAME: | ||||||
|  | 				if (n_desc[hdr->n_descsz -1] == 0) { | ||||||
|  | 					program = n_desc; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case EIN_PROGRAM_VERSION: | ||||||
|  | 				if (n_desc[hdr->n_descsz -1] == 0) { | ||||||
|  | 					version = n_desc; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case EIN_PROGRAM_CHECKSUM: | ||||||
|  | 			{ | ||||||
|  | 				struct ip_checksum_vcb *cb; | ||||||
|  | 				cb = malloc(sizeof(*cb)); | ||||||
|  | 				cb->ip_checksum = *((uint16_t *)n_desc); | ||||||
|  | 				cb->data.callback = verify_ip_checksum; | ||||||
|  | 				cb->data.next = cb_chain; | ||||||
|  | 				cb->data.desc_offset = n_desc - header; | ||||||
|  | 				cb_chain = &cb->data; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		printk_spew("n_type: %08x n_name(%d): %-*.*s n_desc(%d): %-*.*s\n",  | ||||||
|  | 			hdr->n_type, | ||||||
|  | 			hdr->n_namesz, hdr->n_namesz, hdr->n_namesz, n_name, | ||||||
|  | 			hdr->n_descsz,hdr->n_descsz, hdr->n_descsz, n_desc); | ||||||
|  | 		note = next; | ||||||
|  | 	} | ||||||
|  | 	if (program && version) { | ||||||
|  | 		printk_info("Loading %s version: %s\n", | ||||||
|  | 			program, version); | ||||||
|  | 	} | ||||||
|  | 	return cb_chain; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int valid_area(struct lb_memory *mem, unsigned long buffer, | ||||||
|  | 	unsigned long start, unsigned long len) | ||||||
|  | { | ||||||
|  | 	/* Check through all of the memory segments and ensure | ||||||
|  | 	 * the segment that was passed in is completely contained | ||||||
|  | 	 * in RAM. | ||||||
|  | 	 */ | ||||||
|  | 	int i; | ||||||
|  | 	unsigned long end = start + len; | ||||||
|  | 	unsigned long mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); | ||||||
|  |  | ||||||
|  | 	/* See if I conflict with the bounce buffer */ | ||||||
|  | 	if (end >= buffer) { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Walk through the table of valid memory ranges and see if I | ||||||
|  | 	 * have a match. | ||||||
|  | 	 */ | ||||||
|  | 	for(i = 0; i < mem_entries; i++) { | ||||||
|  | 		uint64_t mstart, mend; | ||||||
|  | 		uint32_t mtype; | ||||||
|  | 		mtype = mem->map[i].type; | ||||||
|  | 		mstart = mem->map[i].start; | ||||||
|  | 		mend = mstart + mem->map[i].size; | ||||||
|  | 		if ((mtype == LB_MEM_RAM) && (start < mend) && (end > mstart)) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (i == mem_entries) { | ||||||
|  | 		printk_err("No matching ram area found for range:\n"); | ||||||
|  | 		printk_err("  [0x%016lx, 0x%016lx)\n", start, end); | ||||||
|  | 		printk_err("Ram areas\n"); | ||||||
|  | 		for(i = 0; i < mem_entries; i++) { | ||||||
|  | 			uint64_t mstart, mend; | ||||||
|  | 			uint32_t mtype; | ||||||
|  | 			mtype = mem->map[i].type; | ||||||
|  | 			mstart = mem->map[i].start; | ||||||
|  | 			mend = mstart + mem->map[i].size; | ||||||
|  | 			printk_err("  [0x%016lx, 0x%016lx) %s\n", | ||||||
|  | 				(unsigned long)mstart,  | ||||||
|  | 				(unsigned long)mend,  | ||||||
|  | 				(mtype == LB_MEM_RAM)?"RAM":"Reserved"); | ||||||
|  | 			 | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void relocate_segment(unsigned long buffer, struct segment *seg) | ||||||
|  | { | ||||||
|  | 	/* Modify all segments that want to load onto linuxBIOS | ||||||
|  | 	 * to load onto the bounce buffer instead. | ||||||
|  | 	 */ | ||||||
|  | 	unsigned long lb_start = (unsigned long)&_ram_seg; | ||||||
|  | 	unsigned long lb_end = (unsigned long)&_eram_seg; | ||||||
|  | 	unsigned long start, middle, end; | ||||||
|  |  | ||||||
|  | 	printk_spew("lb: [0x%016lx, 0x%016lx)\n",  | ||||||
|  | 		lb_start, lb_end); | ||||||
|  |  | ||||||
|  | 	start = seg->s_addr; | ||||||
|  | 	middle = start + seg->s_filesz; | ||||||
|  | 	end = start + seg->s_memsz; | ||||||
|  | 	/* I don't conflict with linuxBIOS so get out of here */ | ||||||
|  | 	if ((end <= lb_start) || (start >= lb_end)) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	printk_spew("segment: [0x%016lx, 0x%016lx, 0x%016lx)\n",  | ||||||
|  | 		start, middle, end); | ||||||
|  |  | ||||||
|  | 	/* Slice off a piece at the beginning | ||||||
|  | 	 * that doesn't conflict with linuxBIOS. | ||||||
|  | 	 */ | ||||||
|  | 	if (start < lb_start) { | ||||||
|  | 		struct segment *new; | ||||||
|  | 		unsigned long len = lb_start - start; | ||||||
|  | 		new = malloc(sizeof(*new)); | ||||||
|  | 		*new = *seg; | ||||||
|  | 		new->s_memsz = len; | ||||||
|  | 		seg->s_memsz -= len; | ||||||
|  | 		seg->s_addr += len; | ||||||
|  | 		seg->s_offset += len; | ||||||
|  | 		if (seg->s_filesz > len) { | ||||||
|  | 			new->s_filesz = len; | ||||||
|  | 			seg->s_filesz -= len; | ||||||
|  | 		} else { | ||||||
|  | 			seg->s_filesz = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* Order by stream offset */ | ||||||
|  | 		new->next = seg; | ||||||
|  | 		new->prev = seg->prev; | ||||||
|  | 		seg->prev->next = new; | ||||||
|  | 		seg->prev = new; | ||||||
|  | 		/* Order by original program header order */ | ||||||
|  | 		new->phdr_next = seg; | ||||||
|  | 		new->phdr_prev = seg->phdr_prev; | ||||||
|  | 		seg->phdr_prev->phdr_next = new; | ||||||
|  | 		seg->phdr_prev = new; | ||||||
|  |  | ||||||
|  | 		/* compute the new value of start */ | ||||||
|  | 		start = seg->s_addr; | ||||||
|  | 		 | ||||||
|  | 		printk_spew("   early: [0x%016lx, 0x%016lx, 0x%016lx)\n",  | ||||||
|  | 			new->s_addr,  | ||||||
|  | 			new->s_addr + new->s_filesz, | ||||||
|  | 			new->s_addr + new->s_memsz); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	/* Slice off a piece at the end  | ||||||
|  | 	 * that doesn't conflict with linuxBIOS  | ||||||
|  | 	 */ | ||||||
|  | 	if (end > lb_end) { | ||||||
|  | 		unsigned long len = lb_end - start; | ||||||
|  | 		struct segment *new; | ||||||
|  | 		new = malloc(sizeof(*new)); | ||||||
|  | 		*new = *seg; | ||||||
|  | 		seg->s_memsz = len; | ||||||
|  | 		new->s_memsz -= len; | ||||||
|  | 		new->s_addr += len; | ||||||
|  | 		new->s_offset += len; | ||||||
|  | 		if (seg->s_filesz > len) { | ||||||
|  | 			seg->s_filesz = len; | ||||||
|  | 			new->s_filesz -= len; | ||||||
|  | 		} else { | ||||||
|  | 			new->s_filesz = 0; | ||||||
|  | 		} | ||||||
|  | 		/* Order by stream offset */ | ||||||
|  | 		new->next = seg->next; | ||||||
|  | 		new->prev = seg; | ||||||
|  | 		seg->next->prev = new; | ||||||
|  | 		seg->next = new; | ||||||
|  | 		/* Order by original program header order */ | ||||||
|  | 		new->phdr_next = seg->phdr_next; | ||||||
|  | 		new->phdr_prev = seg; | ||||||
|  | 		seg->phdr_next->phdr_prev = new; | ||||||
|  | 		seg->phdr_next = new; | ||||||
|  |  | ||||||
|  | 		/* compute the new value of end */ | ||||||
|  | 		end = start + len; | ||||||
|  | 		 | ||||||
|  | 		printk_spew("   late: [0x%016lx, 0x%016lx, 0x%016lx)\n",  | ||||||
|  | 			new->s_addr,  | ||||||
|  | 			new->s_addr + new->s_filesz, | ||||||
|  | 			new->s_addr + new->s_memsz); | ||||||
|  | 		 | ||||||
|  | 	} | ||||||
|  | 	/* Now retarget this segment onto the bounce buffer */ | ||||||
|  | 	seg->s_addr = buffer + (seg->s_addr - lb_start); | ||||||
|  |  | ||||||
|  | 	printk_spew(" bounce: [0x%016lx, 0x%016lx, 0x%016lx)\n",  | ||||||
|  | 		seg->s_addr,  | ||||||
|  | 		seg->s_addr + seg->s_filesz,  | ||||||
|  | 		seg->s_addr + seg->s_memsz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int build_elf_segment_list( | ||||||
|  | 	struct segment *head,  | ||||||
|  | 	unsigned long bounce_buffer, struct lb_memory *mem, | ||||||
|  | 	Elf_phdr *phdr, int headers) | ||||||
|  | { | ||||||
|  | 	struct segment *ptr; | ||||||
|  | 	int i; | ||||||
|  | 	memset(head, 0, sizeof(*head)); | ||||||
|  | 	head->next = head->prev = head; | ||||||
|  | 	for(i = 0; i < headers; i++) { | ||||||
|  | 		struct segment *new; | ||||||
|  | 		/* Ignore data that I don't need to handle */ | ||||||
|  | 		if (phdr[i].p_type != PT_LOAD) { | ||||||
|  | 			printk_debug("Dropping non PT_LOAD segment\n"); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (phdr[i].p_memsz == 0) { | ||||||
|  | 			printk_debug("Dropping empty segment\n"); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		new = malloc(sizeof(*new)); | ||||||
|  | 		new->s_addr = phdr[i].p_paddr; | ||||||
|  | 		new->s_memsz = phdr[i].p_memsz; | ||||||
|  | 		new->s_offset = phdr[i].p_offset; | ||||||
|  | 		new->s_filesz = phdr[i].p_filesz; | ||||||
|  | 		printk_debug("New segment addr 0x%lx size 0x%lx offset 0x%lx filesize 0x%lx\n", | ||||||
|  | 			new->s_addr, new->s_memsz, new->s_offset, new->s_filesz); | ||||||
|  | 		/* Clean up the values */ | ||||||
|  | 		if (new->s_filesz > new->s_memsz)  { | ||||||
|  | 			new->s_filesz = new->s_memsz; | ||||||
|  | 		} | ||||||
|  | 		printk_debug("(cleaned up) New segment addr 0x%lx size 0x%lx offset 0x%lx filesize 0x%lx\n", | ||||||
|  | 			new->s_addr, new->s_memsz, new->s_offset, new->s_filesz); | ||||||
|  | 		for(ptr = head->next; ptr != head; ptr = ptr->next) { | ||||||
|  | 			if (new->s_offset < ptr->s_offset) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		/* Order by stream offset */ | ||||||
|  | 		new->next = ptr; | ||||||
|  | 		new->prev = ptr->prev; | ||||||
|  | 		ptr->prev->next = new; | ||||||
|  | 		ptr->prev = new; | ||||||
|  | 		/* Order by original program header order */ | ||||||
|  | 		new->phdr_next = head; | ||||||
|  | 		new->phdr_prev = head->phdr_prev; | ||||||
|  | 		head->phdr_prev->phdr_next  = new; | ||||||
|  | 		head->phdr_prev = new; | ||||||
|  |  | ||||||
|  | 		/* Verify the memory addresses in the segment are valid */ | ||||||
|  | 		if (!valid_area(mem, bounce_buffer, new->s_addr, new->s_memsz))  | ||||||
|  | 			goto out; | ||||||
|  |  | ||||||
|  | 		/* Modify the segment to load onto the bounce_buffer if necessary. | ||||||
|  | 		 */ | ||||||
|  | 		relocate_segment(bounce_buffer, new); | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  |  out: | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int load_elf_segments( | ||||||
|  | 	struct segment *head, unsigned char *header, unsigned long header_size) | ||||||
|  | { | ||||||
|  | 	unsigned long offset; | ||||||
|  | 	struct segment *ptr; | ||||||
|  | 	 | ||||||
|  | 	offset = 0; | ||||||
|  | 	for(ptr = head->next; ptr != head; ptr = ptr->next) { | ||||||
|  | 		unsigned long start_offset; | ||||||
|  | 		unsigned long skip_bytes, read_bytes; | ||||||
|  | 		unsigned char *dest, *middle, *end; | ||||||
|  | 		byte_offset_t result; | ||||||
|  | 		printk_debug("Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n", | ||||||
|  | 			ptr->s_addr, ptr->s_memsz, ptr->s_filesz); | ||||||
|  | 		 | ||||||
|  | 		/* Compute the boundaries of the segment */ | ||||||
|  | 		dest = (unsigned char *)(ptr->s_addr); | ||||||
|  | 		end = dest + ptr->s_memsz; | ||||||
|  | 		middle = dest + ptr->s_filesz; | ||||||
|  | 		start_offset = ptr->s_offset; | ||||||
|  | 		 | ||||||
|  | 		printk_spew("[ 0x%016lx, %016lx, 0x%016lx) <- %016lx\n", | ||||||
|  | 			(unsigned long)dest, | ||||||
|  | 			(unsigned long)middle, | ||||||
|  | 			(unsigned long)end, | ||||||
|  | 			(unsigned long)start_offset); | ||||||
|  | 		 | ||||||
|  | 		/* Skip intial buffer unused bytes */ | ||||||
|  | 		if (offset < header_size) { | ||||||
|  | 			if (start_offset < header_size) { | ||||||
|  | 				offset = start_offset; | ||||||
|  | 			} else { | ||||||
|  | 				offset = header_size; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		/* Skip the unused bytes */ | ||||||
|  | 		skip_bytes = start_offset - offset; | ||||||
|  | 		if (skip_bytes &&  | ||||||
|  | 			((result = stream_skip(skip_bytes)) != skip_bytes)) { | ||||||
|  | 			printk_err("ERROR: Skip of %ld bytes skiped %ld bytes\n", | ||||||
|  | 				skip_bytes, result); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		offset = start_offset; | ||||||
|  | 		 | ||||||
|  | 		/* Copy data from the initial buffer */ | ||||||
|  | 		if (offset < header_size) { | ||||||
|  | 			size_t len; | ||||||
|  | 			if ((ptr->s_filesz + start_offset) > header_size) { | ||||||
|  | 				len = header_size - start_offset; | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				len = ptr->s_filesz; | ||||||
|  | 			} | ||||||
|  | 			memcpy(dest, &header[start_offset], len); | ||||||
|  | 			dest += len; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		/* Read the segment into memory */ | ||||||
|  | 		read_bytes = middle - dest; | ||||||
|  | 		if (read_bytes &&  | ||||||
|  | 			((result = stream_read(dest, read_bytes)) != read_bytes)) { | ||||||
|  | 			printk_err("ERROR: Read of %ld bytes read %ld bytes...\n", | ||||||
|  | 				read_bytes, result); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		offset += ptr->s_filesz; | ||||||
|  | 		 | ||||||
|  | 		/* Zero the extra bytes between middle & end */ | ||||||
|  | 		if (middle < end) { | ||||||
|  | 			printk_debug("Clearing Segment: addr: 0x%016lx memsz: 0x%016lx\n", | ||||||
|  | 				(unsigned long)middle, end - middle); | ||||||
|  | 			 | ||||||
|  | 			/* Zero the extra bytes */ | ||||||
|  | 			memset(middle, 0, end - middle); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  |  out: | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int verify_loaded_image( | ||||||
|  | 	struct verify_callback *vcb, | ||||||
|  | 	Elf_ehdr *ehdr, Elf_phdr *phdr, | ||||||
|  | 	struct segment *head | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	struct segment *ptr; | ||||||
|  | 	int ok; | ||||||
|  | 	ok = 1; | ||||||
|  | 	for(; ok && vcb ; vcb = vcb->next) { | ||||||
|  | 		/* Find where the note is loaded */ | ||||||
|  | 		/* The whole note must be loaded intact | ||||||
|  | 		 * so an address of 0 for the descriptor is impossible | ||||||
|  | 		 */ | ||||||
|  | 		vcb->desc_addr = 0;  | ||||||
|  | 		for(ptr = head->next; ptr != head; ptr = ptr->next) { | ||||||
|  | 			unsigned long desc_addr; | ||||||
|  | 			desc_addr = ptr->s_addr + vcb->desc_offset - ptr->s_offset; | ||||||
|  | 			if ((desc_addr >= ptr->s_addr) && | ||||||
|  | 				(desc_addr < (ptr->s_addr + ptr->s_filesz))) { | ||||||
|  | 				vcb->desc_addr = desc_addr; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		ok = vcb->callback(vcb, ehdr, phdr, head); | ||||||
|  | 	} | ||||||
|  | 	return ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int elfload(struct lb_memory *mem, | ||||||
|  | 	unsigned char *header, unsigned long header_size) | ||||||
|  | { | ||||||
|  | 	Elf_ehdr *ehdr; | ||||||
|  | 	Elf_phdr *phdr; | ||||||
|  | 	void *entry; | ||||||
|  | 	struct segment head; | ||||||
|  | 	struct verify_callback *cb_chain; | ||||||
|  | 	unsigned long bounce_buffer; | ||||||
|  |  | ||||||
|  | 	/* Find a bounce buffer so I can load to linuxBIOS's current location */ | ||||||
|  | 	bounce_buffer = get_bounce_buffer(mem); | ||||||
|  | 	if (!bounce_buffer) { | ||||||
|  | 		printk_err("Could not find a bounce buffer...\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ehdr = (Elf_ehdr *)header; | ||||||
|  | 	entry = (void *)(ehdr->e_entry); | ||||||
|  | 	phdr = (Elf_phdr *)(&header[ehdr->e_phoff]); | ||||||
|  |  | ||||||
|  | 	/* Digest elf note information... */ | ||||||
|  | 	cb_chain = 0; | ||||||
|  | 	if ((phdr[0].p_type == PT_NOTE) &&  | ||||||
|  | 		((phdr[0].p_offset + phdr[0].p_filesz) < header_size)) { | ||||||
|  | 		cb_chain = process_elf_notes(header, | ||||||
|  | 			phdr[0].p_offset, phdr[0].p_filesz); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Preprocess the elf segments */ | ||||||
|  | 	if (!build_elf_segment_list(&head,  | ||||||
|  | 		bounce_buffer, mem, phdr, ehdr->e_phnum)) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	/* Load the segments */ | ||||||
|  | 	if (!load_elf_segments(&head, header, header_size)) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	printk_spew("Loaded segments\n"); | ||||||
|  | 	/* Verify the loaded image */ | ||||||
|  | 	if (!verify_loaded_image(cb_chain, ehdr, phdr, &head))  | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	printk_spew("verified segments\n"); | ||||||
|  | 	/* Shutdown the stream device */ | ||||||
|  | 	stream_fini(); | ||||||
|  | 	 | ||||||
|  | 	printk_spew("closed down stream\n"); | ||||||
|  | 	/* Reset to booting from this image as late as possible */ | ||||||
|  | 	boot_successful(); | ||||||
|  |  | ||||||
|  | 	printk_debug("Jumping to boot code at 0x%x\n", entry); | ||||||
|  | 	post_code(0xfe); | ||||||
|  |  | ||||||
|  | 	/* Jump to kernel */ | ||||||
|  | 	jmp_to_elf_entry(entry, bounce_buffer); | ||||||
|  | 	return 1; | ||||||
|  |  | ||||||
|  |  out: | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int elfboot(struct lb_memory *mem) | ||||||
|  | { | ||||||
|  | 	Elf_ehdr *ehdr; | ||||||
|  | 	static unsigned char header[ELF_HEAD_SIZE]; | ||||||
|  | 	int header_offset; | ||||||
|  | 	int i, result; | ||||||
|  |  | ||||||
|  | 	result = 0; | ||||||
|  | 	printk_info("\n"); | ||||||
|  | 	printk_info("Welcome to %s, the open sourced starter.\n", BOOTLOADER); | ||||||
|  | 	printk_info("January 2002, Eric Biederman.\n"); | ||||||
|  | 	printk_info("Version %s\n", BOOTLOADER_VERSION); | ||||||
|  | 	printk_info("\n"); | ||||||
|  | 	post_code(0xf8); | ||||||
|  |  | ||||||
|  | 	if (stream_init() < 0) { | ||||||
|  | 		printk_err("Could not initialize driver...\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Read in the initial ELF_HEAD_SIZE bytes */ | ||||||
|  | 	if (stream_read(header, ELF_HEAD_SIZE) != ELF_HEAD_SIZE) { | ||||||
|  | 		printk_err("Read failed...\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	/* Scan for an elf header */ | ||||||
|  | 	header_offset = -1; | ||||||
|  | 	for(i = 0; i < ELF_HEAD_SIZE - (sizeof(Elf_ehdr) + sizeof(Elf_phdr)); i+=16) { | ||||||
|  | 		ehdr = (Elf_ehdr *)(&header[i]); | ||||||
|  | 		if (memcmp(ehdr->e_ident, ELFMAG, 4) != 0) { | ||||||
|  | 			printk_spew("NO header at %d\n", i); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		printk_debug("Found ELF candiate at offset %d\n", i); | ||||||
|  | 		/* Sanity check the elf header */ | ||||||
|  | 		if ((ehdr->e_type == ET_EXEC) && | ||||||
|  | 			elf_check_arch(ehdr) && | ||||||
|  | 			(ehdr->e_ident[EI_VERSION] == EV_CURRENT) && | ||||||
|  | 			(ehdr->e_version == EV_CURRENT) && | ||||||
|  | 			(ehdr->e_ehsize == sizeof(Elf_ehdr)) && | ||||||
|  | 			(ehdr->e_phentsize = sizeof(Elf_phdr)) && | ||||||
|  | 			(ehdr->e_phoff < (ELF_HEAD_SIZE - i)) && | ||||||
|  | 			((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) <=  | ||||||
|  | 				(ELF_HEAD_SIZE - i))) { | ||||||
|  | 			header_offset = i; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		ehdr = 0; | ||||||
|  | 	} | ||||||
|  | 	printk_spew("header_offset is %d\n", header_offset); | ||||||
|  | 	if (header_offset == -1) { | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk_spew("Try to load at offset 0x%x\n", header_offset); | ||||||
|  | 	result = elfload(mem,  | ||||||
|  | 		header + header_offset , ELF_HEAD_SIZE - header_offset); | ||||||
|  |  out: | ||||||
|  | 	if (!result) { | ||||||
|  | 		/* Shutdown the stream device */ | ||||||
|  | 		stream_fini(); | ||||||
|  |  | ||||||
|  | 		printk_err("Cannot Load ELF Image\n"); | ||||||
|  |  | ||||||
|  | 		post_code(0xff); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										216
									
								
								src/boot/hardwaremain.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/boot/hardwaremain.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | |||||||
|  | /* | ||||||
|  | This software and ancillary information (herein called SOFTWARE ) | ||||||
|  | called LinuxBIOS          is made available under the terms described | ||||||
|  | here.  The SOFTWARE has been approved for release with associated | ||||||
|  | LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has | ||||||
|  | been authored by an employee or employees of the University of | ||||||
|  | California, operator of the Los Alamos National Laboratory under | ||||||
|  | Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The | ||||||
|  | U.S. Government has rights to use, reproduce, and distribute this | ||||||
|  | SOFTWARE.  The public may copy, distribute, prepare derivative works | ||||||
|  | and publicly display this SOFTWARE without charge, provided that this | ||||||
|  | Notice and any statement of authorship are reproduced on all copies. | ||||||
|  | Neither the Government nor the University makes any warranty, express | ||||||
|  | or implied, or assumes any liability or responsibility for the use of | ||||||
|  | this SOFTWARE.  If SOFTWARE is modified to produce derivative works, | ||||||
|  | such modified SOFTWARE should be clearly marked, so as not to confuse | ||||||
|  | it with the version available from LANL. | ||||||
|  |  */ | ||||||
|  | /* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL | ||||||
|  |  * rminnich@lanl.gov | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * C Bootstrap code for the LinuxBIOS | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <cpu/cpu.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <version.h> | ||||||
|  | #include <smp/start_stop.h> | ||||||
|  | #include <boot/tables.h> | ||||||
|  | #include <part/sizeram.h> | ||||||
|  | #include <device.h> | ||||||
|  | #include <pci.h> | ||||||
|  | #if 0 | ||||||
|  | #include <part/mainboard.h> | ||||||
|  | #endif | ||||||
|  | #if 0 | ||||||
|  | #include <part/hard_reset.h> | ||||||
|  | #endif | ||||||
|  | #include <smp/atomic.h> | ||||||
|  | #include <boot/elf.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef CONFIG_MAX_PHYSICAL_CPUS | ||||||
|  | #define CONFIG_MAX_PHYSICAL_CPUS CONFIG_MAX_CPUS | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* The processor map.  | ||||||
|  |  * Now that SMP is in linuxbios, and Linux counts on us | ||||||
|  |  * giving accurate information about processors, we need a map | ||||||
|  |  * of what processors are out there. This could be a bit mask,  | ||||||
|  |  * but we will be optimistic and hope we someday run on  | ||||||
|  |  * REALLY BIG SMPs. Also we may need more than one bit of  | ||||||
|  |  * info per processor at some point. I hope we don't need  | ||||||
|  |  * anything more complex than an int. | ||||||
|  |  */ | ||||||
|  | static unsigned long processor_map[MAX_CPUS]; | ||||||
|  |  | ||||||
|  | static struct mem_range *get_ramsize(void) | ||||||
|  | { | ||||||
|  | 	struct mem_range *mem = 0; | ||||||
|  | 	if (!mem) { | ||||||
|  | 		mem = sizeram(); | ||||||
|  | 	} | ||||||
|  | 	if (!mem) { | ||||||
|  | 		printk_err("No memory size information!\n"); | ||||||
|  | 		for(;;); | ||||||
|  | 	} | ||||||
|  | 	return mem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if SMP == 1 | ||||||
|  | /* Number of cpus that are currently running in linuxbios */ | ||||||
|  | static atomic_t active_cpus = ATOMIC_INIT(1); | ||||||
|  |  | ||||||
|  | void secondary_cpu_init(void) | ||||||
|  | { | ||||||
|  | 	struct mem_range *mem; | ||||||
|  | 	unsigned long id; | ||||||
|  | 	int index; | ||||||
|  |  | ||||||
|  | 	atomic_inc(&active_cpus); | ||||||
|  | 	printk_debug(__FUNCTION__ "\n"); | ||||||
|  | 	mem = get_ramsize(); | ||||||
|  | 	id = cpu_initialize(mem); | ||||||
|  | 	index = processor_index(id); | ||||||
|  | 	printk_debug(__FUNCTION__ "  %d/%u\n", index, id); | ||||||
|  | 	processor_map[index] = CPU_ENABLED; | ||||||
|  | 	atomic_dec(&active_cpus); | ||||||
|  | 	stop_cpu(id); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void wait_for_other_cpus(void) | ||||||
|  | { | ||||||
|  | 	int old_active_count, active_count; | ||||||
|  | 	int i; | ||||||
|  | 	old_active_count = 1; | ||||||
|  |  | ||||||
|  | 	active_count = atomic_read(&active_cpus); | ||||||
|  | 	while(active_count > 1) { | ||||||
|  | 		if (active_count != old_active_count) { | ||||||
|  | 			printk_info("Waiting for %d CPUS to stop\n", active_count); | ||||||
|  | 			old_active_count = active_count; | ||||||
|  | 		} | ||||||
|  | 		active_count = atomic_read(&active_cpus); | ||||||
|  | 	} | ||||||
|  | 	for(i = 0; i < MAX_CPUS; i++) { | ||||||
|  | 		if (!(processor_map[i] & CPU_ENABLED)) { | ||||||
|  | 			printk_err("CPU %d/%u did not initialize!\n", | ||||||
|  | 				i, initial_apicid[i]); | ||||||
|  | 			processor_map[i] = 0; | ||||||
|  | 			mainboard_cpu_fixup(i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	printk_debug("All AP CPUs stopped\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #else /* SMP */ | ||||||
|  | #define wait_for_other_cpus() do {} while(0) | ||||||
|  | #endif /* SMP */ | ||||||
|  |  | ||||||
|  | void hardwaremain(int boot_complete) | ||||||
|  | { | ||||||
|  | 	/* Processor ID of the BOOT cpu (i.e. the one running this code) */ | ||||||
|  | 	unsigned long boot_cpu; | ||||||
|  | 	int boot_index; | ||||||
|  |  | ||||||
|  | 	/* the order here is a bit tricky. We don't want to do much of  | ||||||
|  | 	 * anything that uses config registers until after PciAllocateResources | ||||||
|  | 	 * since that function also figures out what kind of config strategy | ||||||
|  | 	 * to use (type 1 or type 2).  | ||||||
|  | 	 * so we turn on cache, then worry about PCI setup, then do other  | ||||||
|  | 	 * things, so that the other work can use the PciRead* and PciWrite* | ||||||
|  | 	 * functions.  | ||||||
|  | 	 */ | ||||||
|  | 	struct mem_range *mem, *tmem; | ||||||
|  | 	struct lb_memory *lb_mem; | ||||||
|  | 	unsigned long totalmem; | ||||||
|  |  | ||||||
|  | 	post_code(0x80); | ||||||
|  | 	/* displayinit MUST PRECEDE ALL PRINTK! */ | ||||||
|  | 	console_init(); | ||||||
|  | 	 | ||||||
|  | 	post_code(0x39); | ||||||
|  | 	printk_notice("LinuxBIOS-%s%s %s %s...\n",  | ||||||
|  | 		linuxbios_version, linuxbios_extra_version, linuxbios_build, | ||||||
|  | 		(boot_complete)?"rebooting":"booting"); | ||||||
|  |  | ||||||
|  | 	post_code(0x40); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	/* If we have already booted attempt a hard reboot */ | ||||||
|  | 	if (boot_complete) { | ||||||
|  | 		hard_reset(); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | #if 1 | ||||||
|  |  | ||||||
|  | 	// pick how to scan the bus. This is first so we can get at memory size. | ||||||
|  | 	printk_info("Finding PCI configuration type.\n"); | ||||||
|  | 	pci_set_method(); | ||||||
|  | 	post_code(0x5f); | ||||||
|  | #if 0 | ||||||
|  | 	enumerate_static_devices(); | ||||||
|  | #endif | ||||||
|  | 	dev_enumerate(); | ||||||
|  | 	post_code(0x66); | ||||||
|  | 	// Now do the real bus | ||||||
|  | 	// we round the total ram up a lot for thing like the SISFB, which  | ||||||
|  | 	// shares high memory with the CPU.  | ||||||
|  | 	dev_configure(); | ||||||
|  | 	post_code(0x88); | ||||||
|  |  | ||||||
|  | 	dev_enable(); | ||||||
|  | 	dev_initialize(); | ||||||
|  | 	post_code(0x89); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	mem = get_ramsize(); | ||||||
|  | 	post_code(0x70); | ||||||
|  | 	totalmem = 0; | ||||||
|  | 	for(tmem = mem; tmem->sizek; tmem++) { | ||||||
|  | 		totalmem += tmem->sizek; | ||||||
|  | 	} | ||||||
|  | 	printk_info("totalram: %ldM\n",  | ||||||
|  | 		(totalmem + 512) >> 10); /* Round to the nearest meg */ | ||||||
|  |  | ||||||
|  | 	/* Fully initialize the cpu before configuring the bus */ | ||||||
|  | 	boot_cpu = cpu_initialize(mem); | ||||||
|  | 	boot_index = processor_index(boot_cpu); | ||||||
|  | 	printk_spew("BOOT CPU is %d\n", boot_cpu); | ||||||
|  | 	processor_map[boot_index] = CPU_BOOTPROCESSOR|CPU_ENABLED; | ||||||
|  |  | ||||||
|  | 	/* Now start the other cpus initializing  | ||||||
|  | 	 * The sooner they start the sooner they stop. | ||||||
|  | 	 */ | ||||||
|  | 	post_code(0x75); | ||||||
|  | 	startup_other_cpus(processor_map); | ||||||
|  | 	post_code(0x77); | ||||||
|  |  | ||||||
|  | 	/* make certain we are the only cpu running in linuxBIOS */ | ||||||
|  | 	wait_for_other_cpus(); | ||||||
|  |  | ||||||
|  | 	/* Now that we have collected all of our information | ||||||
|  | 	 * write our configuration tables. | ||||||
|  | 	 */ | ||||||
|  | 	lb_mem = write_tables(mem, processor_map); | ||||||
|  |  | ||||||
|  | 	elfboot(lb_mem); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										691
									
								
								src/config/LinuxBIOSDoc.config
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										691
									
								
								src/config/LinuxBIOSDoc.config
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,691 @@ | |||||||
|  | # Doxyfile 1.2.1 | ||||||
|  |  | ||||||
|  | # This file describes the settings to be used by doxygen for a project | ||||||
|  | # | ||||||
|  | # All text after a hash (#) is considered a comment and will be ignored | ||||||
|  | # The format is: | ||||||
|  | #       TAG = value [value, ...] | ||||||
|  | # For lists items can also be appended using: | ||||||
|  | #       TAG += value [value, ...] | ||||||
|  | # Values that contain spaces should be placed between quotes (" ") | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # General configuration options | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The PROJECT_NAME tag is a single word (or a sequence of words surrounded  | ||||||
|  | # by quotes) that should identify the project.  | ||||||
|  |  | ||||||
|  | PROJECT_NAME           = "LinuxBIOS" | ||||||
|  |  | ||||||
|  | # The PROJECT_NUMBER tag can be used to enter a project or revision number.  | ||||||
|  | # This could be handy for archiving the generated documentation or  | ||||||
|  | # if some version control system is used. | ||||||
|  |  | ||||||
|  | PROJECT_NUMBER         =  | ||||||
|  |  | ||||||
|  | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)  | ||||||
|  | # base path where the generated documentation will be put.  | ||||||
|  | # If a relative path is entered, it will be relative to the location  | ||||||
|  | # where doxygen was started. If left blank the current directory will be used. | ||||||
|  |  | ||||||
|  | OUTPUT_DIRECTORY       = . | ||||||
|  |  | ||||||
|  | # The OUTPUT_LANGUAGE tag is used to specify the language in which all  | ||||||
|  | # documentation generated by doxygen is written. Doxygen will use this  | ||||||
|  | # information to generate all constant output in the proper language.  | ||||||
|  | # The default language is English, other supported languages are:  | ||||||
|  | # Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,  | ||||||
|  | # Spanish, Russian, Croatian, Polish, and Portuguese. | ||||||
|  |  | ||||||
|  | OUTPUT_LANGUAGE        = English | ||||||
|  |  | ||||||
|  | # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in  | ||||||
|  | # documentation are documented, even if no documentation was available.  | ||||||
|  | # Private class members and static file members will be hidden unless  | ||||||
|  | # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES  | ||||||
|  |  | ||||||
|  | EXTRACT_ALL            = YES | ||||||
|  |  | ||||||
|  | # If the EXTRACT_PRIVATE tag is set to YES all private members of a class  | ||||||
|  | # will be included in the documentation.  | ||||||
|  |  | ||||||
|  | EXTRACT_PRIVATE        = YES | ||||||
|  |  | ||||||
|  | # If the EXTRACT_STATIC tag is set to YES all static members of a file  | ||||||
|  | # will be included in the documentation.  | ||||||
|  |  | ||||||
|  | EXTRACT_STATIC         = YES | ||||||
|  |  | ||||||
|  | # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all  | ||||||
|  | # undocumented members of documented classes, files or namespaces.  | ||||||
|  | # If set to NO (the default) these members will be included in the  | ||||||
|  | # various overviews, but no documentation section is generated.  | ||||||
|  | # This option has no effect if EXTRACT_ALL is enabled.  | ||||||
|  |  | ||||||
|  | HIDE_UNDOC_MEMBERS     = NO | ||||||
|  |  | ||||||
|  | # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all  | ||||||
|  | # undocumented classes that are normally visible in the class hierarchy.  | ||||||
|  | # If set to NO (the default) these class will be included in the various  | ||||||
|  | # overviews. This option has no effect if EXTRACT_ALL is enabled.  | ||||||
|  |  | ||||||
|  | HIDE_UNDOC_CLASSES     = NO | ||||||
|  |  | ||||||
|  | # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will  | ||||||
|  | # include brief member descriptions after the members that are listed in  | ||||||
|  | # the file and class documentation (similar to JavaDoc).  | ||||||
|  | # Set to NO to disable this.  | ||||||
|  |  | ||||||
|  | BRIEF_MEMBER_DESC      = YES | ||||||
|  |  | ||||||
|  | # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend  | ||||||
|  | # the brief description of a member or function before the detailed description.  | ||||||
|  | # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the  | ||||||
|  | # brief descriptions will be completely suppressed.  | ||||||
|  |  | ||||||
|  | REPEAT_BRIEF           = YES | ||||||
|  |  | ||||||
|  | # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then  | ||||||
|  | # Doxygen will generate a detailed section even if there is only a brief  | ||||||
|  | # description.  | ||||||
|  |  | ||||||
|  | ALWAYS_DETAILED_SEC    = NO | ||||||
|  |  | ||||||
|  | # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full  | ||||||
|  | # path before files name in the file list and in the header files. If set  | ||||||
|  | # to NO the shortest path that makes the file name unique will be used.  | ||||||
|  |  | ||||||
|  | FULL_PATH_NAMES        = NO | ||||||
|  |  | ||||||
|  | # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag  | ||||||
|  | # can be used to strip a user defined part of the path. Stripping is  | ||||||
|  | # only done if one of the specified strings matches the left-hand part of  | ||||||
|  | # the path. It is allowed to use relative paths in the argument list. | ||||||
|  |  | ||||||
|  | STRIP_FROM_PATH        =  | ||||||
|  |  | ||||||
|  | # The INTERNAL_DOCS tag determines if documentation  | ||||||
|  | # that is typed after a \internal command is included. If the tag is set  | ||||||
|  | # to NO (the default) then the documentation will be excluded.  | ||||||
|  | # Set it to YES to include the internal documentation.  | ||||||
|  |  | ||||||
|  | INTERNAL_DOCS          = NO | ||||||
|  |  | ||||||
|  | # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate a class diagram (in Html and LaTeX) for classes with base or  | ||||||
|  | # super classes. Setting the tag to NO turns the diagrams off.  | ||||||
|  |  | ||||||
|  | CLASS_DIAGRAMS         = YES | ||||||
|  |  | ||||||
|  | # If the SOURCE_BROWSER tag is set to YES then a list of source files will  | ||||||
|  | # be generated. Documented entities will be cross-referenced with these sources.  | ||||||
|  |  | ||||||
|  | SOURCE_BROWSER         = YES | ||||||
|  |  | ||||||
|  | # Setting the INLINE_SOURCES tag to YES will include the body  | ||||||
|  | # of functions and classes directly in the documentation.  | ||||||
|  |  | ||||||
|  | INLINE_SOURCES         = NO | ||||||
|  |  | ||||||
|  | # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct  | ||||||
|  | # doxygen to hide any special comment blocks from generated source code  | ||||||
|  | # fragments. Normal C and C++ comments will always remain visible.  | ||||||
|  |  | ||||||
|  | STRIP_CODE_COMMENTS    = YES | ||||||
|  |  | ||||||
|  | # If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen  | ||||||
|  | # will only generate file names in lower case letters. If set to  | ||||||
|  | # YES upper case letters are also allowed. This is useful if you have  | ||||||
|  | # classes or files whose names only differ in case and if your file system  | ||||||
|  | # supports case sensitive file names.  | ||||||
|  |  | ||||||
|  | CASE_SENSE_NAMES       = YES | ||||||
|  |  | ||||||
|  | # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen  | ||||||
|  | # will show members with their full class and namespace scopes in the  | ||||||
|  | # documentation. If set to YES the scope will be hidden.  | ||||||
|  |  | ||||||
|  | HIDE_SCOPE_NAMES       = NO | ||||||
|  |  | ||||||
|  | # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen  | ||||||
|  | # will generate a verbatim copy of the header file for each class for  | ||||||
|  | # which an include is specified. Set to NO to disable this.  | ||||||
|  |  | ||||||
|  | VERBATIM_HEADERS       = YES | ||||||
|  |  | ||||||
|  | # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen  | ||||||
|  | # will put list of the files that are included by a file in the documentation  | ||||||
|  | # of that file.  | ||||||
|  |  | ||||||
|  | SHOW_INCLUDE_FILES     = YES | ||||||
|  |  | ||||||
|  | # If the JAVADOC_AUTOBRIEF tag is set to YES (the default) then Doxygen  | ||||||
|  | # will interpret the first line (until the first dot) of a JavaDoc-style  | ||||||
|  | # comment as the brief description. If set to NO, the Javadoc-style will  | ||||||
|  | # behave just like the Qt-style comments.  | ||||||
|  |  | ||||||
|  | JAVADOC_AUTOBRIEF      = YES | ||||||
|  |  | ||||||
|  | # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented  | ||||||
|  | # member inherits the documentation from any documented member that it  | ||||||
|  | # reimplements.  | ||||||
|  |  | ||||||
|  | INHERIT_DOCS           = YES | ||||||
|  |  | ||||||
|  | # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]  | ||||||
|  | # is inserted in the documentation for inline members.  | ||||||
|  |  | ||||||
|  | INLINE_INFO            = YES | ||||||
|  |  | ||||||
|  | # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen  | ||||||
|  | # will sort the (detailed) documentation of file and class members  | ||||||
|  | # alphabetically by member name. If set to NO the members will appear in  | ||||||
|  | # declaration order.  | ||||||
|  |  | ||||||
|  | SORT_MEMBER_DOCS       = YES | ||||||
|  |  | ||||||
|  | # The TAB_SIZE tag can be used to set the number of spaces in a tab.  | ||||||
|  | # Doxygen uses this value to replace tabs by spaces in code fragments.  | ||||||
|  |  | ||||||
|  | TAB_SIZE               = 8 | ||||||
|  |  | ||||||
|  | # The ENABLE_SECTIONS tag can be used to enable conditional  | ||||||
|  | # documentation sections, marked by \if sectionname ... \endif.  | ||||||
|  |  | ||||||
|  | ENABLED_SECTIONS       =  | ||||||
|  |  | ||||||
|  | # The GENERATE_TODOLIST tag can be used to enable (YES) or  | ||||||
|  | # disable (NO) the todo list. This list is created by putting \todo  | ||||||
|  | # commands in the documentation. | ||||||
|  |  | ||||||
|  | GENERATE_TODOLIST      = YES | ||||||
|  |  | ||||||
|  | # The GENERATE_TESTLIST tag can be used to enable (YES) or  | ||||||
|  | # disable (NO) the test list. This list is created by putting \test  | ||||||
|  | # commands in the documentation. | ||||||
|  |  | ||||||
|  | GENERATE_TESTLIST      = YES | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to warning and progress messages | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The QUIET tag can be used to turn on/off the messages that are generated  | ||||||
|  | # by doxygen. Possible values are YES and NO. If left blank NO is used.  | ||||||
|  |  | ||||||
|  | QUIET                  = NO | ||||||
|  |  | ||||||
|  | # The WARNINGS tag can be used to turn on/off the warning messages that are  | ||||||
|  | # generated by doxygen. Possible values are YES and NO. If left blank  | ||||||
|  | # NO is used.  | ||||||
|  |  | ||||||
|  | WARNINGS               = YES | ||||||
|  |  | ||||||
|  | # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings  | ||||||
|  | # for undocumented members. If EXTRACT_ALL is set to YES then this flag will  | ||||||
|  | # automatically be disabled.  | ||||||
|  |  | ||||||
|  | WARN_IF_UNDOCUMENTED   = YES | ||||||
|  |  | ||||||
|  | # The WARN_FORMAT tag determines the format of the warning messages that  | ||||||
|  | # doxygen can produce. The string should contain the $file, $line, and $text  | ||||||
|  | # tags, which will be replaced by the file and line number from which the  | ||||||
|  | # warning originated and the warning text.  | ||||||
|  |  | ||||||
|  | WARN_FORMAT            = "$file:$line: $text" | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the input files | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The INPUT tag can be used to specify the files and/or directories that contain  | ||||||
|  | # documented source files. You may enter file names like "myfile.cpp" or  | ||||||
|  | # directories like "/usr/src/myproject". Separate the files or directories  | ||||||
|  | # with spaces.  | ||||||
|  |  | ||||||
|  | # INPUT                  = ../src | ||||||
|  |  | ||||||
|  | # If the value of the INPUT tag contains directories, you can use the  | ||||||
|  | # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp  | ||||||
|  | # and *.h) to filter out the source-files in the directories. If left  | ||||||
|  | # blank all files are included.  | ||||||
|  |  | ||||||
|  | # FILE_PATTERNS          = *.c *.h *.S | ||||||
|  |  | ||||||
|  | # The RECURSIVE tag can be used to turn specify whether or not subdirectories  | ||||||
|  | # should be searched for input files as well. Possible values are YES and NO.  | ||||||
|  | # If left blank NO is used.  | ||||||
|  |  | ||||||
|  | RECURSIVE              = YES | ||||||
|  |  | ||||||
|  | # The EXCLUDE tag can be used to specify files and/or directories that should  | ||||||
|  | # excluded from the INPUT source files. This way you can easily exclude a  | ||||||
|  | # subdirectory from a directory tree whose root is specified with the INPUT tag.  | ||||||
|  |  | ||||||
|  | EXCLUDE                =  | ||||||
|  |  | ||||||
|  | # If the value of the INPUT tag contains directories, you can use the  | ||||||
|  | # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude  | ||||||
|  | # certain files from those directories.  | ||||||
|  |  | ||||||
|  | EXCLUDE_PATTERNS       =  | ||||||
|  |  | ||||||
|  | # The EXAMPLE_PATH tag can be used to specify one or more files or  | ||||||
|  | # directories that contain example code fragments that are included (see  | ||||||
|  | # the \include command).  | ||||||
|  |  | ||||||
|  | EXAMPLE_PATH           =  | ||||||
|  |  | ||||||
|  | # If the value of the EXAMPLE_PATH tag contains directories, you can use the  | ||||||
|  | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp  | ||||||
|  | # and *.h) to filter out the source-files in the directories. If left  | ||||||
|  | # blank all files are included.  | ||||||
|  |  | ||||||
|  | EXAMPLE_PATTERNS       =  | ||||||
|  |  | ||||||
|  | # The IMAGE_PATH tag can be used to specify one or more files or  | ||||||
|  | # directories that contain image that are included in the documentation (see  | ||||||
|  | # the \image command).  | ||||||
|  |  | ||||||
|  | IMAGE_PATH             =  | ||||||
|  |  | ||||||
|  | # The INPUT_FILTER tag can be used to specify a program that doxygen should  | ||||||
|  | # invoke to filter for each input file. Doxygen will invoke the filter program  | ||||||
|  | # by executing (via popen()) the command <filter> <input-file>, where <filter>  | ||||||
|  | # is the value of the INPUT_FILTER tag, and <input-file> is the name of an  | ||||||
|  | # input file. Doxygen will then use the output that the filter program writes  | ||||||
|  | # to standard output.  | ||||||
|  |  | ||||||
|  | INPUT_FILTER           =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the alphabetical class index | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index  | ||||||
|  | # of all compounds will be generated. Enable this if the project  | ||||||
|  | # contains a lot of classes, structs, unions or interfaces.  | ||||||
|  |  | ||||||
|  | ALPHABETICAL_INDEX     = NO | ||||||
|  |  | ||||||
|  | # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then  | ||||||
|  | # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns  | ||||||
|  | # in which this list will be split (can be a number in the range [1..20])  | ||||||
|  |  | ||||||
|  | COLS_IN_ALPHA_INDEX    = 5 | ||||||
|  |  | ||||||
|  | # In case all classes in a project start with a common prefix, all  | ||||||
|  | # classes will be put under the same header in the alphabetical index.  | ||||||
|  | # The IGNORE_PREFIX tag can be used to specify one or more prefixes that  | ||||||
|  | # should be ignored while generating the index headers.  | ||||||
|  |  | ||||||
|  | IGNORE_PREFIX          =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the HTML output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_HTML tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate HTML output.  | ||||||
|  |  | ||||||
|  | GENERATE_HTML          = YES | ||||||
|  |  | ||||||
|  | # The HTML_OUTPUT tag is used to specify where the HTML docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `html' will be used as the default path.  | ||||||
|  |  | ||||||
|  | HTML_OUTPUT            = html | ||||||
|  |  | ||||||
|  | # The HTML_HEADER tag can be used to specify a personal HTML header for  | ||||||
|  | # each generated HTML page. If it is left blank doxygen will generate a  | ||||||
|  | # standard header. | ||||||
|  |  | ||||||
|  | HTML_HEADER            =  | ||||||
|  |  | ||||||
|  | # The HTML_FOOTER tag can be used to specify a personal HTML footer for  | ||||||
|  | # each generated HTML page. If it is left blank doxygen will generate a  | ||||||
|  | # standard footer. | ||||||
|  |  | ||||||
|  | HTML_FOOTER            =  | ||||||
|  |  | ||||||
|  | # The HTML_STYLESHEET tag can be used to specify a user defined cascading  | ||||||
|  | # style sheet that is used by each HTML page. It can be used to  | ||||||
|  | # fine-tune the look of the HTML output. If the tag is left blank doxygen  | ||||||
|  | # will generate a default style sheet  | ||||||
|  |  | ||||||
|  | HTML_STYLESHEET        =  | ||||||
|  |  | ||||||
|  | # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,  | ||||||
|  | # files or namespaces will be aligned in HTML using tables. If set to  | ||||||
|  | # NO a bullet list will be used.  | ||||||
|  |  | ||||||
|  | HTML_ALIGN_MEMBERS     = YES | ||||||
|  |  | ||||||
|  | # If the GENERATE_HTMLHELP tag is set to YES, additional index files  | ||||||
|  | # will be generated that can be used as input for tools like the  | ||||||
|  | # Microsoft HTML help workshop to generate a compressed HTML help file (.chm)  | ||||||
|  | # of the generated HTML documentation.  | ||||||
|  |  | ||||||
|  | GENERATE_HTMLHELP      = NO | ||||||
|  |  | ||||||
|  | # The DISABLE_INDEX tag can be used to turn on/off the condensed index at  | ||||||
|  | # top of each HTML page. The value NO (the default) enables the index and  | ||||||
|  | # the value YES disables it.  | ||||||
|  |  | ||||||
|  | DISABLE_INDEX          = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the LaTeX output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate Latex output.  | ||||||
|  |  | ||||||
|  | GENERATE_LATEX         = YES | ||||||
|  |  | ||||||
|  | # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `latex' will be used as the default path.  | ||||||
|  |  | ||||||
|  | LATEX_OUTPUT           = latex | ||||||
|  |  | ||||||
|  | # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact  | ||||||
|  | # LaTeX documents. This may be useful for small projects and may help to  | ||||||
|  | # save some trees in general.  | ||||||
|  |  | ||||||
|  | COMPACT_LATEX          = NO | ||||||
|  |  | ||||||
|  | # The PAPER_TYPE tag can be used to set the paper type that is used  | ||||||
|  | # by the printer. Possible values are: a4, a4wide, letter, legal and  | ||||||
|  | # executive. If left blank a4wide will be used.  | ||||||
|  |  | ||||||
|  | PAPER_TYPE             = a4wide | ||||||
|  |  | ||||||
|  | # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX  | ||||||
|  | # packages that should be included in the LaTeX output.  | ||||||
|  |  | ||||||
|  | EXTRA_PACKAGES         =  | ||||||
|  |  | ||||||
|  | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for  | ||||||
|  | # the generated latex document. The header should contain everything until  | ||||||
|  | # the first chapter. If it is left blank doxygen will generate a  | ||||||
|  | # standard header. Notice: only use this tag if you know what you are doing!  | ||||||
|  |  | ||||||
|  | LATEX_HEADER           =  | ||||||
|  |  | ||||||
|  | # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated  | ||||||
|  | # is prepared for conversion to pdf (using ps2pdf). The pdf file will  | ||||||
|  | # contain links (just like the HTML output) instead of page references  | ||||||
|  | # This makes the output suitable for online browsing using a pdf viewer.  | ||||||
|  |  | ||||||
|  | PDF_HYPERLINKS         = NO | ||||||
|  |  | ||||||
|  | # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of  | ||||||
|  | # plain latex in the generated Makefile. Set this option to YES to get a  | ||||||
|  | # higher quality PDF documentation.  | ||||||
|  |  | ||||||
|  | USE_PDFLATEX           = NO | ||||||
|  |  | ||||||
|  | # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.  | ||||||
|  | # command to the generated LaTeX files. This will instruct LaTeX to keep  | ||||||
|  | # running if errors occur, instead of asking the user for help.  | ||||||
|  | # This option is also used when generating formulas in HTML.  | ||||||
|  |  | ||||||
|  | LATEX_BATCHMODE        = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the RTF output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output  | ||||||
|  | # The RTF output is optimised for Word 97 and may not look very pretty with  | ||||||
|  | # other RTF readers or editors. | ||||||
|  |  | ||||||
|  | GENERATE_RTF           = YES | ||||||
|  |  | ||||||
|  | # The RTF_OUTPUT tag is used to specify where the RTF docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `rtf' will be used as the default path.  | ||||||
|  |  | ||||||
|  | RTF_OUTPUT             = rtf | ||||||
|  |  | ||||||
|  | # If the COMPACT_RTF tag is set to YES Doxygen generates more compact  | ||||||
|  | # RTF documents. This may be useful for small projects and may help to  | ||||||
|  | # save some trees in general.  | ||||||
|  |  | ||||||
|  | COMPACT_RTF            = NO | ||||||
|  |  | ||||||
|  | # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated  | ||||||
|  | # will contain hyperlink fields. The RTF file will  | ||||||
|  | # contain links (just like the HTML output) instead of page references.  | ||||||
|  | # This makes the output suitable for online browsing using a WORD or other.  | ||||||
|  | # programs which support those fields.  | ||||||
|  | # Note: wordpad (write) and others do not support links.  | ||||||
|  |  | ||||||
|  | RTF_HYPERLINKS         = NO | ||||||
|  |  | ||||||
|  | # Load stylesheet definitions from file. Syntax is similar to doxygen's  | ||||||
|  | # config file, i.e. a series of assigments. You only have to provide  | ||||||
|  | # replacements, missing definitions are set to their default value.  | ||||||
|  |  | ||||||
|  | RTF_STYLESHEET_FILE    =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the man page output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_MAN tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate man pages  | ||||||
|  |  | ||||||
|  | GENERATE_MAN           = YES | ||||||
|  |  | ||||||
|  | # The MAN_OUTPUT tag is used to specify where the man pages will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `man' will be used as the default path.  | ||||||
|  |  | ||||||
|  | MAN_OUTPUT             = man | ||||||
|  |  | ||||||
|  | # The MAN_EXTENSION tag determines the extension that is added to  | ||||||
|  | # the generated man pages (default is the subroutine's section .3)  | ||||||
|  |  | ||||||
|  | MAN_EXTENSION          = .3 | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the XML output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_XML tag is set to YES Doxygen will  | ||||||
|  | # generate an XML file that captures the structure of  | ||||||
|  | # the code including all documentation. Warning: This feature  | ||||||
|  | # is still experimental and very incomplete. | ||||||
|  |  | ||||||
|  | GENERATE_XML           = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration options related to the preprocessor    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will  | ||||||
|  | # evaluate all C-preprocessor directives found in the sources and include  | ||||||
|  | # files.  | ||||||
|  |  | ||||||
|  | ENABLE_PREPROCESSING   = YES | ||||||
|  |  | ||||||
|  | # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro  | ||||||
|  | # names in the source code. If set to NO (the default) only conditional  | ||||||
|  | # compilation will be performed. Macro expansion can be done in a controlled  | ||||||
|  | # way by setting EXPAND_ONLY_PREDEF to YES.  | ||||||
|  |  | ||||||
|  | MACRO_EXPANSION        = NO | ||||||
|  |  | ||||||
|  | # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES  | ||||||
|  | # then the macro expansion is limited to the macros specified with the  | ||||||
|  | # PREDEFINED and EXPAND_AS_PREDEFINED tags.  | ||||||
|  |  | ||||||
|  | EXPAND_ONLY_PREDEF     = NO | ||||||
|  |  | ||||||
|  | # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files  | ||||||
|  | # in the INCLUDE_PATH (see below) will be search if a #include is found.  | ||||||
|  |  | ||||||
|  | SEARCH_INCLUDES        = YES | ||||||
|  |  | ||||||
|  | # The INCLUDE_PATH tag can be used to specify one or more directories that  | ||||||
|  | # contain include files that are not input files but should be processed by  | ||||||
|  | # the preprocessor.  | ||||||
|  |  | ||||||
|  | INCLUDE_PATH           =  | ||||||
|  |  | ||||||
|  | # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard  | ||||||
|  | # patterns (like *.h and *.hpp) to filter out the header-files in the  | ||||||
|  | # directories. If left blank, the patterns specified with FILE_PATTERNS will  | ||||||
|  | # be used.  | ||||||
|  |  | ||||||
|  | INCLUDE_FILE_PATTERNS  =  | ||||||
|  |  | ||||||
|  | # The PREDEFINED tag can be used to specify one or more macro names that  | ||||||
|  | # are defined before the preprocessor is started (similar to the -D option of  | ||||||
|  | # gcc). The argument of the tag is a list of macros of the form: name  | ||||||
|  | # or name=definition (no spaces). If the definition and the = are  | ||||||
|  | # omitted =1 is assumed.  | ||||||
|  |  | ||||||
|  | PREDEFINED             =  | ||||||
|  |  | ||||||
|  | # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then  | ||||||
|  | # this tag can be used to specify a list of macro names that should be expanded.  | ||||||
|  | # The macro definition that is found in the sources will be used.  | ||||||
|  | # Use the PREDEFINED tag if you want to use a different macro definition.  | ||||||
|  |  | ||||||
|  | EXPAND_AS_DEFINED      =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration::addtions related to external references    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The TAGFILES tag can be used to specify one or more tagfiles.  | ||||||
|  |  | ||||||
|  | TAGFILES               =  | ||||||
|  |  | ||||||
|  | # When a file name is specified after GENERATE_TAGFILE, doxygen will create  | ||||||
|  | # a tag file that is based on the input files it reads.  | ||||||
|  |  | ||||||
|  | GENERATE_TAGFILE       =  | ||||||
|  |  | ||||||
|  | # If the ALLEXTERNALS tag is set to YES all external classes will be listed  | ||||||
|  | # in the class index. If set to NO only the inherited external classes  | ||||||
|  | # will be listed.  | ||||||
|  |  | ||||||
|  | ALLEXTERNALS           = NO | ||||||
|  |  | ||||||
|  | # The PERL_PATH should be the absolute path and name of the perl script  | ||||||
|  | # interpreter (i.e. the result of `which perl').  | ||||||
|  |  | ||||||
|  | PERL_PATH              = /usr/bin/perl | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration options related to the dot tool    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is  | ||||||
|  | # available from the path. This tool is part of Graphviz, a graph visualization  | ||||||
|  | # toolkit from AT&T and Lucent Bell Labs. The other options in this section  | ||||||
|  | # have no effect if this option is set to NO (the default)  | ||||||
|  |  | ||||||
|  | HAVE_DOT               = NO | ||||||
|  |  | ||||||
|  | # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will generate a graph for each documented class showing the direct and  | ||||||
|  | # indirect inheritance relations. Setting this tag to YES will force the  | ||||||
|  | # the CLASS_DIAGRAMS tag to NO. | ||||||
|  |  | ||||||
|  | CLASS_GRAPH            = YES | ||||||
|  |  | ||||||
|  | # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will generate a graph for each documented class showing the direct and  | ||||||
|  | # indirect implementation dependencies (inheritance, containment, and  | ||||||
|  | # class references variables) of the class with other documented classes.  | ||||||
|  |  | ||||||
|  | COLLABORATION_GRAPH    = YES | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to  | ||||||
|  | # YES then doxygen will generate a graph for each documented file showing  | ||||||
|  | # the direct and indirect include dependencies of the file with other  | ||||||
|  | # documented files.  | ||||||
|  |  | ||||||
|  | INCLUDE_GRAPH          = YES | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to  | ||||||
|  | # YES then doxygen will generate a graph for each documented header file showing  | ||||||
|  | # the documented files that directly or indirectly include this file  | ||||||
|  |  | ||||||
|  | INCLUDED_BY_GRAPH      = YES | ||||||
|  |  | ||||||
|  | # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will graphical hierarchy of all classes instead of a textual one.  | ||||||
|  |  | ||||||
|  | GRAPHICAL_HIERARCHY    = YES | ||||||
|  |  | ||||||
|  | # The tag DOT_PATH can be used to specify the path where the dot tool can be  | ||||||
|  | # found. If left blank, it is assumed the dot tool can be found on the path.  | ||||||
|  |  | ||||||
|  | DOT_PATH               =  | ||||||
|  |  | ||||||
|  | # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width  | ||||||
|  | # (in pixels) of the graphs generated by dot. If a graph becomes larger than  | ||||||
|  | # this value, doxygen will try to truncate the graph, so that it fits within  | ||||||
|  | # the specified constraint. Beware that most browsers cannot cope with very  | ||||||
|  | # large images.  | ||||||
|  |  | ||||||
|  | MAX_DOT_GRAPH_WIDTH    = 1024 | ||||||
|  |  | ||||||
|  | # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height  | ||||||
|  | # (in pixels) of the graphs generated by dot. If a graph becomes larger than  | ||||||
|  | # this value, doxygen will try to truncate the graph, so that it fits within  | ||||||
|  | # the specified constraint. Beware that most browsers cannot cope with very  | ||||||
|  | # large images.  | ||||||
|  |  | ||||||
|  | MAX_DOT_GRAPH_HEIGHT   = 1024 | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration::addtions related to the search engine    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The SEARCHENGINE tag specifies whether or not a search engine should be  | ||||||
|  | # used. If set to NO the values of all tags below this one will be ignored.  | ||||||
|  |  | ||||||
|  | SEARCHENGINE           = NO | ||||||
|  |  | ||||||
|  | # The CGI_NAME tag should be the name of the CGI script that  | ||||||
|  | # starts the search engine (doxysearch) with the correct parameters.  | ||||||
|  | # A script with this name will be generated by doxygen.  | ||||||
|  |  | ||||||
|  | CGI_NAME               = search.cgi | ||||||
|  |  | ||||||
|  | # The CGI_URL tag should be the absolute URL to the directory where the  | ||||||
|  | # cgi binaries are located. See the documentation of your http daemon for  | ||||||
|  | # details.  | ||||||
|  |  | ||||||
|  | CGI_URL                =  | ||||||
|  |  | ||||||
|  | # The DOC_URL tag should be the absolute URL to the directory where the  | ||||||
|  | # documentation is located. If left blank the absolute path to the  | ||||||
|  | # documentation, with file:// prepended to it, will be used.  | ||||||
|  |  | ||||||
|  | DOC_URL                =  | ||||||
|  |  | ||||||
|  | # The DOC_ABSPATH tag should be the absolute path to the directory where the  | ||||||
|  | # documentation is located. If left blank the directory on the local machine  | ||||||
|  | # will be used.  | ||||||
|  |  | ||||||
|  | DOC_ABSPATH            =  | ||||||
|  |  | ||||||
|  | # The BIN_ABSPATH tag must point to the directory where the doxysearch binary  | ||||||
|  | # is installed.  | ||||||
|  |  | ||||||
|  | BIN_ABSPATH            = /usr/local/bin/ | ||||||
|  |  | ||||||
|  | # The EXT_DOC_PATHS tag can be used to specify one or more paths to  | ||||||
|  | # documentation generated for other projects. This allows doxysearch to search  | ||||||
|  | # the documentation for these projects as well.  | ||||||
|  |  | ||||||
|  | EXT_DOC_PATHS          =  | ||||||
							
								
								
									
										691
									
								
								src/config/doxyscript.base
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										691
									
								
								src/config/doxyscript.base
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,691 @@ | |||||||
|  | # Doxyfile 1.2.1 | ||||||
|  |  | ||||||
|  | # This file describes the settings to be used by doxygen for a project | ||||||
|  | # | ||||||
|  | # All text after a hash (#) is considered a comment and will be ignored | ||||||
|  | # The format is: | ||||||
|  | #       TAG = value [value, ...] | ||||||
|  | # For lists items can also be appended using: | ||||||
|  | #       TAG += value [value, ...] | ||||||
|  | # Values that contain spaces should be placed between quotes (" ") | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # General configuration options | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The PROJECT_NAME tag is a single word (or a sequence of words surrounded  | ||||||
|  | # by quotes) that should identify the project.  | ||||||
|  |  | ||||||
|  | PROJECT_NAME           = "LinuxBIOS" | ||||||
|  |  | ||||||
|  | # The PROJECT_NUMBER tag can be used to enter a project or revision number.  | ||||||
|  | # This could be handy for archiving the generated documentation or  | ||||||
|  | # if some version control system is used. | ||||||
|  |  | ||||||
|  | PROJECT_NUMBER         =  | ||||||
|  |  | ||||||
|  | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)  | ||||||
|  | # base path where the generated documentation will be put.  | ||||||
|  | # If a relative path is entered, it will be relative to the location  | ||||||
|  | # where doxygen was started. If left blank the current directory will be used. | ||||||
|  |  | ||||||
|  | OUTPUT_DIRECTORY       = . | ||||||
|  |  | ||||||
|  | # The OUTPUT_LANGUAGE tag is used to specify the language in which all  | ||||||
|  | # documentation generated by doxygen is written. Doxygen will use this  | ||||||
|  | # information to generate all constant output in the proper language.  | ||||||
|  | # The default language is English, other supported languages are:  | ||||||
|  | # Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,  | ||||||
|  | # Spanish, Russian, Croatian, Polish, and Portuguese. | ||||||
|  |  | ||||||
|  | OUTPUT_LANGUAGE        = English | ||||||
|  |  | ||||||
|  | # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in  | ||||||
|  | # documentation are documented, even if no documentation was available.  | ||||||
|  | # Private class members and static file members will be hidden unless  | ||||||
|  | # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES  | ||||||
|  |  | ||||||
|  | EXTRACT_ALL            = YES | ||||||
|  |  | ||||||
|  | # If the EXTRACT_PRIVATE tag is set to YES all private members of a class  | ||||||
|  | # will be included in the documentation.  | ||||||
|  |  | ||||||
|  | EXTRACT_PRIVATE        = YES | ||||||
|  |  | ||||||
|  | # If the EXTRACT_STATIC tag is set to YES all static members of a file  | ||||||
|  | # will be included in the documentation.  | ||||||
|  |  | ||||||
|  | EXTRACT_STATIC         = YES | ||||||
|  |  | ||||||
|  | # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all  | ||||||
|  | # undocumented members of documented classes, files or namespaces.  | ||||||
|  | # If set to NO (the default) these members will be included in the  | ||||||
|  | # various overviews, but no documentation section is generated.  | ||||||
|  | # This option has no effect if EXTRACT_ALL is enabled.  | ||||||
|  |  | ||||||
|  | HIDE_UNDOC_MEMBERS     = NO | ||||||
|  |  | ||||||
|  | # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all  | ||||||
|  | # undocumented classes that are normally visible in the class hierarchy.  | ||||||
|  | # If set to NO (the default) these class will be included in the various  | ||||||
|  | # overviews. This option has no effect if EXTRACT_ALL is enabled.  | ||||||
|  |  | ||||||
|  | HIDE_UNDOC_CLASSES     = NO | ||||||
|  |  | ||||||
|  | # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will  | ||||||
|  | # include brief member descriptions after the members that are listed in  | ||||||
|  | # the file and class documentation (similar to JavaDoc).  | ||||||
|  | # Set to NO to disable this.  | ||||||
|  |  | ||||||
|  | BRIEF_MEMBER_DESC      = YES | ||||||
|  |  | ||||||
|  | # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend  | ||||||
|  | # the brief description of a member or function before the detailed description.  | ||||||
|  | # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the  | ||||||
|  | # brief descriptions will be completely suppressed.  | ||||||
|  |  | ||||||
|  | REPEAT_BRIEF           = YES | ||||||
|  |  | ||||||
|  | # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then  | ||||||
|  | # Doxygen will generate a detailed section even if there is only a brief  | ||||||
|  | # description.  | ||||||
|  |  | ||||||
|  | ALWAYS_DETAILED_SEC    = NO | ||||||
|  |  | ||||||
|  | # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full  | ||||||
|  | # path before files name in the file list and in the header files. If set  | ||||||
|  | # to NO the shortest path that makes the file name unique will be used.  | ||||||
|  |  | ||||||
|  | FULL_PATH_NAMES        = NO | ||||||
|  |  | ||||||
|  | # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag  | ||||||
|  | # can be used to strip a user defined part of the path. Stripping is  | ||||||
|  | # only done if one of the specified strings matches the left-hand part of  | ||||||
|  | # the path. It is allowed to use relative paths in the argument list. | ||||||
|  |  | ||||||
|  | STRIP_FROM_PATH        =  | ||||||
|  |  | ||||||
|  | # The INTERNAL_DOCS tag determines if documentation  | ||||||
|  | # that is typed after a \internal command is included. If the tag is set  | ||||||
|  | # to NO (the default) then the documentation will be excluded.  | ||||||
|  | # Set it to YES to include the internal documentation.  | ||||||
|  |  | ||||||
|  | INTERNAL_DOCS          = NO | ||||||
|  |  | ||||||
|  | # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate a class diagram (in Html and LaTeX) for classes with base or  | ||||||
|  | # super classes. Setting the tag to NO turns the diagrams off.  | ||||||
|  |  | ||||||
|  | CLASS_DIAGRAMS         = YES | ||||||
|  |  | ||||||
|  | # If the SOURCE_BROWSER tag is set to YES then a list of source files will  | ||||||
|  | # be generated. Documented entities will be cross-referenced with these sources.  | ||||||
|  |  | ||||||
|  | SOURCE_BROWSER         = YES | ||||||
|  |  | ||||||
|  | # Setting the INLINE_SOURCES tag to YES will include the body  | ||||||
|  | # of functions and classes directly in the documentation.  | ||||||
|  |  | ||||||
|  | INLINE_SOURCES         = NO | ||||||
|  |  | ||||||
|  | # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct  | ||||||
|  | # doxygen to hide any special comment blocks from generated source code  | ||||||
|  | # fragments. Normal C and C++ comments will always remain visible.  | ||||||
|  |  | ||||||
|  | STRIP_CODE_COMMENTS    = YES | ||||||
|  |  | ||||||
|  | # If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen  | ||||||
|  | # will only generate file names in lower case letters. If set to  | ||||||
|  | # YES upper case letters are also allowed. This is useful if you have  | ||||||
|  | # classes or files whose names only differ in case and if your file system  | ||||||
|  | # supports case sensitive file names.  | ||||||
|  |  | ||||||
|  | CASE_SENSE_NAMES       = YES | ||||||
|  |  | ||||||
|  | # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen  | ||||||
|  | # will show members with their full class and namespace scopes in the  | ||||||
|  | # documentation. If set to YES the scope will be hidden.  | ||||||
|  |  | ||||||
|  | HIDE_SCOPE_NAMES       = NO | ||||||
|  |  | ||||||
|  | # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen  | ||||||
|  | # will generate a verbatim copy of the header file for each class for  | ||||||
|  | # which an include is specified. Set to NO to disable this.  | ||||||
|  |  | ||||||
|  | VERBATIM_HEADERS       = YES | ||||||
|  |  | ||||||
|  | # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen  | ||||||
|  | # will put list of the files that are included by a file in the documentation  | ||||||
|  | # of that file.  | ||||||
|  |  | ||||||
|  | SHOW_INCLUDE_FILES     = YES | ||||||
|  |  | ||||||
|  | # If the JAVADOC_AUTOBRIEF tag is set to YES (the default) then Doxygen  | ||||||
|  | # will interpret the first line (until the first dot) of a JavaDoc-style  | ||||||
|  | # comment as the brief description. If set to NO, the Javadoc-style will  | ||||||
|  | # behave just like the Qt-style comments.  | ||||||
|  |  | ||||||
|  | JAVADOC_AUTOBRIEF      = YES | ||||||
|  |  | ||||||
|  | # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented  | ||||||
|  | # member inherits the documentation from any documented member that it  | ||||||
|  | # reimplements.  | ||||||
|  |  | ||||||
|  | INHERIT_DOCS           = YES | ||||||
|  |  | ||||||
|  | # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]  | ||||||
|  | # is inserted in the documentation for inline members.  | ||||||
|  |  | ||||||
|  | INLINE_INFO            = YES | ||||||
|  |  | ||||||
|  | # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen  | ||||||
|  | # will sort the (detailed) documentation of file and class members  | ||||||
|  | # alphabetically by member name. If set to NO the members will appear in  | ||||||
|  | # declaration order.  | ||||||
|  |  | ||||||
|  | SORT_MEMBER_DOCS       = YES | ||||||
|  |  | ||||||
|  | # The TAB_SIZE tag can be used to set the number of spaces in a tab.  | ||||||
|  | # Doxygen uses this value to replace tabs by spaces in code fragments.  | ||||||
|  |  | ||||||
|  | TAB_SIZE               = 8 | ||||||
|  |  | ||||||
|  | # The ENABLE_SECTIONS tag can be used to enable conditional  | ||||||
|  | # documentation sections, marked by \if sectionname ... \endif.  | ||||||
|  |  | ||||||
|  | ENABLED_SECTIONS       =  | ||||||
|  |  | ||||||
|  | # The GENERATE_TODOLIST tag can be used to enable (YES) or  | ||||||
|  | # disable (NO) the todo list. This list is created by putting \todo  | ||||||
|  | # commands in the documentation. | ||||||
|  |  | ||||||
|  | GENERATE_TODOLIST      = YES | ||||||
|  |  | ||||||
|  | # The GENERATE_TESTLIST tag can be used to enable (YES) or  | ||||||
|  | # disable (NO) the test list. This list is created by putting \test  | ||||||
|  | # commands in the documentation. | ||||||
|  |  | ||||||
|  | GENERATE_TESTLIST      = YES | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to warning and progress messages | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The QUIET tag can be used to turn on/off the messages that are generated  | ||||||
|  | # by doxygen. Possible values are YES and NO. If left blank NO is used.  | ||||||
|  |  | ||||||
|  | QUIET                  = NO | ||||||
|  |  | ||||||
|  | # The WARNINGS tag can be used to turn on/off the warning messages that are  | ||||||
|  | # generated by doxygen. Possible values are YES and NO. If left blank  | ||||||
|  | # NO is used.  | ||||||
|  |  | ||||||
|  | WARNINGS               = YES | ||||||
|  |  | ||||||
|  | # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings  | ||||||
|  | # for undocumented members. If EXTRACT_ALL is set to YES then this flag will  | ||||||
|  | # automatically be disabled.  | ||||||
|  |  | ||||||
|  | WARN_IF_UNDOCUMENTED   = YES | ||||||
|  |  | ||||||
|  | # The WARN_FORMAT tag determines the format of the warning messages that  | ||||||
|  | # doxygen can produce. The string should contain the $file, $line, and $text  | ||||||
|  | # tags, which will be replaced by the file and line number from which the  | ||||||
|  | # warning originated and the warning text.  | ||||||
|  |  | ||||||
|  | WARN_FORMAT            = "$file:$line: $text" | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the input files | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The INPUT tag can be used to specify the files and/or directories that contain  | ||||||
|  | # documented source files. You may enter file names like "myfile.cpp" or  | ||||||
|  | # directories like "/usr/src/myproject". Separate the files or directories  | ||||||
|  | # with spaces.  | ||||||
|  |  | ||||||
|  | # INPUT                  = ../src | ||||||
|  |  | ||||||
|  | # If the value of the INPUT tag contains directories, you can use the  | ||||||
|  | # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp  | ||||||
|  | # and *.h) to filter out the source-files in the directories. If left  | ||||||
|  | # blank all files are included.  | ||||||
|  |  | ||||||
|  | # FILE_PATTERNS          = *.c *.h *.S | ||||||
|  |  | ||||||
|  | # The RECURSIVE tag can be used to turn specify whether or not subdirectories  | ||||||
|  | # should be searched for input files as well. Possible values are YES and NO.  | ||||||
|  | # If left blank NO is used.  | ||||||
|  |  | ||||||
|  | RECURSIVE              = YES | ||||||
|  |  | ||||||
|  | # The EXCLUDE tag can be used to specify files and/or directories that should  | ||||||
|  | # excluded from the INPUT source files. This way you can easily exclude a  | ||||||
|  | # subdirectory from a directory tree whose root is specified with the INPUT tag.  | ||||||
|  |  | ||||||
|  | EXCLUDE                =  | ||||||
|  |  | ||||||
|  | # If the value of the INPUT tag contains directories, you can use the  | ||||||
|  | # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude  | ||||||
|  | # certain files from those directories.  | ||||||
|  |  | ||||||
|  | EXCLUDE_PATTERNS       =  | ||||||
|  |  | ||||||
|  | # The EXAMPLE_PATH tag can be used to specify one or more files or  | ||||||
|  | # directories that contain example code fragments that are included (see  | ||||||
|  | # the \include command).  | ||||||
|  |  | ||||||
|  | EXAMPLE_PATH           =  | ||||||
|  |  | ||||||
|  | # If the value of the EXAMPLE_PATH tag contains directories, you can use the  | ||||||
|  | # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp  | ||||||
|  | # and *.h) to filter out the source-files in the directories. If left  | ||||||
|  | # blank all files are included.  | ||||||
|  |  | ||||||
|  | EXAMPLE_PATTERNS       =  | ||||||
|  |  | ||||||
|  | # The IMAGE_PATH tag can be used to specify one or more files or  | ||||||
|  | # directories that contain image that are included in the documentation (see  | ||||||
|  | # the \image command).  | ||||||
|  |  | ||||||
|  | IMAGE_PATH             =  | ||||||
|  |  | ||||||
|  | # The INPUT_FILTER tag can be used to specify a program that doxygen should  | ||||||
|  | # invoke to filter for each input file. Doxygen will invoke the filter program  | ||||||
|  | # by executing (via popen()) the command <filter> <input-file>, where <filter>  | ||||||
|  | # is the value of the INPUT_FILTER tag, and <input-file> is the name of an  | ||||||
|  | # input file. Doxygen will then use the output that the filter program writes  | ||||||
|  | # to standard output.  | ||||||
|  |  | ||||||
|  | INPUT_FILTER           =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the alphabetical class index | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index  | ||||||
|  | # of all compounds will be generated. Enable this if the project  | ||||||
|  | # contains a lot of classes, structs, unions or interfaces.  | ||||||
|  |  | ||||||
|  | ALPHABETICAL_INDEX     = NO | ||||||
|  |  | ||||||
|  | # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then  | ||||||
|  | # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns  | ||||||
|  | # in which this list will be split (can be a number in the range [1..20])  | ||||||
|  |  | ||||||
|  | COLS_IN_ALPHA_INDEX    = 5 | ||||||
|  |  | ||||||
|  | # In case all classes in a project start with a common prefix, all  | ||||||
|  | # classes will be put under the same header in the alphabetical index.  | ||||||
|  | # The IGNORE_PREFIX tag can be used to specify one or more prefixes that  | ||||||
|  | # should be ignored while generating the index headers.  | ||||||
|  |  | ||||||
|  | IGNORE_PREFIX          =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the HTML output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_HTML tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate HTML output.  | ||||||
|  |  | ||||||
|  | GENERATE_HTML          = YES | ||||||
|  |  | ||||||
|  | # The HTML_OUTPUT tag is used to specify where the HTML docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `html' will be used as the default path.  | ||||||
|  |  | ||||||
|  | HTML_OUTPUT            = html | ||||||
|  |  | ||||||
|  | # The HTML_HEADER tag can be used to specify a personal HTML header for  | ||||||
|  | # each generated HTML page. If it is left blank doxygen will generate a  | ||||||
|  | # standard header. | ||||||
|  |  | ||||||
|  | HTML_HEADER            =  | ||||||
|  |  | ||||||
|  | # The HTML_FOOTER tag can be used to specify a personal HTML footer for  | ||||||
|  | # each generated HTML page. If it is left blank doxygen will generate a  | ||||||
|  | # standard footer. | ||||||
|  |  | ||||||
|  | HTML_FOOTER            =  | ||||||
|  |  | ||||||
|  | # The HTML_STYLESHEET tag can be used to specify a user defined cascading  | ||||||
|  | # style sheet that is used by each HTML page. It can be used to  | ||||||
|  | # fine-tune the look of the HTML output. If the tag is left blank doxygen  | ||||||
|  | # will generate a default style sheet  | ||||||
|  |  | ||||||
|  | HTML_STYLESHEET        =  | ||||||
|  |  | ||||||
|  | # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,  | ||||||
|  | # files or namespaces will be aligned in HTML using tables. If set to  | ||||||
|  | # NO a bullet list will be used.  | ||||||
|  |  | ||||||
|  | HTML_ALIGN_MEMBERS     = YES | ||||||
|  |  | ||||||
|  | # If the GENERATE_HTMLHELP tag is set to YES, additional index files  | ||||||
|  | # will be generated that can be used as input for tools like the  | ||||||
|  | # Microsoft HTML help workshop to generate a compressed HTML help file (.chm)  | ||||||
|  | # of the generated HTML documentation.  | ||||||
|  |  | ||||||
|  | GENERATE_HTMLHELP      = NO | ||||||
|  |  | ||||||
|  | # The DISABLE_INDEX tag can be used to turn on/off the condensed index at  | ||||||
|  | # top of each HTML page. The value NO (the default) enables the index and  | ||||||
|  | # the value YES disables it.  | ||||||
|  |  | ||||||
|  | DISABLE_INDEX          = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the LaTeX output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate Latex output.  | ||||||
|  |  | ||||||
|  | GENERATE_LATEX         = YES | ||||||
|  |  | ||||||
|  | # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `latex' will be used as the default path.  | ||||||
|  |  | ||||||
|  | LATEX_OUTPUT           = latex | ||||||
|  |  | ||||||
|  | # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact  | ||||||
|  | # LaTeX documents. This may be useful for small projects and may help to  | ||||||
|  | # save some trees in general.  | ||||||
|  |  | ||||||
|  | COMPACT_LATEX          = NO | ||||||
|  |  | ||||||
|  | # The PAPER_TYPE tag can be used to set the paper type that is used  | ||||||
|  | # by the printer. Possible values are: a4, a4wide, letter, legal and  | ||||||
|  | # executive. If left blank a4wide will be used.  | ||||||
|  |  | ||||||
|  | PAPER_TYPE             = a4wide | ||||||
|  |  | ||||||
|  | # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX  | ||||||
|  | # packages that should be included in the LaTeX output.  | ||||||
|  |  | ||||||
|  | EXTRA_PACKAGES         =  | ||||||
|  |  | ||||||
|  | # The LATEX_HEADER tag can be used to specify a personal LaTeX header for  | ||||||
|  | # the generated latex document. The header should contain everything until  | ||||||
|  | # the first chapter. If it is left blank doxygen will generate a  | ||||||
|  | # standard header. Notice: only use this tag if you know what you are doing!  | ||||||
|  |  | ||||||
|  | LATEX_HEADER           =  | ||||||
|  |  | ||||||
|  | # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated  | ||||||
|  | # is prepared for conversion to pdf (using ps2pdf). The pdf file will  | ||||||
|  | # contain links (just like the HTML output) instead of page references  | ||||||
|  | # This makes the output suitable for online browsing using a pdf viewer.  | ||||||
|  |  | ||||||
|  | PDF_HYPERLINKS         = NO | ||||||
|  |  | ||||||
|  | # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of  | ||||||
|  | # plain latex in the generated Makefile. Set this option to YES to get a  | ||||||
|  | # higher quality PDF documentation.  | ||||||
|  |  | ||||||
|  | USE_PDFLATEX           = NO | ||||||
|  |  | ||||||
|  | # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.  | ||||||
|  | # command to the generated LaTeX files. This will instruct LaTeX to keep  | ||||||
|  | # running if errors occur, instead of asking the user for help.  | ||||||
|  | # This option is also used when generating formulas in HTML.  | ||||||
|  |  | ||||||
|  | LATEX_BATCHMODE        = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the RTF output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output  | ||||||
|  | # The RTF output is optimised for Word 97 and may not look very pretty with  | ||||||
|  | # other RTF readers or editors. | ||||||
|  |  | ||||||
|  | GENERATE_RTF           = YES | ||||||
|  |  | ||||||
|  | # The RTF_OUTPUT tag is used to specify where the RTF docs will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `rtf' will be used as the default path.  | ||||||
|  |  | ||||||
|  | RTF_OUTPUT             = rtf | ||||||
|  |  | ||||||
|  | # If the COMPACT_RTF tag is set to YES Doxygen generates more compact  | ||||||
|  | # RTF documents. This may be useful for small projects and may help to  | ||||||
|  | # save some trees in general.  | ||||||
|  |  | ||||||
|  | COMPACT_RTF            = NO | ||||||
|  |  | ||||||
|  | # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated  | ||||||
|  | # will contain hyperlink fields. The RTF file will  | ||||||
|  | # contain links (just like the HTML output) instead of page references.  | ||||||
|  | # This makes the output suitable for online browsing using a WORD or other.  | ||||||
|  | # programs which support those fields.  | ||||||
|  | # Note: wordpad (write) and others do not support links.  | ||||||
|  |  | ||||||
|  | RTF_HYPERLINKS         = NO | ||||||
|  |  | ||||||
|  | # Load stylesheet definitions from file. Syntax is similar to doxygen's  | ||||||
|  | # config file, i.e. a series of assigments. You only have to provide  | ||||||
|  | # replacements, missing definitions are set to their default value.  | ||||||
|  |  | ||||||
|  | RTF_STYLESHEET_FILE    =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the man page output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_MAN tag is set to YES (the default) Doxygen will  | ||||||
|  | # generate man pages  | ||||||
|  |  | ||||||
|  | GENERATE_MAN           = YES | ||||||
|  |  | ||||||
|  | # The MAN_OUTPUT tag is used to specify where the man pages will be put.  | ||||||
|  | # If a relative path is entered the value of OUTPUT_DIRECTORY will be  | ||||||
|  | # put in front of it. If left blank `man' will be used as the default path.  | ||||||
|  |  | ||||||
|  | MAN_OUTPUT             = man | ||||||
|  |  | ||||||
|  | # The MAN_EXTENSION tag determines the extension that is added to  | ||||||
|  | # the generated man pages (default is the subroutine's section .3)  | ||||||
|  |  | ||||||
|  | MAN_EXTENSION          = .3 | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # configuration options related to the XML output | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the GENERATE_XML tag is set to YES Doxygen will  | ||||||
|  | # generate an XML file that captures the structure of  | ||||||
|  | # the code including all documentation. Warning: This feature  | ||||||
|  | # is still experimental and very incomplete. | ||||||
|  |  | ||||||
|  | GENERATE_XML           = NO | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration options related to the preprocessor    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will  | ||||||
|  | # evaluate all C-preprocessor directives found in the sources and include  | ||||||
|  | # files.  | ||||||
|  |  | ||||||
|  | ENABLE_PREPROCESSING   = YES | ||||||
|  |  | ||||||
|  | # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro  | ||||||
|  | # names in the source code. If set to NO (the default) only conditional  | ||||||
|  | # compilation will be performed. Macro expansion can be done in a controlled  | ||||||
|  | # way by setting EXPAND_ONLY_PREDEF to YES.  | ||||||
|  |  | ||||||
|  | MACRO_EXPANSION        = NO | ||||||
|  |  | ||||||
|  | # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES  | ||||||
|  | # then the macro expansion is limited to the macros specified with the  | ||||||
|  | # PREDEFINED and EXPAND_AS_PREDEFINED tags.  | ||||||
|  |  | ||||||
|  | EXPAND_ONLY_PREDEF     = NO | ||||||
|  |  | ||||||
|  | # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files  | ||||||
|  | # in the INCLUDE_PATH (see below) will be search if a #include is found.  | ||||||
|  |  | ||||||
|  | SEARCH_INCLUDES        = YES | ||||||
|  |  | ||||||
|  | # The INCLUDE_PATH tag can be used to specify one or more directories that  | ||||||
|  | # contain include files that are not input files but should be processed by  | ||||||
|  | # the preprocessor.  | ||||||
|  |  | ||||||
|  | INCLUDE_PATH           =  | ||||||
|  |  | ||||||
|  | # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard  | ||||||
|  | # patterns (like *.h and *.hpp) to filter out the header-files in the  | ||||||
|  | # directories. If left blank, the patterns specified with FILE_PATTERNS will  | ||||||
|  | # be used.  | ||||||
|  |  | ||||||
|  | INCLUDE_FILE_PATTERNS  =  | ||||||
|  |  | ||||||
|  | # The PREDEFINED tag can be used to specify one or more macro names that  | ||||||
|  | # are defined before the preprocessor is started (similar to the -D option of  | ||||||
|  | # gcc). The argument of the tag is a list of macros of the form: name  | ||||||
|  | # or name=definition (no spaces). If the definition and the = are  | ||||||
|  | # omitted =1 is assumed.  | ||||||
|  |  | ||||||
|  | PREDEFINED             =  | ||||||
|  |  | ||||||
|  | # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then  | ||||||
|  | # this tag can be used to specify a list of macro names that should be expanded.  | ||||||
|  | # The macro definition that is found in the sources will be used.  | ||||||
|  | # Use the PREDEFINED tag if you want to use a different macro definition.  | ||||||
|  |  | ||||||
|  | EXPAND_AS_DEFINED      =  | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration::addtions related to external references    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The TAGFILES tag can be used to specify one or more tagfiles.  | ||||||
|  |  | ||||||
|  | TAGFILES               =  | ||||||
|  |  | ||||||
|  | # When a file name is specified after GENERATE_TAGFILE, doxygen will create  | ||||||
|  | # a tag file that is based on the input files it reads.  | ||||||
|  |  | ||||||
|  | GENERATE_TAGFILE       =  | ||||||
|  |  | ||||||
|  | # If the ALLEXTERNALS tag is set to YES all external classes will be listed  | ||||||
|  | # in the class index. If set to NO only the inherited external classes  | ||||||
|  | # will be listed.  | ||||||
|  |  | ||||||
|  | ALLEXTERNALS           = NO | ||||||
|  |  | ||||||
|  | # The PERL_PATH should be the absolute path and name of the perl script  | ||||||
|  | # interpreter (i.e. the result of `which perl').  | ||||||
|  |  | ||||||
|  | PERL_PATH              = /usr/bin/perl | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration options related to the dot tool    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is  | ||||||
|  | # available from the path. This tool is part of Graphviz, a graph visualization  | ||||||
|  | # toolkit from AT&T and Lucent Bell Labs. The other options in this section  | ||||||
|  | # have no effect if this option is set to NO (the default)  | ||||||
|  |  | ||||||
|  | HAVE_DOT               = NO | ||||||
|  |  | ||||||
|  | # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will generate a graph for each documented class showing the direct and  | ||||||
|  | # indirect inheritance relations. Setting this tag to YES will force the  | ||||||
|  | # the CLASS_DIAGRAMS tag to NO. | ||||||
|  |  | ||||||
|  | CLASS_GRAPH            = YES | ||||||
|  |  | ||||||
|  | # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will generate a graph for each documented class showing the direct and  | ||||||
|  | # indirect implementation dependencies (inheritance, containment, and  | ||||||
|  | # class references variables) of the class with other documented classes.  | ||||||
|  |  | ||||||
|  | COLLABORATION_GRAPH    = YES | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to  | ||||||
|  | # YES then doxygen will generate a graph for each documented file showing  | ||||||
|  | # the direct and indirect include dependencies of the file with other  | ||||||
|  | # documented files.  | ||||||
|  |  | ||||||
|  | INCLUDE_GRAPH          = YES | ||||||
|  |  | ||||||
|  | # If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to  | ||||||
|  | # YES then doxygen will generate a graph for each documented header file showing  | ||||||
|  | # the documented files that directly or indirectly include this file  | ||||||
|  |  | ||||||
|  | INCLUDED_BY_GRAPH      = YES | ||||||
|  |  | ||||||
|  | # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen  | ||||||
|  | # will graphical hierarchy of all classes instead of a textual one.  | ||||||
|  |  | ||||||
|  | GRAPHICAL_HIERARCHY    = YES | ||||||
|  |  | ||||||
|  | # The tag DOT_PATH can be used to specify the path where the dot tool can be  | ||||||
|  | # found. If left blank, it is assumed the dot tool can be found on the path.  | ||||||
|  |  | ||||||
|  | DOT_PATH               =  | ||||||
|  |  | ||||||
|  | # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width  | ||||||
|  | # (in pixels) of the graphs generated by dot. If a graph becomes larger than  | ||||||
|  | # this value, doxygen will try to truncate the graph, so that it fits within  | ||||||
|  | # the specified constraint. Beware that most browsers cannot cope with very  | ||||||
|  | # large images.  | ||||||
|  |  | ||||||
|  | MAX_DOT_GRAPH_WIDTH    = 1024 | ||||||
|  |  | ||||||
|  | # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height  | ||||||
|  | # (in pixels) of the graphs generated by dot. If a graph becomes larger than  | ||||||
|  | # this value, doxygen will try to truncate the graph, so that it fits within  | ||||||
|  | # the specified constraint. Beware that most browsers cannot cope with very  | ||||||
|  | # large images.  | ||||||
|  |  | ||||||
|  | MAX_DOT_GRAPH_HEIGHT   = 1024 | ||||||
|  |  | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  | # Configuration::addtions related to the search engine    | ||||||
|  | #--------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | # The SEARCHENGINE tag specifies whether or not a search engine should be  | ||||||
|  | # used. If set to NO the values of all tags below this one will be ignored.  | ||||||
|  |  | ||||||
|  | SEARCHENGINE           = NO | ||||||
|  |  | ||||||
|  | # The CGI_NAME tag should be the name of the CGI script that  | ||||||
|  | # starts the search engine (doxysearch) with the correct parameters.  | ||||||
|  | # A script with this name will be generated by doxygen.  | ||||||
|  |  | ||||||
|  | CGI_NAME               = search.cgi | ||||||
|  |  | ||||||
|  | # The CGI_URL tag should be the absolute URL to the directory where the  | ||||||
|  | # cgi binaries are located. See the documentation of your http daemon for  | ||||||
|  | # details.  | ||||||
|  |  | ||||||
|  | CGI_URL                =  | ||||||
|  |  | ||||||
|  | # The DOC_URL tag should be the absolute URL to the directory where the  | ||||||
|  | # documentation is located. If left blank the absolute path to the  | ||||||
|  | # documentation, with file:// prepended to it, will be used.  | ||||||
|  |  | ||||||
|  | DOC_URL                =  | ||||||
|  |  | ||||||
|  | # The DOC_ABSPATH tag should be the absolute path to the directory where the  | ||||||
|  | # documentation is located. If left blank the directory on the local machine  | ||||||
|  | # will be used.  | ||||||
|  |  | ||||||
|  | DOC_ABSPATH            =  | ||||||
|  |  | ||||||
|  | # The BIN_ABSPATH tag must point to the directory where the doxysearch binary  | ||||||
|  | # is installed.  | ||||||
|  |  | ||||||
|  | BIN_ABSPATH            = /usr/local/bin/ | ||||||
|  |  | ||||||
|  | # The EXT_DOC_PATHS tag can be used to specify one or more paths to  | ||||||
|  | # documentation generated for other projects. This allows doxysearch to search  | ||||||
|  | # the documentation for these projects as well.  | ||||||
|  |  | ||||||
|  | EXT_DOC_PATHS          =  | ||||||
							
								
								
									
										112
									
								
								src/config/linuxbios_c.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/config/linuxbios_c.ld
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | /* | ||||||
|  |  *	Memory map: | ||||||
|  |  * | ||||||
|  |  *	_RAMBASE		 | ||||||
|  |  *				: data segment | ||||||
|  |  *				: bss segment | ||||||
|  |  *				: heap | ||||||
|  |  *				: stack | ||||||
|  |  */ | ||||||
|  | /* | ||||||
|  |  * Bootstrap code for the STPC Consumer | ||||||
|  |  * Copyright (c) 1999 by Net Insight AB. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *	Written by Johan Rydberg, based on work by Daniel Kahlin. | ||||||
|  |  *      Rewritten by Eric Biederman | ||||||
|  |  */ | ||||||
|  | /* | ||||||
|  |  *	We use ELF as output format. So that we can | ||||||
|  |  *	debug the code in some form.  | ||||||
|  |  */ | ||||||
|  | INCLUDE ldoptions | ||||||
|  |  | ||||||
|  | ENTRY(_start) | ||||||
|  |  | ||||||
|  | SECTIONS | ||||||
|  | { | ||||||
|  | 	. = _RAMBASE; | ||||||
|  | 	/* | ||||||
|  | 	 * First we place the code and read only data (typically const declared). | ||||||
|  | 	 * This get placed in rom. | ||||||
|  | 	 */ | ||||||
|  | 	.text : { | ||||||
|  | 		_text = .; | ||||||
|  | 		*(.text); | ||||||
|  | 		*(.text.*); | ||||||
|  | 		. = ALIGN(16); | ||||||
|  | 		_etext = .; | ||||||
|  | 	} | ||||||
|  | 	.rodata : { | ||||||
|  | 		_rodata = .; | ||||||
|  | 		. = ALIGN(4); | ||||||
|  | 		console_drivers = .; | ||||||
|  | 		*(.rodata.console_drivers) | ||||||
|  | 		econsole_drivers = . ; | ||||||
|  | 		. = ALIGN(4); | ||||||
|  | 		pci_drivers = . ; | ||||||
|  | 		*(.rodata.pci_drivers) | ||||||
|  | 		epci_drivers = . ; | ||||||
|  | 		*(.rodata) | ||||||
|  | 		*(.rodata.*) | ||||||
|  | 		/* | ||||||
|  | 		 * kevinh/Ispiri - Added an align, because the objcopy tool | ||||||
|  | 		 * incorrectly converts sections that are not long word aligned. | ||||||
|  | 		 * This breaksthe linuxbios.strip target. | ||||||
|  | 		 */ | ||||||
|  | 		 . = ALIGN(4); | ||||||
|  |  | ||||||
|  | 		_erodata = .; | ||||||
|  | 	}	 | ||||||
|  | 	/* | ||||||
|  | 	 * After the code we place initialized data (typically initialized | ||||||
|  | 	 * global variables). This gets copied into ram by startup code. | ||||||
|  | 	 * __data_start and __data_end shows where in ram this should be placed, | ||||||
|  | 	 * whereas __data_loadstart and __data_loadend shows where in rom to | ||||||
|  | 	 * copy from. | ||||||
|  | 	 */ | ||||||
|  | 	.data : { | ||||||
|  | 		_data = .; | ||||||
|  | 		*(.data) | ||||||
|  | 		_edata = .; | ||||||
|  | 	} | ||||||
|  | 	/* | ||||||
|  | 	 * bss does not contain data, it is just a space that should be zero | ||||||
|  | 	 * initialized on startup. (typically uninitialized global variables) | ||||||
|  | 	 * crt0.S fills between _bss and _ebss with zeroes. | ||||||
|  | 	 */ | ||||||
|  | 	_bss = .; | ||||||
|  | 	.bss . : { | ||||||
|  | 		*(.bss) | ||||||
|  | 		*(.sbss) | ||||||
|  | 		*(COMMON) | ||||||
|  | 	} | ||||||
|  | 	_ebss = .; | ||||||
|  | 	_end = .; | ||||||
|  | 	_stack = .; | ||||||
|  | 	.stack . : { | ||||||
|  | 		/* Reserve a stack for each possible cpu, +1 extra */ | ||||||
|  | 		. = ((MAX_CPUS * STACK_SIZE) + STACK_SIZE) ;  | ||||||
|  | 	} | ||||||
|  | 	_estack = .; | ||||||
|  | 	_heap = .; | ||||||
|  | 	.heap . : { | ||||||
|  | 		/* Reserve 256K for the heap */ | ||||||
|  | 		. = HEAP_SIZE ; | ||||||
|  | 		. = ALIGN(4); | ||||||
|  | 	} | ||||||
|  | 	_eheap = .; | ||||||
|  | 	/* The ram segment | ||||||
|  |  	 * This is all address of the memory resident copy of linuxBIOS. | ||||||
|  | 	 */ | ||||||
|  | 	_ram_seg = _text; | ||||||
|  | 	_eram_seg = _eheap; | ||||||
|  | 	/DISCARD/ : { | ||||||
|  | 		*(.comment) | ||||||
|  | 		*(.note) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										75
									
								
								src/console/console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/console/console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  | /* | ||||||
|  |  * Bootstrap code for the INTEL  | ||||||
|  |  * $Id$ | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <pc80/mc146818rtc.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int initialized; | ||||||
|  |  | ||||||
|  | /* initialize the console */ | ||||||
|  | void console_init(void) | ||||||
|  | { | ||||||
|  | 	struct console_driver *driver; | ||||||
|  | 	if(get_option(&console_loglevel, "debug_level")) | ||||||
|  | 		console_loglevel=DEFAULT_CONSOLE_LOGLEVEL; | ||||||
|  |  | ||||||
|  | 	for(driver = console_drivers; driver < econsole_drivers; driver++) { | ||||||
|  | 		if (!driver->init) | ||||||
|  | 			continue; | ||||||
|  | 		driver->init(); | ||||||
|  | 	} | ||||||
|  | 	initialized = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void __console_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	struct console_driver *driver; | ||||||
|  | 	for(driver = console_drivers; driver < econsole_drivers; driver++) { | ||||||
|  | 		driver->tx_byte(byte); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void console_tx_flush(void) | ||||||
|  | { | ||||||
|  | 	struct console_driver *driver; | ||||||
|  | 	for(driver = console_drivers; driver < econsole_drivers; driver++) { | ||||||
|  | 		if (!driver->tx_flush)  | ||||||
|  | 			continue; | ||||||
|  | 		driver->tx_flush(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void console_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	if (!initialized) | ||||||
|  | 		return; | ||||||
|  | 	if (byte == '\n') | ||||||
|  | 		__console_tx_byte('\r'); | ||||||
|  | 	__console_tx_byte(byte); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *    Write POST information | ||||||
|  |  */ | ||||||
|  | void post_code(uint8_t value) | ||||||
|  | { | ||||||
|  | #ifdef CONFIG_SERIAL_POST | ||||||
|  | 	printk_info("POST: 0x%02x\n", value); | ||||||
|  | #elsif !define(NO_POST) | ||||||
|  | 	outb(value, 0x80); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Report a fatal error */ | ||||||
|  | void die(char *msg) | ||||||
|  | { | ||||||
|  | 	printk_emerg("%s", msg); | ||||||
|  | 	post_code(0xff); | ||||||
|  | 	while (1);		/* Halt */ | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/console/logbuf_console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/console/logbuf_console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  | #define LOGBUF_SIZE  1024 | ||||||
|  |  | ||||||
|  | // KEEP THIS GLOBAL.  | ||||||
|  | // I need the address so I can watch it with the ARIUM hardware. RGM. | ||||||
|  | char logbuf[LOGBUF_SIZE]; | ||||||
|  | int logbuf_offset = 0; | ||||||
|  |  | ||||||
|  | static void logbuf_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	logbuf[logbuf_offset] = byte; | ||||||
|  | 	logbuf_offset = (logbuf_offset +1) % LOGBUF_SIZE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static struct console_driver __console = { | ||||||
|  | 	.init    = 0, | ||||||
|  | 	.tx_byte = logbuf_tx_byte, | ||||||
|  | };} | ||||||
							
								
								
									
										56
									
								
								src/console/printk.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/console/printk.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | /* | ||||||
|  |  *  blantantly copied from linux/kernel/printk.c | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 1991, 1992  Linus Torvalds | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef lint | ||||||
|  | static char rcsid[] = "$Id$"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //typedef void * va_list; | ||||||
|  |  | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <smp/spinlock.h> | ||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  | /* printk's without a loglevel use this.. */ | ||||||
|  | #define DEFAULT_MESSAGE_LOGLEVEL 4 /* BIOS_WARNING */ | ||||||
|  |  | ||||||
|  | /* We show everything that is MORE important than this.. */ | ||||||
|  | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ | ||||||
|  |  | ||||||
|  | /* Keep together for sysctl support */ | ||||||
|  |  | ||||||
|  | int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; | ||||||
|  | int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL; | ||||||
|  | int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL; | ||||||
|  | int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; | ||||||
|  |  | ||||||
|  | void display(char*); | ||||||
|  | extern int vtxprintf(void (*)(unsigned char), const char *, va_list); | ||||||
|  |  | ||||||
|  | spinlock_t console_lock = SPIN_LOCK_UNLOCKED; | ||||||
|  |  | ||||||
|  | int do_printk(int msg_level, const char *fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list args; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	if (msg_level >= console_loglevel) { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	spin_lock(&console_lock); | ||||||
|  |  | ||||||
|  | 	va_start(args, fmt); | ||||||
|  | 	i = vtxprintf(console_tx_byte, fmt, args); | ||||||
|  | 	va_end(args); | ||||||
|  |  | ||||||
|  | 	console_tx_flush(); | ||||||
|  |  | ||||||
|  | 	spin_unlock(&console_lock); | ||||||
|  |  | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								src/console/uart8250_console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/console/uart8250_console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <uart8250.h> | ||||||
|  | #include <pc80/mc146818rtc.h> | ||||||
|  |  | ||||||
|  | /* Base Address */ | ||||||
|  | #ifndef TTYS0_BASE | ||||||
|  | #define TTYS0_BASE 0x3f8 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef TTYS0_BAUD | ||||||
|  | #define TTYS0_BAUD 115200 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ((115200%TTYS0_BAUD) != 0) | ||||||
|  | #error Bad ttys0 baud rate | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define TTYS0_DIV	(115200/TTYS0_BAUD) | ||||||
|  |  | ||||||
|  | /* Line Control Settings */ | ||||||
|  | #ifndef TTYS0_LCS | ||||||
|  | /* Set 8bit, 1 stop bit, no parity */ | ||||||
|  | #define TTYS0_LCS	0x3 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define UART_LCS	TTYS0_LCS | ||||||
|  |  | ||||||
|  | void ttyS0_init(void) | ||||||
|  | { | ||||||
|  | 	static unsigned char div[8]={1,2,3,6,12,24,48,96}; | ||||||
|  | 	int b_index=0; | ||||||
|  | 	unsigned int divisor=TTYS0_DIV; | ||||||
|  |  | ||||||
|  | 	if(get_option(&b_index,"baud_rate")==0) { | ||||||
|  | 		divisor=div[b_index]; | ||||||
|  | 	} | ||||||
|  | 	uart8250_init(TTYS0_BASE, divisor, TTYS0_LCS); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ttyS0_tx_byte(unsigned char data)  | ||||||
|  | { | ||||||
|  | 	uart8250_tx_byte(TTYS0_BASE, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static struct console_driver uart8250_console __console = { | ||||||
|  | 	.init    = ttyS0_init, | ||||||
|  | 	.tx_byte = ttyS0_tx_byte, | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										100
									
								
								src/console/vga_console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/console/vga_console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | |||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * modified from original freebios code | ||||||
|  |  * by Steve M. Gehlbach <steve@kesa.com> | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <pc80/vga.h> | ||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  | void beep(int ms); | ||||||
|  |  | ||||||
|  | static char *vidmem;		/* The video buffer, should be replaced by symbol in ldscript.ld */ | ||||||
|  | int vga_line, vga_col; | ||||||
|  |  | ||||||
|  | #define VIDBUFFER 0xB8000; | ||||||
|  |  | ||||||
|  | static void memsetw(void *s, int c, unsigned int n) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	 u16 *ss = (u16 *) s; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < n; i++) { | ||||||
|  | 		ss[i] = ( u16 ) c; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void vga_init(void) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	// these are globals | ||||||
|  | 	vga_line = 0; | ||||||
|  | 	vga_col = 0; | ||||||
|  | 	vidmem = (unsigned char *) VIDBUFFER; | ||||||
|  | 	 | ||||||
|  | 	// mainboard or chip specific init routines | ||||||
|  | 	// also loads font | ||||||
|  | 	vga_hardware_fixup(); | ||||||
|  | 	 | ||||||
|  | 	// set attributes, char for entire screen | ||||||
|  | 	// font should be previously loaded in  | ||||||
|  | 	// device specific code (vga_hardware_fixup) | ||||||
|  | 	 memsetw(vidmem, VGA_ATTR_CLR_WHT, 2*1024); // | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void vga_scroll(void) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2); | ||||||
|  | 	for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2) | ||||||
|  | 		vidmem[i] = ' '; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void vga_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	if (byte == '\n') { | ||||||
|  | 		vga_line++; | ||||||
|  | 		vga_col = 0; | ||||||
|  |  | ||||||
|  | 	} else if (byte == '\r') { | ||||||
|  | 		vga_col = 0; | ||||||
|  |  | ||||||
|  | 	} else if (byte == '\b') { | ||||||
|  | 		vga_col--; | ||||||
|  |  | ||||||
|  | 	} else if (byte == '\t') { | ||||||
|  | 		vga_col += 4; | ||||||
|  |  | ||||||
|  | 	} else if (byte == '\a') { | ||||||
|  | 		//beep | ||||||
|  | 		beep(500); | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  | 		vidmem[((vga_col + (vga_line *COLS)) * 2)] = byte; | ||||||
|  | 		vidmem[((vga_col + (vga_line *COLS)) * 2) +1] = VGA_ATTR_CLR_WHT; | ||||||
|  | 		vga_col++; | ||||||
|  | 	} | ||||||
|  | 	if (vga_col < 0) { | ||||||
|  | 		vga_col = 0; | ||||||
|  | 	} | ||||||
|  | 	if (vga_col >= COLS) { | ||||||
|  | 		vga_line++; | ||||||
|  | 		vga_col = 0; | ||||||
|  | 	} | ||||||
|  | 	if (vga_line >= LINES) { | ||||||
|  | 		vga_scroll(); | ||||||
|  | 		vga_line--; | ||||||
|  | 	} | ||||||
|  | 	// move the cursor | ||||||
|  | 	write_crtc((vga_col + (vga_line *COLS)) >> 8, CRTC_CURSOR_HI); | ||||||
|  | 	write_crtc((vga_col + (vga_line *COLS)) & 0x0ff, CRTC_CURSOR_LO); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct console_driver { | ||||||
|  | 	.init    = vga_init, | ||||||
|  | 	.tx_byte = vga_tx_byte, | ||||||
|  | }; | ||||||
							
								
								
									
										352
									
								
								src/console/vsprintf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								src/console/vsprintf.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | |||||||
|  | /* | ||||||
|  |  *  linux/lib/vsprintf.c | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 1991, 1992  Linus Torvalds | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ | ||||||
|  | /* | ||||||
|  |  * Wirzenius wrote this portably, Torvalds fucked it up :-) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef lint | ||||||
|  | static char rcsid[] = "$Id$"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | /* haha, don't need ctype.c */ | ||||||
|  | #define isdigit(c)	((c) >= '0' && (c) <= '9') | ||||||
|  | #define is_digit isdigit | ||||||
|  | #define isxdigit(c)	(((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) | ||||||
|  | #define islower(c)	((c) >= 'a' && (c) <= 'z') | ||||||
|  | #define toupper(c) __toupper(c) | ||||||
|  |  | ||||||
|  | static inline unsigned char __toupper(unsigned char c) | ||||||
|  | { | ||||||
|  |         if (islower(c)) | ||||||
|  |                 c -= 'a'-'A'; | ||||||
|  |         return c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) | ||||||
|  | { | ||||||
|  | 	unsigned long result = 0,value; | ||||||
|  |  | ||||||
|  | 	if (!base) { | ||||||
|  | 		base = 10; | ||||||
|  | 		if (*cp == '0') { | ||||||
|  | 			base = 8; | ||||||
|  | 			cp++; | ||||||
|  | 			if ((*cp == 'x') && isxdigit(cp[1])) { | ||||||
|  | 				cp++; | ||||||
|  | 				base = 16; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) | ||||||
|  | 	    ? toupper(*cp) : *cp)-'A'+10) < base) { | ||||||
|  | 		result = result*base + value; | ||||||
|  | 		cp++; | ||||||
|  | 	} | ||||||
|  | 	if (endp) | ||||||
|  | 		*endp = (char *)cp; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | long simple_strtol(const char *cp,char **endp,unsigned int base) | ||||||
|  | { | ||||||
|  | 	if(*cp=='-') | ||||||
|  | 		return -simple_strtoul(cp+1,endp,base); | ||||||
|  | 	return simple_strtoul(cp,endp,base); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int skip_atoi(const char **s) | ||||||
|  | { | ||||||
|  | 	int i=0; | ||||||
|  |  | ||||||
|  | 	while (is_digit(**s)) | ||||||
|  | 		i = i*10 + *((*s)++) - '0'; | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define ZEROPAD	1		/* pad with zero */ | ||||||
|  | #define SIGN	2		/* unsigned/signed long */ | ||||||
|  | #define PLUS	4		/* show plus */ | ||||||
|  | #define SPACE	8		/* space if plus */ | ||||||
|  | #define LEFT	16		/* left justified */ | ||||||
|  | #define SPECIAL	32		/* 0x */ | ||||||
|  | #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */ | ||||||
|  |  | ||||||
|  | #define do_div(n,base) ({ \ | ||||||
|  | int __res; \ | ||||||
|  | __res = ((unsigned long) n) % (unsigned) base; \ | ||||||
|  | n = ((unsigned long) n) / (unsigned) base; \ | ||||||
|  | __res; }) | ||||||
|  |  | ||||||
|  | static int number(void (*tx_byte)(unsigned char byte), long num, int base, int size, int precision | ||||||
|  | 	,int type) | ||||||
|  | { | ||||||
|  | 	char c,sign,tmp[66]; | ||||||
|  | 	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; | ||||||
|  | 	int i; | ||||||
|  | 	int count = 0; | ||||||
|  |  | ||||||
|  | 	if (type & LARGE) | ||||||
|  | 		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||||||
|  | 	if (type & LEFT) | ||||||
|  | 		type &= ~ZEROPAD; | ||||||
|  | 	if (base < 2 || base > 36) | ||||||
|  | 		return 0; | ||||||
|  | 	c = (type & ZEROPAD) ? '0' : ' '; | ||||||
|  | 	sign = 0; | ||||||
|  | 	if (type & SIGN) { | ||||||
|  | 		if (num < 0) { | ||||||
|  | 			sign = '-'; | ||||||
|  | 			num = -num; | ||||||
|  | 			size--; | ||||||
|  | 		} else if (type & PLUS) { | ||||||
|  | 			sign = '+'; | ||||||
|  | 			size--; | ||||||
|  | 		} else if (type & SPACE) { | ||||||
|  | 			sign = ' '; | ||||||
|  | 			size--; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (type & SPECIAL) { | ||||||
|  | 		if (base == 16) | ||||||
|  | 			size -= 2; | ||||||
|  | 		else if (base == 8) | ||||||
|  | 			size--; | ||||||
|  | 	} | ||||||
|  | 	i = 0; | ||||||
|  | 	if (num == 0) | ||||||
|  | 		tmp[i++]='0'; | ||||||
|  | 	else while (num != 0) | ||||||
|  | 		tmp[i++] = digits[do_div(num,base)]; | ||||||
|  | 	if (i > precision) | ||||||
|  | 		precision = i; | ||||||
|  | 	size -= precision; | ||||||
|  | 	if (!(type&(ZEROPAD+LEFT))) | ||||||
|  | 		while(size-->0) | ||||||
|  | 			tx_byte(' '), count++; | ||||||
|  | 	if (sign) | ||||||
|  | 		tx_byte(sign), count++; | ||||||
|  | 	if (type & SPECIAL) { | ||||||
|  | 		if (base==8) | ||||||
|  | 			tx_byte('0'), count++; | ||||||
|  | 		else if (base==16) { | ||||||
|  | 			tx_byte('0'), count++; | ||||||
|  | 			tx_byte(digits[33]), count++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!(type & LEFT)) | ||||||
|  | 		while (size-- > 0) | ||||||
|  | 			tx_byte(c), count++; | ||||||
|  | 	while (i < precision--) | ||||||
|  | 		tx_byte('0'), count++; | ||||||
|  | 	while (i-- > 0) | ||||||
|  | 		tx_byte(tmp[i]), count++; | ||||||
|  | 	while (size-- > 0) | ||||||
|  | 		tx_byte(' '), count++; | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args) | ||||||
|  | { | ||||||
|  | 	int len; | ||||||
|  | 	unsigned long num; | ||||||
|  | 	int i, base; | ||||||
|  | 	const char *s; | ||||||
|  |  | ||||||
|  | 	int flags;		/* flags to number() */ | ||||||
|  |  | ||||||
|  | 	int field_width;	/* width of output field */ | ||||||
|  | 	int precision;		/* min. # of digits for integers; max | ||||||
|  | 				   number of chars for from string */ | ||||||
|  | 	int qualifier;		/* 'h', 'l', or 'L' for integer fields */ | ||||||
|  | 	 | ||||||
|  | 	int count; | ||||||
|  |  | ||||||
|  | 	for (count=0; *fmt ; ++fmt) { | ||||||
|  | 		if (*fmt != '%') { | ||||||
|  | 			tx_byte(*fmt), count++; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 			 | ||||||
|  | 		/* process flags */ | ||||||
|  | 		flags = 0; | ||||||
|  | 		repeat: | ||||||
|  | 			++fmt;		/* this also skips first '%' */ | ||||||
|  | 			switch (*fmt) { | ||||||
|  | 				case '-': flags |= LEFT; goto repeat; | ||||||
|  | 				case '+': flags |= PLUS; goto repeat; | ||||||
|  | 				case ' ': flags |= SPACE; goto repeat; | ||||||
|  | 				case '#': flags |= SPECIAL; goto repeat; | ||||||
|  | 				case '0': flags |= ZEROPAD; goto repeat; | ||||||
|  | 				} | ||||||
|  | 		 | ||||||
|  | 		/* get field width */ | ||||||
|  | 		field_width = -1; | ||||||
|  | 		if (is_digit(*fmt)) | ||||||
|  | 			field_width = skip_atoi(&fmt); | ||||||
|  | 		else if (*fmt == '*') { | ||||||
|  | 			++fmt; | ||||||
|  | 			/* it's the next argument */ | ||||||
|  | 			field_width = va_arg(args, int); | ||||||
|  | 			if (field_width < 0) { | ||||||
|  | 				field_width = -field_width; | ||||||
|  | 				flags |= LEFT; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* get the precision */ | ||||||
|  | 		precision = -1; | ||||||
|  | 		if (*fmt == '.') { | ||||||
|  | 			++fmt;	 | ||||||
|  | 			if (is_digit(*fmt)) | ||||||
|  | 				precision = skip_atoi(&fmt); | ||||||
|  | 			else if (*fmt == '*') { | ||||||
|  | 				++fmt; | ||||||
|  | 				/* it's the next argument */ | ||||||
|  | 				precision = va_arg(args, int); | ||||||
|  | 			} | ||||||
|  | 			if (precision < 0) | ||||||
|  | 				precision = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* get the conversion qualifier */ | ||||||
|  | 		qualifier = -1; | ||||||
|  | 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { | ||||||
|  | 			qualifier = *fmt; | ||||||
|  | 			++fmt; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* default base */ | ||||||
|  | 		base = 10; | ||||||
|  |  | ||||||
|  | 		switch (*fmt) { | ||||||
|  | 		case 'c': | ||||||
|  | 			if (!(flags & LEFT)) | ||||||
|  | 				while (--field_width > 0) | ||||||
|  | 					tx_byte(' '), count++; | ||||||
|  | 			tx_byte((unsigned char) va_arg(args, int)), count++; | ||||||
|  | 			while (--field_width > 0) | ||||||
|  | 				tx_byte(' '), count++; | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		case 's': | ||||||
|  | 			s = va_arg(args, char *); | ||||||
|  | 			if (!s) | ||||||
|  | 				s = "<NULL>"; | ||||||
|  |  | ||||||
|  | 			len = strnlen(s, precision); | ||||||
|  |  | ||||||
|  | 			if (!(flags & LEFT)) | ||||||
|  | 				while (len < field_width--) | ||||||
|  | 					tx_byte(' '), count++; | ||||||
|  | 			for (i = 0; i < len; ++i) | ||||||
|  | 				tx_byte(*s++), count++; | ||||||
|  | 			while (len < field_width--) | ||||||
|  | 				tx_byte(' '), count++; | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		case 'p': | ||||||
|  | 			if (field_width == -1) { | ||||||
|  | 				field_width = 2*sizeof(void *); | ||||||
|  | 				flags |= ZEROPAD; | ||||||
|  | 			} | ||||||
|  | 			count += number(tx_byte, | ||||||
|  | 				(unsigned long) va_arg(args, void *), 16, | ||||||
|  | 				field_width, precision, flags); | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		case 'n': | ||||||
|  | 			if (qualifier == 'l') { | ||||||
|  | 				long * ip = va_arg(args, long *); | ||||||
|  | 				*ip = count; | ||||||
|  | 			} else { | ||||||
|  | 				int * ip = va_arg(args, int *); | ||||||
|  | 				*ip = count; | ||||||
|  | 			} | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		case '%': | ||||||
|  | 			tx_byte('%'), count++; | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		/* integer number formats - set up the flags and "break" */ | ||||||
|  | 		case 'o': | ||||||
|  | 			base = 8; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case 'X': | ||||||
|  | 			flags |= LARGE; | ||||||
|  | 		case 'x': | ||||||
|  | 			base = 16; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case 'd': | ||||||
|  | 		case 'i': | ||||||
|  | 			flags |= SIGN; | ||||||
|  | 		case 'u': | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		default: | ||||||
|  | 			tx_byte('%'), count++; | ||||||
|  | 			if (*fmt) | ||||||
|  | 				tx_byte(*fmt), count++; | ||||||
|  | 			else | ||||||
|  | 				--fmt; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (qualifier == 'l') | ||||||
|  | 			num = va_arg(args, unsigned long); | ||||||
|  | 		else if (qualifier == 'h') { | ||||||
|  | 			num = (unsigned short) va_arg(args, int); | ||||||
|  | 			if (flags & SIGN) | ||||||
|  | 				num = (short) num; | ||||||
|  | 		} else if (flags & SIGN) | ||||||
|  | 			num = va_arg(args, int); | ||||||
|  | 		else | ||||||
|  | 			num = va_arg(args, unsigned int); | ||||||
|  | 		count += number(tx_byte, num, base, field_width, precision, flags); | ||||||
|  | 	} | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* FIXME this global makes vsprintf non-reentrant | ||||||
|  |  */ | ||||||
|  | static char *str_buf; | ||||||
|  | static void str_tx_byte(unsigned char byte) | ||||||
|  | { | ||||||
|  | 	*str_buf = byte; | ||||||
|  | 	str_buf++; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int vsprintf(char * buf, const char *fmt, va_list args) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	str_buf = buf; | ||||||
|  | 	i = vtxprintf(str_tx_byte, fmt, args); | ||||||
|  | 	/* maeder/Ispiri -- The null termination was missing a deference */ | ||||||
|  | 	/*                  and was just zeroing out the pointer instead */ | ||||||
|  | 	*str_buf = '\0'; | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int sprintf(char * buf, const char *fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list args; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	va_start(args, fmt); | ||||||
|  | 	i=vsprintf(buf,fmt,args); | ||||||
|  | 	va_end(args); | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
							
								
								
									
										112
									
								
								src/cpu/i386/entry16.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/cpu/i386/entry16.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | /* | ||||||
|  | This software and ancillary information (herein called SOFTWARE ) | ||||||
|  | called LinuxBIOS          is made available under the terms described | ||||||
|  | here.  The SOFTWARE has been approved for release with associated | ||||||
|  | LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has | ||||||
|  | been authored by an employee or employees of the University of | ||||||
|  | California, operator of the Los Alamos National Laboratory under | ||||||
|  | Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The | ||||||
|  | U.S. Government has rights to use, reproduce, and distribute this | ||||||
|  | SOFTWARE.  The public may copy, distribute, prepare derivative works | ||||||
|  | and publicly display this SOFTWARE without charge, provided that this | ||||||
|  | Notice and any statement of authorship are reproduced on all copies. | ||||||
|  | Neither the Government nor the University makes any warranty, express | ||||||
|  | or implied, or assumes any liability or responsibility for the use of | ||||||
|  | this SOFTWARE.  If SOFTWARE is modified to produce derivative works, | ||||||
|  | such modified SOFTWARE should be clearly marked, so as not to confuse | ||||||
|  | it with the version available from LANL. | ||||||
|  |  */ | ||||||
|  | /* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL | ||||||
|  |  * rminnich@lanl.gov | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** Start code to put an i386 or later processor into 32-bit  | ||||||
|  |  * protected mode.  | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* .section ".rom.text" */ | ||||||
|  | #include <arch/rom_segs.h> | ||||||
|  | .code16 | ||||||
|  | .globl	EXT(_start) | ||||||
|  | .type EXT(_start), @function | ||||||
|  |  | ||||||
|  | EXT(_start):  | ||||||
|  | 	cli | ||||||
|  |  | ||||||
|  | /* thanks to kmliu@sis.tw.com for this TBL fix ... */ | ||||||
|  | /**/ | ||||||
|  | /* IMMEDIATELY invalidate the translation lookaside buffer before executing*/ | ||||||
|  | /* any further code.  Even though paging is disabled we could still get*/ | ||||||
|  | /*false address translations due to the TLB if we didn't invalidate it.*/ | ||||||
|  | /**/ | ||||||
|  | 	xorl	%eax, %eax | ||||||
|  | 	movl	%eax, %cr3    /* Invalidate TLB*/ | ||||||
|  |  | ||||||
|  | 	/* invalidate the cache */ | ||||||
|  | 	invd  | ||||||
|  |  | ||||||
|  | 	/* Note: gas handles memory addresses in 16 bit code very poorly. | ||||||
|  | 	 * In particular it doesn't appear to have a directive allowing you | ||||||
|  | 	 * associate a section or even an absolute offset with a segment register. | ||||||
|  | 	 * | ||||||
|  | 	 * This means that anything except cs:ip relative offsets are | ||||||
|  | 	 * a real pain in 16 bit mode.  And explains why it is almost | ||||||
|  | 	 * imposible to get gas to do lgdt correctly. | ||||||
|  | 	 * | ||||||
|  | 	 * One way to work around this is to have the linker do the | ||||||
|  | 	 * math instead of the assembler.  This solves the very | ||||||
|  | 	 * pratical problem of being able to write code that can | ||||||
|  | 	 * be relocated. | ||||||
|  | 	 * | ||||||
|  | 	 * An lgdt call before we have memory enabled cannot be  | ||||||
|  | 	 * position independent, as we cannot execute a call | ||||||
|  | 	 * instruction to get our current instruction pointer. | ||||||
|  | 	 * So while this code is relocateable it isn't arbitrarily | ||||||
|  | 	 * relocatable. | ||||||
|  | 	 * | ||||||
|  | 	 * The criteria for relocation have been relaxed to their  | ||||||
|  | 	 * utmost, so that we can use the same code for both | ||||||
|  | 	 * our initial entry point and startup of the second cpu. | ||||||
|  | 	 * The code assumes when executing at _start that: | ||||||
|  | 	 * (((cs & 0xfff) == 0) and (ip == _start & 0xffff)) | ||||||
|  | 	 * or | ||||||
|  | 	 * ((cs == anything) and (ip == 0)). | ||||||
|  | 	 * | ||||||
|  | 	 * The restrictions in reset16.inc mean that _start initially | ||||||
|  | 	 * must be loaded at or above 0xffff0000 or below 0x100000. | ||||||
|  | 	 * | ||||||
|  | 	 * The linker scripts computs gdtptr16_offset by simply returning | ||||||
|  | 	 * the low 16 bits.  This means that the intial segment used | ||||||
|  | 	 * when start is called must be 64K aligned.  This should not | ||||||
|  | 	 * restrict the address as the ip address can be anything. | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  | 	movw	%cs, %ax | ||||||
|  | 	shlw	$4, %ax | ||||||
|  | 	movw	$EXT(gdtptr16_offset), %bx | ||||||
|  | 	subw	%ax, %bx | ||||||
|  | 	data32  lgdt %cs:(%bx) | ||||||
|  |  | ||||||
|  | 	movl	%cr0, %eax | ||||||
|  | 	andl	$0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ | ||||||
|  | 	orl	$0x60000001, %eax /* CD, NW, PE = 1 */ | ||||||
|  | 	movl	%eax, %cr0 | ||||||
|  |  | ||||||
|  | 	/* Now that we are in protected mode jump to a 32 bit code segment. */ | ||||||
|  | 	data32	ljmp	$ROM_CODE_SEG, $__protected_start | ||||||
|  |  | ||||||
|  | /** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment | ||||||
|  |  * at 0x18; these are Linux-compatible.  | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | .align	4 | ||||||
|  | .globl EXT(gdtptr16) | ||||||
|  | EXT(gdtptr16): | ||||||
|  | 	.word	gdt_end - gdt -1 /* compute the table limit */ | ||||||
|  | 	.long	gdt		 /* we know the offset */ | ||||||
|  |  | ||||||
|  | .globl EXT(_estart) | ||||||
|  | EXT(_estart): | ||||||
|  | 	.code32 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								src/cpu/i386/entry16.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/cpu/i386/entry16.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | 	gdtptr16_offset = gdtptr16 & 0xffff; | ||||||
|  | 	_start_offset = _start & 0xffff; | ||||||
							
								
								
									
										55
									
								
								src/cpu/i386/entry32.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/cpu/i386/entry32.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | /* For starting linuxBIOS in protected mode */ | ||||||
|  |  | ||||||
|  | #include <arch/rom_segs.h> | ||||||
|  |  | ||||||
|  | /* 	.section ".rom.text" */ | ||||||
|  | 	.code32 | ||||||
|  |  | ||||||
|  | 	.align	4 | ||||||
|  | .globl EXT(gdtptr) | ||||||
|  |  | ||||||
|  | gdt: | ||||||
|  | EXT(gdtptr): | ||||||
|  | 	.word	gdt_end - gdt -1 /* compute the table limit */ | ||||||
|  | 	.long	gdt		 /* we know the offset */ | ||||||
|  | 	.word	0 | ||||||
|  |  | ||||||
|  | /* flat code segment */ | ||||||
|  | 	.word	0xffff, 0x0000		 | ||||||
|  | 	.byte	0x00, 0x9b, 0xcf, 0x00	 | ||||||
|  | 	 | ||||||
|  | /* flat data segment */ | ||||||
|  | 	.word	0xffff, 0x0000		 | ||||||
|  | 	.byte	0x00, 0x93, 0xcf, 0x00	 | ||||||
|  |  | ||||||
|  | gdt_end: | ||||||
|  | 	 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *	When we come here we are in protected mode. We expand  | ||||||
|  |  *	the stack and copies the data segment from ROM to the | ||||||
|  |  *	memory. | ||||||
|  |  * | ||||||
|  |  *	After that, we call the chipset bootstrap routine that | ||||||
|  |  *	does what is left of the chipset initialization.  | ||||||
|  |  * | ||||||
|  |  *	NOTE aligned to 4 so that we are sure that the prefetch | ||||||
|  |  *	cache will be reloaded. | ||||||
|  |  */ | ||||||
|  | 	.align	4 | ||||||
|  | .globl EXT(protected_start) | ||||||
|  | EXT(protected_start): | ||||||
|  |  | ||||||
|  | 	lgdt	%cs:gdtptr | ||||||
|  | 	ljmp	$ROM_CODE_SEG, $__protected_start | ||||||
|  | 	 | ||||||
|  | __protected_start: | ||||||
|  | 	intel_chip_post_macro(0x10)	/* post 10 */ | ||||||
|  |  | ||||||
|  | 	movw	$ROM_DATA_SEG, %ax | ||||||
|  | 	movw	%ax, %ds | ||||||
|  | 	movw	%ax, %es | ||||||
|  | 	movw	%ax, %ss | ||||||
|  | 	movw	%ax, %fs | ||||||
|  | 	movw	%ax, %gs | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								src/cpu/i386/entry32.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/cpu/i386/entry32.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | /* | ||||||
|  | 	_cache_ram_seg_base = DEFINED(CACHE_RAM_BASE)? CACHE_RAM_BASE - _rodata : 0; | ||||||
|  | 	_cache_ram_seg_base_low    = (_cache_ram_seg_base) & 0xffff; | ||||||
|  | 	_cache_ram_seg_base_middle = (_cache_ram_seg_base >> 16) & 0xff; | ||||||
|  | 	_cache_ram_seg_base_high   = (_cache_ram_seg_base >> 24) & 0xff; | ||||||
|  |  | ||||||
|  | 	_rom_code_seg_base =  _ltext - _text; | ||||||
|  | 	_rom_code_seg_base_low    = (_rom_code_seg_base) & 0xffff; | ||||||
|  | 	_rom_code_seg_base_middle = (_rom_code_seg_base >> 16) & 0xff; | ||||||
|  | 	_rom_code_seg_base_high   = (_rom_code_seg_base >> 24) & 0xff; | ||||||
|  | */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								src/cpu/i386/reset16.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/cpu/i386/reset16.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | 	.section ".reset" | ||||||
|  | 	.code16 | ||||||
|  | .globl	EXT(reset_vector) | ||||||
|  | EXT(reset_vector): | ||||||
|  | #if _ROMBASE >= 0xffff0000 | ||||||
|  | 	/* Hmm. | ||||||
|  | 	 * _start_offset is the low 16 bits of _start. | ||||||
|  | 	 * Theoretically we should have problems but it compiles | ||||||
|  | 	 * and links properly with binutils 2.9.5 & 2.10.90 | ||||||
|  | 	 * This is probably a case that needs fixing in binutils. | ||||||
|  | 	 * And then we can just use _start. | ||||||
|  | 	 * We also need something like the assume directive in | ||||||
|  | 	 * other assemblers to tell it where the segment registers | ||||||
|  | 	 * are pointing in memory right now. | ||||||
|  | 	 */ | ||||||
|  | 	jmp	EXT(_start_offset) | ||||||
|  | #elif (_ROMBASE < 0x100000) | ||||||
|  | 	ljmp	$((_ROMBASE & 0xf0000)>>4),$EXT(_start_offset); | ||||||
|  | #else | ||||||
|  | #error	_ROMBASE is an unsupported value | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	. = 0x8; | ||||||
|  | 	.code32 | ||||||
|  | 	jmp	EXT(protected_start) | ||||||
|  |  | ||||||
|  | 	.previous | ||||||
							
								
								
									
										14
									
								
								src/cpu/i386/reset16.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/cpu/i386/reset16.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | /* | ||||||
|  |  *      _ROMTOP                 : The top of the rom used where we | ||||||
|  |  *				  need to put the reset vector. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | SECTIONS { | ||||||
|  | 	_ROMTOP = (_ROMBASE >= 0xffff0000)? 0xfffffff0 : 0xffff0; | ||||||
|  | 	. = _ROMTOP; | ||||||
|  | 	.reset . : { | ||||||
|  | 		*(.reset) | ||||||
|  | 		. = 15 ; | ||||||
|  | 		BYTE(0x00); | ||||||
|  | 	}  | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								src/cpu/i386/reset32.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/cpu/i386/reset32.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | 	.section ".reset" | ||||||
|  | 	.code16 | ||||||
|  | .globl	EXT(reset_vector) | ||||||
|  | EXT(reset_vector): | ||||||
|  |  | ||||||
|  | 	. = 0x8; | ||||||
|  | 	.code32 | ||||||
|  | 	jmp	EXT(protected_start) | ||||||
|  |  | ||||||
|  | 	.previous | ||||||
							
								
								
									
										14
									
								
								src/cpu/i386/reset32.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/cpu/i386/reset32.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | /* | ||||||
|  |  *      _ROMTOP                 : The top of the rom used where we | ||||||
|  |  *				  need to put the reset vector. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | SECTIONS { | ||||||
|  | 	_ROMTOP = _ROMBASE + ROM_IMAGE_SIZE - 0x10; | ||||||
|  | 	. = _ROMTOP; | ||||||
|  | 	.reset (.): { | ||||||
|  | 		*(.reset) | ||||||
|  | 		. = 15 ; | ||||||
|  | 		BYTE(0x00); | ||||||
|  | 	}  | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/cpu/k8/cpufixup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/cpu/k8/cpufixup.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | /* Needed so the AMD K8 runs correctly.  */ | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <cpu/p6/msr.h> | ||||||
|  |  | ||||||
|  | #define TOP_MEM    0xc001001A | ||||||
|  | #define TOP_MEM2   0xc001001D | ||||||
|  | #define IORR_FIRST 0xC0010016 | ||||||
|  | #define IORR_LAST  0xC0010019 | ||||||
|  | #define SYSCFG     0xC0010010 | ||||||
|  |  | ||||||
|  | #define MTRRVARDRAMEN (1 << 20) | ||||||
|  |  | ||||||
|  | void k8_cpufixup(struct mem_range *mem) | ||||||
|  | { | ||||||
|  | 	unsigned long lo = 0, hi = 0, i; | ||||||
|  | 	unsigned long ram_megabytes; | ||||||
|  |  | ||||||
|  | 	/* For now no Athlon board has significant holes in it's | ||||||
|  | 	 * address space so just find the last memory region | ||||||
|  | 	 * and compute the end of memory from that. | ||||||
|  | 	 */ | ||||||
|  | 	for(i = 0; mem[i].sizek; i++) | ||||||
|  | 		; | ||||||
|  | 	if (i == 0)  | ||||||
|  | 		return; | ||||||
|  | 	ram_megabytes = (mem[i-1].basek + mem[i-1].sizek) *1024; | ||||||
|  | 		 | ||||||
|  |  | ||||||
|  | 	// 8 MB alignment please | ||||||
|  | 	ram_megabytes += 0x7fffff; | ||||||
|  | 	ram_megabytes &= (~0x7fffff); | ||||||
|  |  | ||||||
|  | 	// set top_mem registers to ram size | ||||||
|  | 	printk_spew("Setting top_mem to 0x%x\n", ram_megabytes); | ||||||
|  | 	rdmsr(TOP_MEM, lo, hi); | ||||||
|  | 	printk_spew("TOPMEM was 0x%02x:0x%02x\n", hi, lo); | ||||||
|  | 	hi = 0; | ||||||
|  | 	lo = ram_megabytes; | ||||||
|  | 	wrmsr(TOP_MEM, lo, hi); | ||||||
|  |  | ||||||
|  | 	// I am setting this even though I won't enable it | ||||||
|  | 	wrmsr(TOP_MEM2, lo, hi); | ||||||
|  |  | ||||||
|  | 	/* zero the IORR's before we enable to prevent | ||||||
|  | 	 * undefined side effects | ||||||
|  | 	 */ | ||||||
|  | 	lo = hi = 0; | ||||||
|  | 	for (i = IORR_FIRST; i <= IORR_LAST; i++) | ||||||
|  | 		wrmsr(i, lo, hi); | ||||||
|  |  | ||||||
|  | 	rdmsr(SYSCFG, lo, hi); | ||||||
|  | 	printk_spew("SYSCFG was 0x%x:0x%x\n", hi, lo); | ||||||
|  | 	lo |= MTRRVARDRAMEN; | ||||||
|  | 	wrmsr(SYSCFG, lo, hi); | ||||||
|  | 	rdmsr(SYSCFG, lo, hi); | ||||||
|  | 	printk_spew("SYSCFG IS NOW 0x%x:0x%x\n", hi, lo); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										99
									
								
								src/cpu/k8/earlymtrr.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/cpu/k8/earlymtrr.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | #include <cpu/k8/mtrr.h> | ||||||
|  |  | ||||||
|  | /* The fixed and variable MTRRs are powered-up with random values, clear them to | ||||||
|  |  * MTRR_TYPE_UNCACHABLE for safty reason  | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | earlymtrr_start: | ||||||
|  | 	xorl	%eax, %eax			# clear %eax and %edx | ||||||
|  | 	xorl	%edx, %edx			# | ||||||
|  | 	movl	$fixed_mtrr_msr, %esi | ||||||
|  |  | ||||||
|  | clear_fixed_var_mtrr: | ||||||
|  | 	lodsl	(%esi), %eax | ||||||
|  | 	testl	%eax, %eax | ||||||
|  | 	jz	clear_fixed_var_mtrr_out | ||||||
|  |  | ||||||
|  | 	movl	%eax, %ecx | ||||||
|  | 	xorl	%eax, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | 	jmp	clear_fixed_var_mtrr | ||||||
|  | clear_fixed_var_mtrr_out: | ||||||
|  |  | ||||||
|  | /* enable memory access for 0 - 8MB using top_mem */ | ||||||
|  | 	movl	$TOP_MEM, %ecx | ||||||
|  | 	xorl	%edx, %edx | ||||||
|  | 	movl	$0x0800000, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | set_var_mtrr: | ||||||
|  | 	/* enable caching for 0 - 128MB using variable mtrr */ | ||||||
|  | 	movl	$0x200, %ecx | ||||||
|  | 	rdmsr | ||||||
|  | 	andl	$0xfffffff0, %edx | ||||||
|  | 	orl	$0x00000000, %edx | ||||||
|  | 	andl	$0x00000f00, %eax | ||||||
|  | 	orl	$0x00000006, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | 	movl	$0x201, %ecx | ||||||
|  | 	rdmsr | ||||||
|  | 	andl	$0xfffffff0, %edx | ||||||
|  | 	orl	$0x0000000f, %edx | ||||||
|  | 	andl	$0x000007ff, %eax | ||||||
|  | 	orl	$0xf0000800, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | #if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE) | ||||||
|  | 	/* enable write protect caching so we can do execute in place | ||||||
|  | 	 * on the flash rom. | ||||||
|  | 	 */ | ||||||
|  | 	movl	$0x202, %ecx | ||||||
|  | 	xorl	%edx, %edx | ||||||
|  | 	movl	$(XIP_ROM_BASE | 0x005), %eax | ||||||
|  | 	wrmsr	 | ||||||
|  |  | ||||||
|  | 	movl	$0x203, %ecx | ||||||
|  | 	movl	$0x0000000f, %edx | ||||||
|  | 	movl	$(~(XIP_ROM_SIZE - 1) | 0x800), %eax | ||||||
|  | 	wrmsr | ||||||
|  | #endif /* XIP_ROM_SIZE && XIP_ROM_BASE */ | ||||||
|  |  | ||||||
|  | enable_mtrr:	 | ||||||
|  | 	/* Set the default memory type and enable fixed and variable MTRRs */ | ||||||
|  | 	movl	$0x2ff, %ecx | ||||||
|  | 	xorl	%edx, %edx | ||||||
|  | 	/* Enable Variable MTRRs */ | ||||||
|  | 	movl	$0x00000800, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | 	/* Enable the MTRRs in SYSCFG */ | ||||||
|  | 	movl	$SYSCFG_MSR, %ecx | ||||||
|  | 	rdmsr | ||||||
|  | 	orl	$(SYSCFG_MSR_MtrrVarDramEn), %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | 	/* enable cache */ | ||||||
|  | 	movl	%cr0, %eax | ||||||
|  | 	andl	$0x9fffffff,%eax | ||||||
|  | 	movl	%eax, %cr0 | ||||||
|  |  | ||||||
|  | 	jmp	earlymtrr_end | ||||||
|  |  | ||||||
|  | fixed_mtrr_msr:	 | ||||||
|  | 	.long	0x250, 0x258, 0x259 | ||||||
|  | 	.long	0x268, 0x269, 0x26A | ||||||
|  | 	.long	0x26B, 0x26C, 0x26D | ||||||
|  | 	.long	0x26E, 0x26F | ||||||
|  | var_mtrr_msr: | ||||||
|  | 	.long	0x200, 0x201, 0x202, 0x203 | ||||||
|  | 	.long	0x204, 0x205, 0x206, 0x207 | ||||||
|  | 	.long	0x208, 0x209, 0x20A, 0x20B | ||||||
|  | 	.long	0x20C, 0x20D, 0x20E, 0x20F | ||||||
|  | var_iorr_msr: | ||||||
|  | 	.long	0xC0010016, 0xC0010017, 0xC0010018, 0xC0010019 | ||||||
|  | mem_top: | ||||||
|  | 	.long	0xC001001A, 0xC001001D | ||||||
|  | 	.long	0x000 /* NULL, end of table */ | ||||||
|  | earlymtrr_end: | ||||||
							
								
								
									
										222
									
								
								src/cpu/p5/cpuid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								src/cpu/p5/cpuid.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | |||||||
|  | #ifndef lint | ||||||
|  | static char rcsid[] = "$Id$"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <cpu/p5/cpuid.h> | ||||||
|  | #ifdef i586 | ||||||
|  | #include <cpu/p6/msr.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int mtrr_check(void) | ||||||
|  | { | ||||||
|  | #ifdef i686 | ||||||
|  | 	/* Only Pentium Pro and later have MTRR */ | ||||||
|  | 	unsigned long low, high; | ||||||
|  |  | ||||||
|  | 	printk_debug("\nMTRR check\n"); | ||||||
|  |  | ||||||
|  | 	rdmsr(0x2ff, low, high); | ||||||
|  | 	low = low >> 10; | ||||||
|  |  | ||||||
|  | 	printk_debug("Fixed MTRRs   : "); | ||||||
|  | 	if (low & 0x01) | ||||||
|  | 		printk_debug("Enabled\n"); | ||||||
|  | 	else | ||||||
|  | 		printk_debug("Disabled\n"); | ||||||
|  |  | ||||||
|  | 	printk_debug("Variable MTRRs: "); | ||||||
|  | 	if (low & 0x02) | ||||||
|  | 		printk_debug("Enabled\n"); | ||||||
|  | 	else | ||||||
|  | 		printk_debug("Disabled\n"); | ||||||
|  |  | ||||||
|  | 	printk_debug("\n"); | ||||||
|  |  | ||||||
|  | 	post_code(0x93); | ||||||
|  | 	return ((int) low); | ||||||
|  | #else /* !i686 */ | ||||||
|  | 	return 0; | ||||||
|  | #endif /* i686 */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void display_cpuid(void) | ||||||
|  | { | ||||||
|  | 	int op, eax, ebx, ecx, edx; | ||||||
|  | 	int max_op; | ||||||
|  |  | ||||||
|  | 	max_op = 0; | ||||||
|  |  | ||||||
|  | 	printk_debug("\n"); | ||||||
|  |  | ||||||
|  | 	for (op = 0; op <= max_op; op++) { | ||||||
|  | 		cpuid(op, &eax, &ebx, &ecx, &edx); | ||||||
|  |  | ||||||
|  | 		if (0 == op) { | ||||||
|  | 			max_op = eax; | ||||||
|  | 			printk_debug("Max cpuid index    : %d\n", eax); | ||||||
|  | 			printk_debug("Vendor ID          : " | ||||||
|  | 			    "%c%c%c%c%c%c%c%c%c%c%c%c\n", | ||||||
|  | 			    ebx, ebx >> 8, ebx >> 16, ebx >> 24, edx, | ||||||
|  | 			    edx >> 8, edx >> 16, edx >> 24, ecx, ecx >> 8, | ||||||
|  | 			    ecx >> 16, ecx >> 24); | ||||||
|  | 		} else if (1 == op) { | ||||||
|  | 			printk_debug("Processor Type     : 0x%02x\n", | ||||||
|  | 			    (eax >> 12) & 0x03); | ||||||
|  | 			printk_debug("Processor Family   : 0x%02x\n", | ||||||
|  | 			    (eax >> 8) & 0x0f); | ||||||
|  | 			printk_debug("Processor Model    : 0x%02x\n", | ||||||
|  | 			    (eax >> 4) & 0x0f); | ||||||
|  | 			printk_debug("Processor Mask     : 0x%02x\n", | ||||||
|  | 			    (ecx >> 0) & 0x0f); | ||||||
|  | 			printk_debug("Processor Stepping : 0x%02x\n", | ||||||
|  | 			    (eax >> 0) & 0x0f); | ||||||
|  | 			printk_debug("Feature flags      : 0x%08x\n", edx); | ||||||
|  | 		} else if (2 == op) { | ||||||
|  | 			int desc[4]; | ||||||
|  | 			int ii; | ||||||
|  | 			int _desc; | ||||||
|  |  | ||||||
|  | 			printk_debug("\n"); | ||||||
|  |  | ||||||
|  | 			printk_debug("Cache/TLB descriptor values: %d " | ||||||
|  | 			    "reads required\n", eax & 0xff); | ||||||
|  |  | ||||||
|  | 			desc[0] = eax; | ||||||
|  | 			desc[1] = ebx; | ||||||
|  | 			desc[2] = ecx; | ||||||
|  | 			desc[3] = edx; | ||||||
|  |  | ||||||
|  | 			for (ii = 1; ii < 16; ii++) { | ||||||
|  | 				if (desc[ii >> 2] & 0x80000000) { | ||||||
|  | 					printk_debug("reserved descriptor\n"); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				_desc = | ||||||
|  | 				    ((desc[ii >> 2]) >> ((ii & 0x3) << 3)) | ||||||
|  | 				    & 0xff; | ||||||
|  | 				printk_debug("Desc 0x%02x : ", _desc); | ||||||
|  |  | ||||||
|  | 				switch (_desc) { | ||||||
|  | 				case 0x00: | ||||||
|  | 					printk_debug("null\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x01: | ||||||
|  | 					printk_debug("Instr TLB: " | ||||||
|  | 					    "4KB pages, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 entries\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x02: | ||||||
|  | 					printk_debug("Instr TLB: " | ||||||
|  | 					    "4MB pages, " | ||||||
|  | 					    "fully assoc, " "2 entries\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x03: | ||||||
|  | 					printk_debug("Data TLB: " | ||||||
|  | 					    "4KB pages, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "64 entries\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x04: | ||||||
|  | 					printk_debug("Data TLB: " | ||||||
|  | 					    "4MB pages, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "8 entries\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x06: | ||||||
|  | 					printk_debug("Inst cache: " | ||||||
|  | 					    "8K bytes, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x08: | ||||||
|  | 					printk_debug("Inst cache: " | ||||||
|  | 					    "16K bytes, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x0a: | ||||||
|  | 					printk_debug("Data cache: " | ||||||
|  | 					    "8K bytes, " | ||||||
|  | 					    "2-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x0c: | ||||||
|  | 					printk_debug("Data cache: " | ||||||
|  | 					    "16K bytes, " | ||||||
|  | 					    "2-way or 4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x40: | ||||||
|  | 					printk_debug("No L2 cache\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x41: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "128K bytes, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x42: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "256K bytes, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x43: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "512K bytes, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x44: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "1M byte, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x45: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "2M byte, " | ||||||
|  | 					    "4-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				case 0x82: | ||||||
|  | 					printk_debug("L2 Unified cache: " | ||||||
|  | 					    "256K bytes, " | ||||||
|  | 					    "8-way set assoc, " | ||||||
|  | 					    "32 byte line size\n"); | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					printk_debug("UNKNOWN\n"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			printk_debug("\n"); | ||||||
|  | 		} else { | ||||||
|  | 			printk_debug("op: 0x%02x  eax:0x%08x  " | ||||||
|  | 			    "ebx:0x%08x  ecx:0x%08x  edx:0x%08x\n", | ||||||
|  | 			    op, eax, ebx, ecx, edx); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk_debug("\n"); | ||||||
|  | 	post_code(0x92); | ||||||
|  | } | ||||||
							
								
								
									
										356
									
								
								src/cpu/p6/mtrr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								src/cpu/p6/mtrr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,356 @@ | |||||||
|  | /* | ||||||
|  |  * intel_mtrr.c: setting MTRR to decent values for cache initialization on P6 | ||||||
|  |  * | ||||||
|  |  * Derived from intel_set_mtrr in intel_subr.c and mtrr.c in linux kernel | ||||||
|  |  * | ||||||
|  |  * Copyright 2000 Silicon Integrated System Corporation | ||||||
|  |  * | ||||||
|  |  *	This program is free software; you can redistribute it and/or modify | ||||||
|  |  *	it under the terms of the GNU General Public License as published by | ||||||
|  |  *	the Free Software Foundation; 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. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * Reference: Intel Architecture Software Developer's Manual, Volume 3: System Programming | ||||||
|  |  * | ||||||
|  |  * $Id$ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef lint | ||||||
|  | static char rcsid[] = "$Id$"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <cpu/p6/msr.h> | ||||||
|  | #include <cpu/p6/mtrr.h> | ||||||
|  | #include <cpu/k7/mtrr.h> | ||||||
|  |  | ||||||
|  | #define arraysize(x)   (sizeof(x)/sizeof((x)[0])) | ||||||
|  |  | ||||||
|  | static unsigned int mtrr_msr[] = { | ||||||
|  | 	MTRRfix64K_00000_MSR, MTRRfix16K_80000_MSR, MTRRfix16K_A0000_MSR, | ||||||
|  | 	MTRRfix4K_C0000_MSR, MTRRfix4K_C8000_MSR, MTRRfix4K_D0000_MSR, MTRRfix4K_D8000_MSR, | ||||||
|  | 	MTRRfix4K_E0000_MSR, MTRRfix4K_E8000_MSR, MTRRfix4K_F0000_MSR, MTRRfix4K_F8000_MSR, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void intel_enable_fixed_mtrr(void) | ||||||
|  | { | ||||||
|  | 	unsigned long low, high; | ||||||
|  |  | ||||||
|  | 	rdmsr(MTRRdefType_MSR, low, high); | ||||||
|  | 	low |= 0xc00; | ||||||
|  | 	wrmsr(MTRRdefType_MSR, low, high); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void intel_enable_var_mtrr(void) | ||||||
|  | { | ||||||
|  | 	unsigned long low, high; | ||||||
|  |  | ||||||
|  | 	rdmsr(MTRRdefType_MSR, low, high); | ||||||
|  | 	low |= 0x800; | ||||||
|  | 	wrmsr(MTRRdefType_MSR, low, high); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void disable_cache(void) | ||||||
|  | { | ||||||
|  | 	unsigned int tmp; | ||||||
|  | 	/* Disable cache */ | ||||||
|  | 	/* Write back the cache and flush TLB */ | ||||||
|  | 	asm volatile ( | ||||||
|  | 		"movl  %%cr0, %0\n\t" | ||||||
|  | 		"orl  $0x40000000, %0\n\t" | ||||||
|  | 		"wbinvd\n\t" | ||||||
|  | 		"movl  %0, %%cr0\n\t" | ||||||
|  | 		"wbinvd\n\t" | ||||||
|  | 		:"=r" (tmp) | ||||||
|  | 		::"memory"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void enable_cache(void) | ||||||
|  | { | ||||||
|  | 	unsigned int tmp; | ||||||
|  | 	// turn cache back on.  | ||||||
|  | 	asm volatile ( | ||||||
|  | 		"movl  %%cr0, %0\n\t" | ||||||
|  | 		"andl  $0x9fffffff, %0\n\t" | ||||||
|  | 		"movl  %0, %%cr0\n\t" | ||||||
|  | 		:"=r" (tmp) | ||||||
|  | 		::"memory"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* setting variable mtrr, comes from linux kernel source */ | ||||||
|  | static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, unsigned char type) | ||||||
|  | { | ||||||
|  | 	unsigned long base_high, base_low; | ||||||
|  | 	unsigned long  mask_high, mask_low; | ||||||
|  |  | ||||||
|  | 	base_high = basek >> 22; | ||||||
|  | 	base_low  = basek << 10; | ||||||
|  |  | ||||||
|  | 	if (sizek < 4*1024*1024) { | ||||||
|  | 		mask_high = 0x0F; | ||||||
|  | 		mask_low = ~((sizek << 10) -1); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		mask_high = 0x0F & (~((sizek >> 22) -1)); | ||||||
|  | 		mask_low = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (reg >= 8) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	// it is recommended that we disable and enable cache when we  | ||||||
|  | 	// do this.  | ||||||
|  | 	disable_cache(); | ||||||
|  | 	if (sizek == 0) { | ||||||
|  | 		/* The invalid bit is kept in the mask, so we simply clear the | ||||||
|  | 		   relevant mask register to disable a range. */ | ||||||
|  | 		wrmsr (MTRRphysMask_MSR (reg), 0, 0); | ||||||
|  | 	} else { | ||||||
|  | 		/* Bit 32-35 of MTRRphysMask should be set to 1 */ | ||||||
|  | 		wrmsr (MTRRphysBase_MSR(reg), base_low | type, base_high); | ||||||
|  | 		wrmsr (MTRRphysMask_MSR(reg), mask_low | 0x800, mask_high); | ||||||
|  | 	} | ||||||
|  | 	enable_cache(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* setting variable mtrr, comes from linux kernel source */ | ||||||
|  | void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type) | ||||||
|  | { | ||||||
|  | 	unsigned int tmp; | ||||||
|  |  | ||||||
|  | 	if (reg >= 8) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	// it is recommended that we disable and enable cache when we  | ||||||
|  | 	// do this.  | ||||||
|  | 	disable_cache(); | ||||||
|  | 	if (size == 0) { | ||||||
|  | 		/* The invalid bit is kept in the mask, so we simply clear the | ||||||
|  | 		   relevant mask register to disable a range. */ | ||||||
|  | 		wrmsr (MTRRphysMask_MSR (reg), 0, 0); | ||||||
|  | 	} else { | ||||||
|  | 		/* Bit 32-35 of MTRRphysMask should be set to 1 */ | ||||||
|  | 		wrmsr (MTRRphysBase_MSR (reg), base | type, 0); | ||||||
|  | 		wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0x0F); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// turn cache back on.  | ||||||
|  | 	enable_cache(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* fms: find most sigificant bit set, stolen from Linux Kernel Source. */ | ||||||
|  | static inline unsigned int fms(unsigned int x) | ||||||
|  | { | ||||||
|  | 	int r; | ||||||
|  |  | ||||||
|  | 	__asm__("bsrl %1,%0\n\t" | ||||||
|  | 	        "jnz 1f\n\t" | ||||||
|  | 	        "movl $0,%0\n" | ||||||
|  | 	        "1:" : "=r" (r) : "g" (x)); | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* fms: find least sigificant bit set */ | ||||||
|  | static inline unsigned int fls(unsigned int x) | ||||||
|  | { | ||||||
|  | 	int r; | ||||||
|  |  | ||||||
|  | 	__asm__("bsfl %1,%0\n\t" | ||||||
|  | 	        "jnz 1f\n\t" | ||||||
|  | 	        "movl $32,%0\n" | ||||||
|  | 	        "1:" : "=r" (r) : "g" (x)); | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* setting up variable and fixed mtrr | ||||||
|  |  * | ||||||
|  |  * From Intel Vol. III Section 9.12.4, the Range Size and Base Alignment has some kind of requirement: | ||||||
|  |  *	1. The range size must be 2^N byte for N >= 12 (i.e 4KB minimum). | ||||||
|  |  *	2. The base address must be 2^N aligned, where the N here is equal to the N in previous | ||||||
|  |  *	   requirement. So a 8K range must be 8K aligned not 4K aligned. | ||||||
|  |  * | ||||||
|  |  * These requirement is meet by "decompositing" the ramsize into Sum(Cn * 2^n, n = [0..N], Cn = [0, 1]). | ||||||
|  |  * For Cm = 1, there is a WB range of 2^m size at base address Sum(Cm * 2^m, m = [N..n]). | ||||||
|  |  * A 124MB (128MB - 4MB SMA) example: | ||||||
|  |  * 	ramsize = 124MB == 64MB (at 0MB) + 32MB (at 64MB) + 16MB (at 96MB ) + 8MB (at 112MB) + 4MB (120MB). | ||||||
|  |  * But this wastes a lot of MTRR registers so we use another more "aggresive" way with Uncacheable Regions. | ||||||
|  |  * | ||||||
|  |  * In the Uncacheable Region scheme, we try to cover the whole ramsize by one WB region as possible, | ||||||
|  |  * If (an only if) this can not be done we will try to decomposite the ramesize, the mathematical formula | ||||||
|  |  * whould be ramsize = Sum(Cn * 2^n, n = [0..N], Cn = [-1, 0, 1]). For Cn = -1, a Uncachable Region is used. | ||||||
|  |  * The same 124MB example: | ||||||
|  |  * 	ramsize = 124MB == 128MB WB (at 0MB) + 4MB UC (at 124MB) | ||||||
|  |  * or a 156MB (128MB + 32MB - 4MB SMA) example: | ||||||
|  |  *	ramsize = 156MB == 128MB WB (at 0MB) + 32MB WB (at 128MB) + 4MB UC (at 156MB) | ||||||
|  |  */ | ||||||
|  | /* 2 MTRRS are reserved for the operating system */ | ||||||
|  | #define BIOS_MTRRS 6 | ||||||
|  | #define OS_MTRRS   2 | ||||||
|  | #define MTRRS        (BIOS_MTRRS + OS_MTRRS) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char type) | ||||||
|  | { | ||||||
|  | 	unsigned int i; | ||||||
|  | 	unsigned int fixed_msr = NUM_FIXED_RANGES >> 3; | ||||||
|  | 	unsigned long low, high; | ||||||
|  | 	low = high = 0; /* Shut up gcc */ | ||||||
|  | 	for(i = first; i < last; i++) { | ||||||
|  | 		/* When I switch to a new msr read it in */ | ||||||
|  | 		if (fixed_msr != i >> 3) { | ||||||
|  | 			/* But first write out the old msr */ | ||||||
|  | 			if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { | ||||||
|  | 				disable_cache(); | ||||||
|  | 				wrmsr(mtrr_msr[fixed_msr], low, high); | ||||||
|  | 				enable_cache(); | ||||||
|  | 			} | ||||||
|  | 			fixed_msr = i>>3; | ||||||
|  | 			rdmsr(mtrr_msr[fixed_msr], low, high); | ||||||
|  | 		} | ||||||
|  | 		if ((i & 7) < 4) { | ||||||
|  | 			low &= ~(0xff << ((i&3)*8)); | ||||||
|  | 			low |= type << ((i&3)*8); | ||||||
|  | 		} else { | ||||||
|  | 			high &= ~(0xff << ((i&3)*8)); | ||||||
|  | 			high |= type << ((i&3)*8); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/* Write out the final msr */ | ||||||
|  | 	if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { | ||||||
|  | 		disable_cache(); | ||||||
|  | 		wrmsr(mtrr_msr[fixed_msr], low, high); | ||||||
|  | 		enable_cache(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned fixed_mtrr_index(unsigned long addrk) | ||||||
|  | { | ||||||
|  | 	unsigned index; | ||||||
|  | 	index = (addrk - 0) >> 6; | ||||||
|  | 	if (index >= 8) { | ||||||
|  | 		index = ((addrk - 8*64) >> 4) + 8; | ||||||
|  | 	} | ||||||
|  | 	if (index >= 24) { | ||||||
|  | 		index = ((addrk - (8*64 + 16*16)) >> 2) + 24; | ||||||
|  | 	} | ||||||
|  | 	if (index > NUM_FIXED_RANGES) { | ||||||
|  | 		index = NUM_FIXED_RANGES; | ||||||
|  | 	} | ||||||
|  | 	return index; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned int range_to_mtrr(unsigned int reg,  | ||||||
|  | 	unsigned long range_startk, unsigned long range_sizek, | ||||||
|  | 	unsigned long next_range_startk) | ||||||
|  | { | ||||||
|  | 	if (!range_sizek || (reg >= BIOS_MTRRS)) { | ||||||
|  | 		return reg; | ||||||
|  | 	} | ||||||
|  | 	while(range_sizek) { | ||||||
|  | 		unsigned long max_align, align; | ||||||
|  | 		unsigned long sizek; | ||||||
|  | 		/* Compute the maximum size I can make a range */ | ||||||
|  | 		max_align = fls(range_startk); | ||||||
|  | 		align = fms(range_sizek);  | ||||||
|  | 		if (align > max_align) { | ||||||
|  | 			align = max_align; | ||||||
|  | 		} | ||||||
|  | 		sizek = 1 << align; | ||||||
|  | 		printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n", | ||||||
|  | 			reg, range_startk >>10, sizek >> 10); | ||||||
|  | 		intel_set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK); | ||||||
|  | 		range_startk += sizek; | ||||||
|  | 		range_sizek -= sizek; | ||||||
|  | 		if (reg >= BIOS_MTRRS) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 	return reg; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void setup_mtrrs(struct mem_range *mem) | ||||||
|  | { | ||||||
|  | 	/* Try this the simple way of incrementally adding together | ||||||
|  | 	 * mtrrs.  If this doesn't work out we can get smart again  | ||||||
|  | 	 * and clear out the mtrrs. | ||||||
|  | 	 */ | ||||||
|  | 	struct mem_range *memp; | ||||||
|  | 	unsigned long range_startk, range_sizek; | ||||||
|  | 	unsigned int reg; | ||||||
|  |  | ||||||
|  | 	printk_debug("\n"); | ||||||
|  | 	/* Initialized the fixed_mtrrs to uncached */ | ||||||
|  | 	printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n",  | ||||||
|  | 		0, NUM_FIXED_RANGES); | ||||||
|  | 	set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHABLE); | ||||||
|  |  | ||||||
|  | 	/* Now see which of the fixed mtrrs cover ram. | ||||||
|  | 	 */ | ||||||
|  | 	for(memp = mem; memp->sizek; memp++) { | ||||||
|  | 		unsigned int start_mtrr; | ||||||
|  | 		unsigned int last_mtrr; | ||||||
|  | 		start_mtrr = fixed_mtrr_index(memp->basek); | ||||||
|  | 		last_mtrr = fixed_mtrr_index(memp->basek + memp->sizek); | ||||||
|  | 		if (start_mtrr >= NUM_FIXED_RANGES) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		printk_debug("Setting fixed MTRRs(%d-%d) type: WB\n", | ||||||
|  | 			start_mtrr, last_mtrr); | ||||||
|  | 		set_fixed_mtrrs(start_mtrr, last_mtrr, MTRR_TYPE_WRBACK); | ||||||
|  | 	} | ||||||
|  | 	printk_debug("DONE fixed MTRRs\n"); | ||||||
|  | 	/* Cache as many memory areas as possible */ | ||||||
|  | 	/* FIXME is there an algorithm for computing the optimal set of mtrrs?  | ||||||
|  | 	 * In some cases it is definitely possible to do better. | ||||||
|  | 	 */ | ||||||
|  | 	range_startk = 0; | ||||||
|  | 	range_sizek = 0; | ||||||
|  | 	reg = 0; | ||||||
|  | 	for (memp = mem; memp->sizek; memp++) { | ||||||
|  | 		/* See if I can merge with the last range  | ||||||
|  | 		 * Either I am below 1M and the fixed mtrrs handle it, or | ||||||
|  | 		 * the ranges touch. | ||||||
|  | 		 */ | ||||||
|  | 		if ((memp->basek <= 1024) || (range_startk + range_sizek == memp->basek)) { | ||||||
|  | 			unsigned long endk = memp->basek + memp->sizek; | ||||||
|  | 			range_sizek = endk - range_startk; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		/* Write the range mtrrs */ | ||||||
|  | 		if (range_sizek != 0) { | ||||||
|  | 			reg = range_to_mtrr(reg, range_startk, range_sizek, memp->basek); | ||||||
|  | 			range_startk = 0; | ||||||
|  | 			range_sizek = 0; | ||||||
|  | 			if (reg >= BIOS_MTRRS) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		/* Allocate an msr */ | ||||||
|  | 		range_startk = memp->basek; | ||||||
|  | 		range_sizek = memp->sizek; | ||||||
|  | 	} | ||||||
|  | 	/* Write the last range */ | ||||||
|  | 	reg = range_to_mtrr(reg, range_startk, range_sizek, 0); | ||||||
|  | 	printk_debug("DONE variable MTRRs\n"); | ||||||
|  | 	printk_debug("Clear out the extra MTRR's\n"); | ||||||
|  | 	/* Clear out the extra MTRR's */ | ||||||
|  | 	while(reg < MTRRS) { | ||||||
|  | 		intel_set_var_mtrr(reg++, 0, 0, 0); | ||||||
|  | 	} | ||||||
|  | 	/* enable fixed MTRR */ | ||||||
|  | 	printk_debug("call intel_enable_fixed_mtrr()\n"); | ||||||
|  | 	intel_enable_fixed_mtrr(); | ||||||
|  | 	printk_debug("call intel_enable_var_mtrr()\n"); | ||||||
|  | 	intel_enable_var_mtrr(); | ||||||
|  | 	printk_debug("Leave %s\n", __FUNCTION__); | ||||||
|  | } | ||||||
							
								
								
									
										423
									
								
								src/devices/device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								src/devices/device.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,423 @@ | |||||||
|  | /* | ||||||
|  |  *      (c) 1999--2000 Martin Mares <mj@suse.cz> | ||||||
|  |  *      (c) 2003 Eric Biederman <ebiederm@xmission.com> | ||||||
|  |  */ | ||||||
|  | /* lots of mods by ron minnich (rminnich@lanl.gov), with  | ||||||
|  |  * the final architecture guidance from Tom Merritt (tjm@codegen.com) | ||||||
|  |  * In particular, we changed from the one-pass original version to  | ||||||
|  |  * Tom's recommended multiple-pass version. I wasn't sure about doing  | ||||||
|  |  * it with multiple passes, until I actually started doing it and saw | ||||||
|  |  * the wisdom of Tom's recommendations ... | ||||||
|  |  * | ||||||
|  |  * Lots of cleanups by Eric Biederman to handle bridges, and to | ||||||
|  |  * handle resource allocation for non-pci devices. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <bitops.h> | ||||||
|  | #include <device.h> | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <pci.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This is the root of the device tree. A PCI tree always has  | ||||||
|  |  * one bus, bus 0. Bus 0 contains devices and bridges.  | ||||||
|  |  */ | ||||||
|  | struct device dev_root; | ||||||
|  | /* Linked list of ALL devices */ | ||||||
|  | struct device *all_devices = 0; | ||||||
|  | /* pointer to the last device */ | ||||||
|  | static struct device **last_dev_p = &all_devices; | ||||||
|  |  | ||||||
|  | #define DEVICE_MEM_HIGH  0xFEC00000UL /* Reserve 20M for the system */ | ||||||
|  | #define DEVICE_IO_START 0x1000 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | unsigned long device_memory_base; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Append a new device to the global device chain. | ||||||
|  |  * The chain is used to find devices once everything is set up. | ||||||
|  |  */ | ||||||
|  | void append_device(struct device *dev) | ||||||
|  | { | ||||||
|  | 	*last_dev_p = dev; | ||||||
|  | 	last_dev_p = &dev->next; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** round a number to an alignment.  | ||||||
|  |  * @param val the starting value | ||||||
|  |  * @param roundup Alignment as a power of two | ||||||
|  |  * @returns rounded up number | ||||||
|  |  */ | ||||||
|  | static unsigned long round(unsigned long val, unsigned long roundup) | ||||||
|  | { | ||||||
|  | 	/* ROUNDUP MUST BE A POWER OF TWO. */ | ||||||
|  | 	unsigned long inverse; | ||||||
|  | 	inverse = ~(roundup - 1); | ||||||
|  | 	val += (roundup - 1); | ||||||
|  | 	val &= inverse; | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static unsigned long round_down(unsigned long val, unsigned long round_down) | ||||||
|  | { | ||||||
|  | 	/* ROUND_DOWN MUST BE A POWER OF TWO. */ | ||||||
|  | 	unsigned long inverse; | ||||||
|  | 	inverse = ~(round_down - 1); | ||||||
|  | 	val &= inverse; | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** Read the resources on all devices of a given bus. | ||||||
|  |  * @param bus bus to read the resources on. | ||||||
|  |  */ | ||||||
|  | static void read_resources(struct device *bus) | ||||||
|  | { | ||||||
|  | 	struct device *curdev; | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  | 	/* Walk through all of the devices and find which resources they need. */ | ||||||
|  | 	for(curdev = bus->children; curdev; curdev = curdev->sibling) { | ||||||
|  | 		if (curdev->resources > 0) { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		curdev->ops->read_resources(curdev); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static struct device *largest_resource(struct device *bus, struct resource **result_res, | ||||||
|  | 	unsigned long type_mask, unsigned long type) | ||||||
|  | { | ||||||
|  | 	struct device *curdev; | ||||||
|  | 	struct device *result_dev = 0; | ||||||
|  | 	struct resource *last = *result_res; | ||||||
|  | 	struct resource *result = 0; | ||||||
|  | 	int seen_last = 0; | ||||||
|  | 	for(curdev = bus->children; curdev; curdev = curdev->sibling) { | ||||||
|  | 		int i; | ||||||
|  | 		for(i = 0; i < curdev->resources; i++) { | ||||||
|  | 			struct resource *resource = &curdev->resource[i]; | ||||||
|  | 			/* If it isn't the right kind of resource ignore it */ | ||||||
|  | 			if ((resource->flags & type_mask) != type) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			/* Be certain to pick the successor to last */ | ||||||
|  | 			if (resource == last) { | ||||||
|  | 				seen_last = 1; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (last && ( | ||||||
|  | 				(last->align < resource->align) || | ||||||
|  | 				((last->align == resource->align) && | ||||||
|  | 					(last->size < resource->size)) || | ||||||
|  | 				((last->align == resource->align) && | ||||||
|  | 					(last->size == resource->size) && | ||||||
|  | 					(!seen_last)))) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (!result ||  | ||||||
|  | 				(result->align < resource->align) || | ||||||
|  | 				((result->align == resource->align) && | ||||||
|  | 					(result->size < resource->size))) { | ||||||
|  | 				result_dev = curdev; | ||||||
|  | 				result = resource; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	*result_res = result; | ||||||
|  | 	return result_dev; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Compute allocate resources is the guts of the resource allocator. | ||||||
|  |  *  | ||||||
|  |  * The problem. | ||||||
|  |  *  - Allocate resources locations for every device. | ||||||
|  |  *  - Don't overlap, and follow the rules of bridges. | ||||||
|  |  *  - Don't overlap with resources in fixed locations. | ||||||
|  |  *  - Be efficient so we don't have ugly strategies. | ||||||
|  |  * | ||||||
|  |  * The strategy. | ||||||
|  |  * - Devices that have fixed addresses are the minority so don't | ||||||
|  |  *   worry about them too much.  Instead only use part of the address | ||||||
|  |  *   space for devices with programmable addresses.  This easily handles | ||||||
|  |  *   everything except bridges. | ||||||
|  |  * | ||||||
|  |  * - PCI devices are required to have thier sizes and their alignments | ||||||
|  |  *   equal.  In this case an optimal solution to the packing problem | ||||||
|  |  *   exists.  Allocate all devices from highest alignment to least | ||||||
|  |  *   alignment or vice versa.  Use this. | ||||||
|  |  * | ||||||
|  |  * - So we can handle more than PCI run two allocation passes on | ||||||
|  |  *   bridges.  The first to see how large the resources are behind | ||||||
|  |  *   the bridge, and what their alignment requirements are.  The | ||||||
|  |  *   second to assign a safe address to the devices behind the | ||||||
|  |  *   bridge.  This allows me to treat a bridge as just a device with  | ||||||
|  |  *   a couple of resources, and not need to special case it in the | ||||||
|  |  *   allocator.  Also this allows handling of other types of bridges. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | void compute_allocate_resource( | ||||||
|  | 	struct device *bus, | ||||||
|  | 	struct resource *bridge, | ||||||
|  | 	unsigned long type_mask, | ||||||
|  | 	unsigned long type) | ||||||
|  | { | ||||||
|  | 	struct device *dev; | ||||||
|  | 	struct resource *resource; | ||||||
|  | 	unsigned long base; | ||||||
|  | 	unsigned long align, min_align; | ||||||
|  | 	min_align = 0; | ||||||
|  | 	base = bridge->base; | ||||||
|  |  | ||||||
|  | 	/* We want different minimum alignments for different kinds of | ||||||
|  | 	 * resources.  These minimums are not device type specific | ||||||
|  | 	 * but resource type specific. | ||||||
|  | 	 */ | ||||||
|  | 	if (bridge->flags & IORESOURCE_IO) { | ||||||
|  | 		min_align = log2(DEVICE_IO_ALIGN); | ||||||
|  | 	} | ||||||
|  | 	if (bridge->flags & IORESOURCE_MEM) { | ||||||
|  | 		min_align = log2(DEVICE_MEM_ALIGN); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printk_spew("DEV: %02x:%02x.%01x compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d\n",  | ||||||
|  | 		bus->bus->secondary, | ||||||
|  | 		PCI_SLOT(bus->devfn), PCI_FUNC(bus->devfn), | ||||||
|  | 		(bridge->flags & IORESOURCE_IO)? "io": | ||||||
|  | 		(bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", | ||||||
|  | 		base, bridge->size, bridge->align, bridge->gran); | ||||||
|  |  | ||||||
|  | 	/* Make certain I have read in all of the resources */ | ||||||
|  | 	read_resources(bus); | ||||||
|  |  | ||||||
|  | 	/* Remember I haven't found anything yet. */ | ||||||
|  | 	resource = 0; | ||||||
|  |  | ||||||
|  | 	/* Walk through all the devices on the current bus and compute the addresses */ | ||||||
|  | 	while((dev = largest_resource(bus, &resource, type_mask, type))) { | ||||||
|  | 		unsigned long size; | ||||||
|  | 		/* Do NOT I repeat do not ignore resources which have zero size. | ||||||
|  | 		 * If they need to be ignored dev->read_resources should not even | ||||||
|  | 		 * return them.   Some resources must be set even when they have | ||||||
|  | 		 * no size.  PCI bridge resources are a good example of this. | ||||||
|  | 		 */ | ||||||
|  |  | ||||||
|  | 		/* Propogate the resource alignment to the bridge register  */ | ||||||
|  | 		if (resource->align > bridge->align) { | ||||||
|  | 			bridge->align = resource->align; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* Make certain we are dealing with a good minimum size */ | ||||||
|  | 		size = resource->size; | ||||||
|  | 		align = resource->align; | ||||||
|  | 		if (align < min_align) { | ||||||
|  | 			align = min_align; | ||||||
|  | 		} | ||||||
|  | 		if (resource->flags & IORESOURCE_IO) { | ||||||
|  | 			/* Don't allow potential aliases over the | ||||||
|  | 			 * legacy pci expansion card addresses. | ||||||
|  | 			 */ | ||||||
|  | 			if ((base > 0x3ff) && ((base & 0x300) != 0)) { | ||||||
|  | 				base = (base & ~0x3ff) + 0x400; | ||||||
|  | 			} | ||||||
|  | 			/* Don't allow allocations in the VGA IO range. | ||||||
|  | 			 * PCI has special cases for that. | ||||||
|  | 			 */ | ||||||
|  | 			else if ((base >= 0x3b0) && (base <= 0x3df)) { | ||||||
|  | 				base = 0x3e0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (((round(base, 1UL << align) + size) -1) <= resource->limit) { | ||||||
|  | 			/* base must be aligned to size */ | ||||||
|  | 			base = round(base, 1UL << align); | ||||||
|  | 			resource->base = base; | ||||||
|  | 			resource->flags |= IORESOURCE_SET; | ||||||
|  | 			base += size; | ||||||
|  | 			 | ||||||
|  | 			printk_spew( | ||||||
|  | 				"DEV: %02x:%02x.%01x %02x *  [0x%08lx - 0x%08lx] %s\n", | ||||||
|  | 				dev->bus->secondary,  | ||||||
|  | 				PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 				resource->index,  | ||||||
|  | 				resource->base, resource->base + resource->size -1, | ||||||
|  | 				(resource->flags & IORESOURCE_IO)? "io": | ||||||
|  | 				(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  | 	/* A pci bridge resource does not need to be a power | ||||||
|  | 	 * of two size, but it does have a minimum granularity. | ||||||
|  | 	 * Round the size up to that minimum granularity so we | ||||||
|  | 	 * know not to place something else at an address postitively | ||||||
|  | 	 * decoded by the bridge. | ||||||
|  | 	 */ | ||||||
|  | 	bridge->size = round(base, 1UL << bridge->gran) - bridge->base; | ||||||
|  |  | ||||||
|  | 	printk_spew("DEV: %02x:%02x.%01x compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d done\n",  | ||||||
|  | 		bus->bus->secondary, | ||||||
|  | 		PCI_SLOT(bus->devfn), PCI_FUNC(bus->devfn), | ||||||
|  | 		(bridge->flags & IORESOURCE_IO)? "io": | ||||||
|  | 		(bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", | ||||||
|  | 		base, bridge->size, bridge->align, bridge->gran); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void allocate_vga_resource(void) | ||||||
|  | { | ||||||
|  | 	/* FIXME handle the VGA pallette snooping */ | ||||||
|  | 	struct device *dev, *vga, *bus; | ||||||
|  | 	bus = vga = 0; | ||||||
|  | 	for(dev = all_devices; dev; dev = dev->next) { | ||||||
|  | 		uint32_t class_revision; | ||||||
|  | 		pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_revision); | ||||||
|  | 		if (((class_revision >> 24) == 0x03) &&  | ||||||
|  | 		    ((class_revision >> 16) != 0x380)) { | ||||||
|  | 			if (!vga) { | ||||||
|  | 				printk_debug("Allocating VGA resource\n"); | ||||||
|  | 				vga = dev; | ||||||
|  | 			} | ||||||
|  | 			if (vga == dev) { | ||||||
|  | 				/* All legacy VGA cards have MEM & I/O space registers */ | ||||||
|  | 				dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO; | ||||||
|  | 			} else { | ||||||
|  | 				/* It isn't safe to enable other VGA cards */ | ||||||
|  | 				dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (vga) { | ||||||
|  | 		bus = vga->bus; | ||||||
|  | 	} | ||||||
|  | 	/* Now walk up the bridges setting the VGA enable */ | ||||||
|  | 	while(bus) { | ||||||
|  | 		uint16_t ctrl; | ||||||
|  | 		pci_read_config_word(bus, PCI_BRIDGE_CONTROL, &ctrl); | ||||||
|  | 		ctrl |= PCI_BRIDGE_CTL_VGA; | ||||||
|  | 		pci_write_config_word(bus, PCI_BRIDGE_CONTROL, ctrl); | ||||||
|  | 		bus = (bus == bus->bus)? 0 : bus->bus; | ||||||
|  | 	}  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** Assign the computed resources to the bridges and devices on the bus. | ||||||
|  |  * Recurse to any bridges found on this bus first. Then do the devices | ||||||
|  |  * on this bus.  | ||||||
|  |  * @param bus Pointer to the structure for this bus | ||||||
|  |  */  | ||||||
|  | void assign_resources(struct device *bus) | ||||||
|  | { | ||||||
|  | 	struct device *curdev; | ||||||
|  |  | ||||||
|  | 	printk_debug("ASSIGN RESOURCES, bus %d\n", bus->secondary); | ||||||
|  |  | ||||||
|  | 	for (curdev = bus->children; curdev; curdev = curdev->sibling) { | ||||||
|  | 		curdev->ops->set_resources(curdev); | ||||||
|  | 	} | ||||||
|  | 	printk_debug("ASSIGNED RESOURCES, bus %d\n", bus->secondary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void enable_resources(struct device *bus) | ||||||
|  | { | ||||||
|  | 	struct device *curdev; | ||||||
|  |  | ||||||
|  | 	/* Walk through the chain of all pci devices and enable them. | ||||||
|  | 	 * This is effectively a breadth first traversal so we should | ||||||
|  | 	 * not have enalbing ordering problems. | ||||||
|  | 	 */ | ||||||
|  | 	for (curdev = all_devices; curdev; curdev = curdev->next) { | ||||||
|  | 		uint16_t command; | ||||||
|  | 		pci_read_config_word(curdev, PCI_COMMAND, &command); | ||||||
|  | 		command |= curdev->command; | ||||||
|  | 		printk_debug("DEV: %02x:%02x.%01x cmd <- %02x\n", | ||||||
|  | 			curdev->bus->secondary, | ||||||
|  | 			PCI_SLOT(curdev->devfn), PCI_FUNC(curdev->devfn), | ||||||
|  | 			command); | ||||||
|  | 		pci_write_config_word(curdev, PCI_COMMAND, command); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Enumerate the resources on the PCI by calling pci_init | ||||||
|  |  */ | ||||||
|  | void dev_enumerate(void) | ||||||
|  | { | ||||||
|  | 	struct device *root; | ||||||
|  | 	printk_info("Enumerating buses..."); | ||||||
|  | 	root = &dev_root; | ||||||
|  | 	if (!root->ops) { | ||||||
|  | 		root->ops = &default_pci_ops_root; | ||||||
|  | 	} | ||||||
|  | 	root->subordinate = root->ops->scan_bus(root, 0); | ||||||
|  | 	printk_info("done\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Starting at the root, compute what resources are needed and allocate them.  | ||||||
|  |  * I/O starts at PCI_IO_START. Since the assignment is hierarchical we | ||||||
|  |  * set the values into the dev_root struct.  | ||||||
|  |  */ | ||||||
|  | void dev_configure(void) | ||||||
|  | { | ||||||
|  | 	struct device *root = &dev_root; | ||||||
|  | 	printk_info("Allocating resources..."); | ||||||
|  | 	printk_debug("\n"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	root->ops->read_resources(root); | ||||||
|  |  | ||||||
|  | 	/* Make certain the io devices are allocated somewhere | ||||||
|  | 	 * safe. | ||||||
|  | 	 */ | ||||||
|  | 	root->resource[0].base = DEVICE_IO_START; | ||||||
|  | 	root->resource[0].flags |= IORESOURCE_SET; | ||||||
|  | 	/* Now reallocate the pci resources memory with the | ||||||
|  | 	 * highest addresses I can manage. | ||||||
|  | 	 */ | ||||||
|  | 	root->resource[1].base =  | ||||||
|  | 		round_down(DEVICE_MEM_HIGH - root->resource[1].size, | ||||||
|  | 			1UL << root->resource[1].align); | ||||||
|  | 	device_memory_base = root->resource[1].base; | ||||||
|  | 	root->resource[1].flags |= IORESOURCE_SET; | ||||||
|  | 	// now just set things into registers ... we hope ... | ||||||
|  | 	root->ops->set_resources(root); | ||||||
|  |  | ||||||
|  | 	allocate_vga_resource(); | ||||||
|  |  | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Starting at the root, walk the tree and enable all devices/bridges.  | ||||||
|  |  * What really happens is computed COMMAND bits get set in register 4 | ||||||
|  |  */ | ||||||
|  | void dev_enable(void) | ||||||
|  | { | ||||||
|  | 	printk_info("Enabling resourcess..."); | ||||||
|  |  | ||||||
|  | 	/* now enable everything. */ | ||||||
|  | 	enable_resources(&dev_root); | ||||||
|  | 	printk_info("done.\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Starting at the root, walk the tree and call a driver to | ||||||
|  |  *  do device specific setup. | ||||||
|  |  */ | ||||||
|  | void dev_initialize(void) | ||||||
|  | { | ||||||
|  | 	struct device *dev; | ||||||
|  |  | ||||||
|  | 	printk_info("Initializing devices...\n"); | ||||||
|  | 	for (dev = all_devices; dev; dev = dev->next) { | ||||||
|  | 		if (dev->ops->init) { | ||||||
|  | 			printk_debug("PCI: %02x:%02x.%01x init\n", | ||||||
|  | 				dev->bus->secondary, | ||||||
|  | 				PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||||||
|  | 			dev->ops->init(dev); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	printk_info("Devices initialized\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										56
									
								
								src/devices/device_util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/devices/device_util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <device.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Given a bus and a devfn number, find the device structure | ||||||
|  |  * @param bus The bus number | ||||||
|  |  * @param devfn a device/function number | ||||||
|  |  * @return pointer to the device structure | ||||||
|  |  */ | ||||||
|  | struct device *dev_find_slot(unsigned int bus, unsigned int devfn) | ||||||
|  | { | ||||||
|  | 	struct device *dev; | ||||||
|  |  | ||||||
|  | 	for (dev = all_devices; dev; dev = dev->next) | ||||||
|  | 		if (dev->bus->secondary == bus && dev->devfn == devfn) | ||||||
|  | 			break; | ||||||
|  | 	return dev; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Find a device of a given vendor and type | ||||||
|  |  * @param vendor Vendor ID (e.g. 0x8086 for Intel) | ||||||
|  |  * @param device Device ID | ||||||
|  |  * @param from Pointer to the device structure, used as a starting point | ||||||
|  |  *        in the linked list of all_devices, which can be 0 to start at the  | ||||||
|  |  *        head of the list (i.e. all_devices) | ||||||
|  |  * @return Pointer to the device struct  | ||||||
|  |  */ | ||||||
|  | struct device *dev_find_device(unsigned int vendor, unsigned int device, struct device *from) | ||||||
|  | { | ||||||
|  | 	if (!from) | ||||||
|  | 		from = all_devices; | ||||||
|  | 	else | ||||||
|  | 		from = from->next; | ||||||
|  | 	while (from && (from->vendor != vendor || from->device != device)) | ||||||
|  | 		from = from->next; | ||||||
|  | 	return from; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Find a device of a given class | ||||||
|  |  * @param class Class of the device | ||||||
|  |  * @param from Pointer to the device structure, used as a starting point | ||||||
|  |  *        in the linked list of all_devices, which can be 0 to start at the  | ||||||
|  |  *        head of the list (i.e. all_devices) | ||||||
|  |  * @return Pointer to the device struct  | ||||||
|  |  */ | ||||||
|  | struct device *dev_find_class(unsigned int class, struct device *from) | ||||||
|  | { | ||||||
|  | 	if (!from) | ||||||
|  | 		from = all_devices; | ||||||
|  | 	else | ||||||
|  | 		from = from->next; | ||||||
|  | 	while (from && from->class != class) | ||||||
|  | 		from = from->next; | ||||||
|  | 	return from; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										670
									
								
								src/devices/pci_device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										670
									
								
								src/devices/pci_device.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,670 @@ | |||||||
|  | /* | ||||||
|  |  *      PCI Bus Services, see include/linux/pci.h for further explanation. | ||||||
|  |  * | ||||||
|  |  *      Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, | ||||||
|  |  *      David Mosberger-Tang | ||||||
|  |  * | ||||||
|  |  *      Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz> | ||||||
|  |  *	 | ||||||
|  |  *	Copyright 2003 -- Eric Biederman <ebiederman@lnxi.com> | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <bitops.h> | ||||||
|  | #include <pci.h> | ||||||
|  | #include <pci_ids.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | static unsigned int pci_scan_bridge(struct device *bus, unsigned int max); | ||||||
|  |  | ||||||
|  | /** Given a device and register, read the size of the BAR for that register.  | ||||||
|  |  * @param dev       Pointer to the device structure | ||||||
|  |  * @param resource  Pointer to the resource structure | ||||||
|  |  * @param index     Address of the pci configuration register | ||||||
|  |  */ | ||||||
|  | static void pci_get_resource(struct device *dev, struct resource *resource, unsigned long index) | ||||||
|  | { | ||||||
|  | 	uint32_t addr, size, base; | ||||||
|  | 	unsigned long type; | ||||||
|  |  | ||||||
|  | 	/* Initialize the resources to nothing */ | ||||||
|  | 	resource->base = 0; | ||||||
|  | 	resource->size = 0; | ||||||
|  | 	resource->align = 0; | ||||||
|  | 	resource->gran = 0; | ||||||
|  | 	resource->limit = 0; | ||||||
|  | 	resource->flags = 0; | ||||||
|  | 	resource->index = index; | ||||||
|  |  | ||||||
|  | 	pci_read_config_dword(dev, index, &addr); | ||||||
|  | 	if (addr == 0xffffffffUL) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	/* FIXME: more consideration for 64-bit PCI devices, | ||||||
|  | 	 * we currently detect their size but otherwise | ||||||
|  | 	 * treat them as 32-bit resources | ||||||
|  | 	 */ | ||||||
|  | 	/* get the size */ | ||||||
|  | 	pci_write_config_dword(dev, index, ~0); | ||||||
|  | 	pci_read_config_dword(dev,  index, &size); | ||||||
|  |  | ||||||
|  | 	/* get the minimum value the bar can be set to */ | ||||||
|  | 	pci_write_config_dword(dev, index, 0); | ||||||
|  | 	pci_read_config_dword(dev, index, &base); | ||||||
|  |  | ||||||
|  | 	/* restore addr */ | ||||||
|  | 	pci_write_config_dword(dev, index, addr); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * some broken hardware has read-only registers that do not  | ||||||
|  | 	 * really size correctly. You can tell this if addr == size | ||||||
|  | 	 * Example: the acer m7229 has BARs 1-4 normally read-only.  | ||||||
|  | 	 * so BAR1 at offset 0x10 reads 0x1f1. If you size that register | ||||||
|  | 	 * by writing 0xffffffff to it, it will read back as 0x1f1 -- a  | ||||||
|  | 	 * violation of the spec.  | ||||||
|  | 	 * We catch this case and ignore it by settting size and type to 0. | ||||||
|  | 	 * This incidentally catches the common case where registers  | ||||||
|  | 	 * read back as 0 for both address and size.  | ||||||
|  | 	 */ | ||||||
|  | 	if ((addr == size) && (addr == base)) { | ||||||
|  | 		if (size != 0) { | ||||||
|  | 			printk_debug( | ||||||
|  | 				"PCI: %02x:%02x.%01x register %02x(%08x), read-only ignoring it\n", | ||||||
|  | 				dev->bus->secondary, | ||||||
|  | 				PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 				index, addr); | ||||||
|  | 		} | ||||||
|  | 		resource->flags = 0; | ||||||
|  | 	} | ||||||
|  | 	/* Now compute the actual size, See PCI Spec 6.2.5.1 ...  */ | ||||||
|  | 	else if (size & PCI_BASE_ADDRESS_SPACE_IO) { | ||||||
|  | 		type = size & (~PCI_BASE_ADDRESS_IO_MASK); | ||||||
|  | 		/* BUG! Top 16 bits can be zero (or not)  | ||||||
|  | 		 * So set them to 0xffff so they go away ... | ||||||
|  | 		 */ | ||||||
|  | 		resource->size = (~((size | 0xffff0000) & PCI_BASE_ADDRESS_IO_MASK)) +1; | ||||||
|  | 		resource->align = log2(resource->size); | ||||||
|  | 		resource->gran = resource->align; | ||||||
|  | 		resource->flags = IORESOURCE_IO; | ||||||
|  | 		resource->limit = 0xffff; | ||||||
|  | 	}  | ||||||
|  | 	else { | ||||||
|  | 		/* A Memory mapped base address */ | ||||||
|  | 		type = size & (~PCI_BASE_ADDRESS_MEM_MASK); | ||||||
|  | 		resource->size = (~(size &PCI_BASE_ADDRESS_MEM_MASK)) +1; | ||||||
|  | 		resource->align = log2(resource->size); | ||||||
|  | 		resource->gran = resource->align; | ||||||
|  | 		resource->flags = IORESOURCE_MEM; | ||||||
|  | 		if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) { | ||||||
|  | 			resource->flags |= IORESOURCE_PREFETCH; | ||||||
|  | 		} | ||||||
|  | 		type &= PCI_BASE_ADDRESS_MEM_TYPE_MASK; | ||||||
|  | 		if (type == PCI_BASE_ADDRESS_MEM_TYPE_32) { | ||||||
|  | 			/* 32bit limit */ | ||||||
|  | 			resource->limit = 0xffffffffUL; | ||||||
|  | 		} | ||||||
|  | 		else if (type == PCI_BASE_ADDRESS_MEM_TYPE_1M) { | ||||||
|  | 			/* 1MB limit */ | ||||||
|  | 			resource->limit = 0x000fffffUL; | ||||||
|  | 		} | ||||||
|  | 		else if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) { | ||||||
|  | 			unsigned long index_hi; | ||||||
|  | 			/* 64bit limit  | ||||||
|  | 			 * For now just treat this as a 32bit limit | ||||||
|  | 			 */ | ||||||
|  | 			index_hi = index + 4; | ||||||
|  | 			resource->limit = 0xffffffffUL; | ||||||
|  | 			resource->flags |= IORESOURCE_PCI64; | ||||||
|  | 			pci_read_config_dword( dev, index_hi, &addr); | ||||||
|  | 			/* get the extended size */ | ||||||
|  | 			pci_write_config_dword(dev, index_hi, 0xffffffffUL); | ||||||
|  | 			pci_read_config_dword( dev, index_hi, &size); | ||||||
|  |  | ||||||
|  | 			/* get the minimum value the bar can be set to */ | ||||||
|  | 			pci_write_config_dword(dev, index_hi, 0); | ||||||
|  | 			pci_read_config_dword(dev,  index_hi, &base); | ||||||
|  |  | ||||||
|  | 			/* restore addr */ | ||||||
|  | 			pci_write_config_dword(dev, index_hi, addr); | ||||||
|  | 			 | ||||||
|  | 			if ((size == 0xffffffff) && (base == 0)) { | ||||||
|  | 				/* Clear the top half of the bar */ | ||||||
|  | 				pci_write_config_dword(dev, index_hi, 0); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				printk_err("PCI: %02x:%02x.%01x Unable to handle 64-bit address\n", | ||||||
|  | 					dev->bus->secondary,  | ||||||
|  | 					PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||||||
|  | 				resource->flags = IORESOURCE_PCI64; | ||||||
|  | 			} | ||||||
|  | 		}  | ||||||
|  | 		else { | ||||||
|  | 			/* Invalid value */ | ||||||
|  | 			resource->flags = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/* dev->size holds the flags... */ | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Read the base address registers for a given device.  | ||||||
|  |  * @param dev Pointer to the dev structure | ||||||
|  |  * @param howmany How many registers to read (6 for device, 2 for bridge) | ||||||
|  |  */ | ||||||
|  | static void pci_read_bases(struct device *dev, unsigned int howmany) | ||||||
|  | { | ||||||
|  | 	unsigned int reg; | ||||||
|  | 	unsigned long index; | ||||||
|  |  | ||||||
|  | 	reg = dev->resources; | ||||||
|  | 	for(index = PCI_BASE_ADDRESS_0;  | ||||||
|  | 	    (reg < MAX_RESOURCES) && (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) { | ||||||
|  | 		struct resource *resource; | ||||||
|  | 		resource = &dev->resource[reg]; | ||||||
|  | 		pci_get_resource(dev, resource, index); | ||||||
|  | 		reg += (resource->flags & (IORESOURCE_IO | IORESOURCE_MEM))? 1:0; | ||||||
|  | 		index += (resource->flags & IORESOURCE_PCI64)?8:4; | ||||||
|  | 	} | ||||||
|  | 	dev->resources = reg; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void pci_bridge_read_bases(struct device *dev) | ||||||
|  | { | ||||||
|  | 	unsigned int reg = dev->resources; | ||||||
|  |  | ||||||
|  | 	/* FIXME handle bridges without some of the optional resources */ | ||||||
|  |  | ||||||
|  | 	/* Initialize the io space constraints on the current bus */ | ||||||
|  | 	dev->resource[reg].base  = 0; | ||||||
|  | 	dev->resource[reg].size  = 0; | ||||||
|  | 	dev->resource[reg].align = log2(PCI_IO_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].gran  = log2(PCI_IO_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].limit = 0xffffUL; | ||||||
|  | 	dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_PCI_BRIDGE; | ||||||
|  | 	dev->resource[reg].index = PCI_IO_BASE; | ||||||
|  | 	compute_allocate_resource(dev, &dev->resource[reg], | ||||||
|  | 		IORESOURCE_IO, IORESOURCE_IO); | ||||||
|  | 	reg++; | ||||||
|  |  | ||||||
|  | 	/* Initiliaze the prefetchable memory constraints on the current bus */ | ||||||
|  | 	dev->resource[reg].base = 0; | ||||||
|  | 	dev->resource[reg].size = 0; | ||||||
|  | 	dev->resource[reg].align = log2(PCI_MEM_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].gran  = log2(PCI_MEM_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].limit = 0xffffffffUL; | ||||||
|  | 	dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_PCI_BRIDGE; | ||||||
|  | 	dev->resource[reg].index = PCI_PREF_MEMORY_BASE; | ||||||
|  | 	compute_allocate_resource(dev, &dev->resource[reg], | ||||||
|  | 		IORESOURCE_MEM | IORESOURCE_PREFETCH,  | ||||||
|  | 		IORESOURCE_MEM | IORESOURCE_PREFETCH); | ||||||
|  | 	reg++; | ||||||
|  |  | ||||||
|  | 	/* Initialize the memory resources on the current bus */ | ||||||
|  | 	dev->resource[reg].base = 0; | ||||||
|  | 	dev->resource[reg].size = 0; | ||||||
|  | 	dev->resource[reg].align = log2(PCI_MEM_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].gran  = log2(PCI_MEM_BRIDGE_ALIGN); | ||||||
|  | 	dev->resource[reg].limit = 0xffffffffUL; | ||||||
|  | 	dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE; | ||||||
|  | 	dev->resource[reg].index = PCI_MEMORY_BASE; | ||||||
|  | 	compute_allocate_resource(dev, &dev->resource[reg], | ||||||
|  | 		IORESOURCE_MEM | IORESOURCE_PREFETCH,  | ||||||
|  | 		IORESOURCE_MEM); | ||||||
|  | 	reg++; | ||||||
|  |  | ||||||
|  | 	dev->resources = reg; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void pci_dev_read_resources(struct device *dev) | ||||||
|  | { | ||||||
|  | 	uint32_t addr; | ||||||
|  | 	dev->resources = 0; | ||||||
|  | 	memset(&dev->resource[0], 0, sizeof(dev->resource)); | ||||||
|  | 	pci_read_bases(dev, 6); | ||||||
|  | 	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr); | ||||||
|  | 	dev->rom_address = (addr == 0xffffffff)? 0 : addr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pci_bus_read_resources(struct device *dev) | ||||||
|  | { | ||||||
|  | 	uint32_t addr; | ||||||
|  | 	dev->resources = 0; | ||||||
|  | 	memset(&dev->resource[0], 0, sizeof(dev->resource)); | ||||||
|  | 	pci_bridge_read_bases(dev); | ||||||
|  | 	pci_read_bases(dev, 2); | ||||||
|  | 	 | ||||||
|  | 	pci_read_config_dword(dev, PCI_ROM_ADDRESS1, &addr); | ||||||
|  | 	dev->rom_address = (addr == 0xffffffff)? 0 : addr; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void pci_set_resource(struct device *dev, struct resource *resource) | ||||||
|  | { | ||||||
|  | 	unsigned long base, limit; | ||||||
|  | 	unsigned long bridge_align = PCI_MEM_BRIDGE_ALIGN; | ||||||
|  | 	unsigned char buf[10]; | ||||||
|  | 	 | ||||||
|  | 	/* Make certain the resource has actually been set */ | ||||||
|  | 	if (!(resource->flags & IORESOURCE_SET)) { | ||||||
|  | #if 1 | ||||||
|  | 		printk_err("ERROR: %02x:%02x.%01x %02x not allocated\n", | ||||||
|  | 			dev->bus->secondary, | ||||||
|  | 			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 			resource->index); | ||||||
|  | #endif | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Only handle PCI memory and IO resources for now */ | ||||||
|  | 	if (!(resource->flags & (IORESOURCE_MEM |IORESOURCE_IO))) | ||||||
|  | 		return; | ||||||
|  | 	 | ||||||
|  | 	if (resource->flags & IORESOURCE_MEM) { | ||||||
|  | 		dev->command |= PCI_COMMAND_MEMORY; | ||||||
|  | 		bridge_align = PCI_MEM_BRIDGE_ALIGN; | ||||||
|  | 	} | ||||||
|  | 	if (resource->flags & IORESOURCE_IO) { | ||||||
|  | 		dev->command |= PCI_COMMAND_IO; | ||||||
|  | 		bridge_align = PCI_IO_BRIDGE_ALIGN; | ||||||
|  | 	} | ||||||
|  | 	if (resource->flags & IORESOURCE_PCI_BRIDGE) { | ||||||
|  | 		dev->command |= PCI_COMMAND_MASTER; | ||||||
|  | 	} | ||||||
|  | 	/* Get the base address */ | ||||||
|  | 	base = resource->base; | ||||||
|  | 	 | ||||||
|  | 	/* Get the limit (rounded up) */ | ||||||
|  | 	limit = base + ((resource->size + bridge_align - 1UL) & ~(bridge_align -1)) -1UL; | ||||||
|  | 	 | ||||||
|  | 	if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) { | ||||||
|  | 		/* | ||||||
|  | 		 * some chipsets allow us to set/clear the IO bit.  | ||||||
|  | 		 * (e.g. VIA 82c686a.) So set it to be safe) | ||||||
|  | 		 */ | ||||||
|  | 		limit = base + resource->size -1; | ||||||
|  | 		if (resource->flags & IORESOURCE_IO) { | ||||||
|  | 			base |= PCI_BASE_ADDRESS_SPACE_IO; | ||||||
|  | 		} | ||||||
|  | 		pci_write_config_dword(dev, resource->index, base & 0xffffffff); | ||||||
|  | 		if (resource->flags & IORESOURCE_PCI64) { | ||||||
|  | 			/* FIXME handle real 64bit base addresses */ | ||||||
|  | 			pci_write_config_dword(dev, resource->index + 4, 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if (resource->index == PCI_IO_BASE) { | ||||||
|  | 		/* set the IO ranges | ||||||
|  | 		 * WARNING: we don't really do 32-bit addressing for IO yet!  | ||||||
|  | 		 */ | ||||||
|  | 		compute_allocate_resource(dev, resource,  | ||||||
|  | 			IORESOURCE_IO, IORESOURCE_IO); | ||||||
|  | 		pci_write_config_byte(dev, PCI_IO_BASE,  base >> 8); | ||||||
|  | 		pci_write_config_byte(dev, PCI_IO_LIMIT, limit >> 8); | ||||||
|  | 	} | ||||||
|  | 	else if (resource->index == PCI_MEMORY_BASE) { | ||||||
|  | 		/* set the memory range | ||||||
|  | 		 */ | ||||||
|  | 		compute_allocate_resource(dev, resource, | ||||||
|  | 			IORESOURCE_MEM | IORESOURCE_PREFETCH,  | ||||||
|  | 			IORESOURCE_MEM); | ||||||
|  | 		pci_write_config_word(dev, PCI_MEMORY_BASE, base >> 16); | ||||||
|  | 		pci_write_config_word(dev, PCI_MEMORY_LIMIT, limit >> 16); | ||||||
|  | 	} | ||||||
|  | 	else if (resource->index == PCI_PREF_MEMORY_BASE) { | ||||||
|  | 		/* set the prefetchable memory range | ||||||
|  | 		 * WARNING: we don't really do 64-bit addressing for prefetchable memory yet! | ||||||
|  | 		 */ | ||||||
|  | 		compute_allocate_resource(dev, resource, | ||||||
|  | 			IORESOURCE_MEM | IORESOURCE_PREFETCH,  | ||||||
|  | 			IORESOURCE_MEM | IORESOURCE_PREFETCH); | ||||||
|  | 		pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,  base >> 16); | ||||||
|  | 		pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, limit >> 16); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		printk_err("ERROR: invalid resource->index %x\n", | ||||||
|  | 			resource->index); | ||||||
|  | 	} | ||||||
|  | 	buf[0] = '\0'; | ||||||
|  | 	if (resource->flags & IORESOURCE_PCI_BRIDGE) { | ||||||
|  | 		sprintf(buf, "bus %d ", dev->secondary); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	printk_debug( | ||||||
|  | 		"PCI: %02x:%02x.%01x %02x <- [0x%08lx - 0x%08lx] %s%s\n", | ||||||
|  | 		dev->bus->secondary,  | ||||||
|  | 		PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 		resource->index,  | ||||||
|  | 		resource->base, limit, | ||||||
|  | 		buf, | ||||||
|  | 		(resource->flags & IORESOURCE_IO)? "io": | ||||||
|  | 		(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pci_dev_set_resources(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct resource *resource, *last; | ||||||
|  | 	uint8_t line; | ||||||
|  |  | ||||||
|  | 	last = &dev->resource[dev->resources]; | ||||||
|  |  | ||||||
|  | 	for(resource = &dev->resource[0]; resource < last; resource++) { | ||||||
|  | 		pci_set_resource(dev, resource); | ||||||
|  | 	} | ||||||
|  | 	if (dev->children) { | ||||||
|  | 		assign_resources(dev); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* set a default latency timer */ | ||||||
|  | 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); | ||||||
|  |  | ||||||
|  | 	/* set a default secondary latency timer */ | ||||||
|  | 	if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) { | ||||||
|  | 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* zero the irq settings */ | ||||||
|  | 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &line); | ||||||
|  | 	if (line) { | ||||||
|  | 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 0); | ||||||
|  | 	} | ||||||
|  | 	/* set the cache line size, so far 64 bytes is good for everyone */ | ||||||
|  | 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 >> 2); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct device_operations default_pci_ops_dev = { | ||||||
|  | 	.read_resources = pci_dev_read_resources, | ||||||
|  | 	.set_resources = pci_dev_set_resources, | ||||||
|  | 	.init = 0, | ||||||
|  | 	.scan_bus = 0, | ||||||
|  | }; | ||||||
|  | struct device_operations default_pci_ops_bus = { | ||||||
|  | 	.read_resources = pci_bus_read_resources, | ||||||
|  | 	.set_resources = pci_dev_set_resources, | ||||||
|  | 	.init = 0, | ||||||
|  | 	.scan_bus = pci_scan_bridge, | ||||||
|  | }; | ||||||
|  | static void set_pci_ops(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct pci_driver *driver; | ||||||
|  | 	if (dev->ops) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	/* Look through the list of setup drivers and find one for | ||||||
|  | 	 * this pci device  | ||||||
|  | 	 */ | ||||||
|  | 	for(driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { | ||||||
|  | 		if ((driver->vendor == dev->vendor) && | ||||||
|  | 			(driver->device = dev->device)) { | ||||||
|  | 			dev->ops = driver->ops; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/* If I don't have a specific driver use the default operations */ | ||||||
|  | 	switch(dev->hdr_type & 0x7f) {	/* header type */ | ||||||
|  | 	case PCI_HEADER_TYPE_NORMAL:	/* standard header */ | ||||||
|  | 		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) | ||||||
|  | 			goto bad; | ||||||
|  | 		dev->ops = &default_pci_ops_dev; | ||||||
|  | 		break; | ||||||
|  | 	case PCI_HEADER_TYPE_BRIDGE: | ||||||
|  | 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||||||
|  | 			goto bad; | ||||||
|  | 		dev->ops = &default_pci_ops_bus; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 	bad: | ||||||
|  | 		printk_err("PCI: %02x:%02x.%01x [%04x/%04x/%06x] has unknown header " | ||||||
|  | 			"type %02x, ignoring.\n", | ||||||
|  | 			dev->bus->secondary,  | ||||||
|  | 			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 			dev->vendor, dev->device,  | ||||||
|  | 			dev->class >> 8, dev->hdr_type); | ||||||
|  | 	} | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Given a bus and a devfn number, find the device structure | ||||||
|  |  * @param bus The bus structure | ||||||
|  |  * @param devfn a device/function number | ||||||
|  |  * @return pointer to the device structure | ||||||
|  |  */ | ||||||
|  | static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) | ||||||
|  | { | ||||||
|  | 	struct device *dev = 0; | ||||||
|  | 	for(; *list; list = &(*list)->sibling) { | ||||||
|  | 		if ((*list)->devfn == devfn) { | ||||||
|  | 			/* Unlink from the list */ | ||||||
|  | 			dev = *list; | ||||||
|  | 			*list = (*list)->sibling; | ||||||
|  | 			dev->sibling = 0; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return dev; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** Scan the pci bus devices and bridges. | ||||||
|  |  * @param pci_bus pointer to the bus structure | ||||||
|  |  * @param max current bus number | ||||||
|  |  * @return The maximum bus number found, after scanning all subordinate busses | ||||||
|  |  */ | ||||||
|  | unsigned int pci_scan_bus(struct device *bus, unsigned int max) | ||||||
|  | { | ||||||
|  | 	unsigned int devfn; | ||||||
|  | 	struct device *dev, **bus_last; | ||||||
|  | 	struct device *old_devices; | ||||||
|  | 	struct device *child; | ||||||
|  |  | ||||||
|  | 	printk_debug("PCI: pci_scan_bus for bus %d\n", bus->secondary); | ||||||
|  |  | ||||||
|  | 	old_devices = bus->children; | ||||||
|  | 	bus->children = 0; | ||||||
|  | 	bus_last = &bus->children; | ||||||
|  |  | ||||||
|  | 	post_code(0x24); | ||||||
|  | 	 | ||||||
|  |  | ||||||
|  | 	/* probe all devices on this bus with some optimization for non-existance and  | ||||||
|  | 	   single funcion devices */ | ||||||
|  | 	for (devfn = 0; devfn < 0xff; devfn++) { | ||||||
|  | 		struct device dummy; | ||||||
|  | 		uint32_t id, class; | ||||||
|  | 		uint8_t cmd, tmp, hdr_type; | ||||||
|  |  | ||||||
|  | 		/* First thing setup the device structure */ | ||||||
|  | 		dev = pci_scan_get_dev(&old_devices, devfn); | ||||||
|  | 	 | ||||||
|  | 		dummy.bus = bus; | ||||||
|  | 		dummy.devfn = devfn; | ||||||
|  | 		pci_read_config_dword(&dummy, PCI_VENDOR_ID, &id); | ||||||
|  | 		/* some broken boards return 0 if a slot is empty: */ | ||||||
|  | 		if (!dev && | ||||||
|  | 			(id == 0xffffffff || id == 0x00000000 ||  | ||||||
|  | 			 id == 0x0000ffff || id == 0xffff0000)) { | ||||||
|  | 			printk_spew("PCI: devfn 0x%x, bad id 0x%x\n", devfn, id); | ||||||
|  | 			if (PCI_FUNC(devfn) == 0x00) { | ||||||
|  | 				/* if this is a function 0 device and it is not present, | ||||||
|  | 				   skip to next device */ | ||||||
|  | 				devfn += 0x07; | ||||||
|  | 			} | ||||||
|  | 			/* multi function device, skip to next function */ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		pci_read_config_byte(&dummy, PCI_HEADER_TYPE, &hdr_type); | ||||||
|  | 		pci_read_config_dword(&dummy, PCI_CLASS_REVISION, &class); | ||||||
|  |  | ||||||
|  | 		if (!dev) { | ||||||
|  | 			if ((dev = malloc(sizeof(*dev))) == 0) { | ||||||
|  | 				printk_err("PCI: out of memory.\n"); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			memset(dev, 0, sizeof(*dev)); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		dev->bus = bus; | ||||||
|  | 		dev->devfn = devfn; | ||||||
|  | 		dev->vendor = id & 0xffff; | ||||||
|  | 		dev->device = (id >> 16) & 0xffff; | ||||||
|  | 		dev->hdr_type = hdr_type; | ||||||
|  | 		/* class code, the upper 3 bytes of PCI_CLASS_REVISION */ | ||||||
|  | 		dev->class = class >> 8; | ||||||
|  |  | ||||||
|  | 		/* non-destructively determine if device can be a master: */ | ||||||
|  | 		pci_read_config_byte(dev, PCI_COMMAND, &cmd); | ||||||
|  | 		pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); | ||||||
|  | 		pci_read_config_byte(dev, PCI_COMMAND, &tmp); | ||||||
|  |  | ||||||
|  | 		dev->master = ((tmp & PCI_COMMAND_MASTER) != 0); | ||||||
|  | 		pci_write_config_byte(dev, PCI_COMMAND, cmd); | ||||||
|  |  | ||||||
|  | 		/* Look at the vendor and device id, or at least the  | ||||||
|  | 		 * header type and class and figure out which set of configuration | ||||||
|  | 		 * methods to use. | ||||||
|  | 		 */ | ||||||
|  | 		set_pci_ops(dev); | ||||||
|  | 		/* Kill the device if we don't have some pci operations for it */ | ||||||
|  | 		if (!dev->ops) { | ||||||
|  | 			free(dev); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		printk_debug("PCI: %02x:%02x.%01x [%04x/%04x]\n",  | ||||||
|  | 			bus->secondary, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),  | ||||||
|  | 			dev->vendor, dev->device); | ||||||
|  |  | ||||||
|  | 		/* Put it into the global device chain. */ | ||||||
|  | 		append_device(dev); | ||||||
|  |  | ||||||
|  | 		/* Now insert it into the list of devices held by the parent bus. */ | ||||||
|  | 		*bus_last = dev; | ||||||
|  | 		bus_last = &dev->sibling; | ||||||
|  |  | ||||||
|  | 		if (PCI_FUNC(devfn) == 0x00 && (hdr_type & 0x80) != 0x80) { | ||||||
|  | 			/* if this is not a multi function device, don't waste time probe | ||||||
|  | 			   another function. Skip to next device. */ | ||||||
|  | 			devfn += 0x07; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	post_code(0x25); | ||||||
|  |  | ||||||
|  | 	for(child = bus->children; child; child = child->sibling) { | ||||||
|  | 		if (!child->ops->scan_bus) | ||||||
|  | 			continue; | ||||||
|  | 		max = child->ops->scan_bus(child, max); | ||||||
|  | 		 | ||||||
|  | 	} | ||||||
|  | 	/* | ||||||
|  | 	 * We've scanned the bus and so we know all about what's on | ||||||
|  | 	 * the other side of any bridges that may be on this bus plus | ||||||
|  | 	 * any devices. | ||||||
|  | 	 * | ||||||
|  | 	 * Return how far we've got finding sub-buses. | ||||||
|  | 	 */ | ||||||
|  | 	printk_debug("PCI: pci_scan_bus returning with max=%02x\n", max); | ||||||
|  | 	post_code(0x55); | ||||||
|  | 	return max; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** Scan the bus, first for bridges and next for devices.  | ||||||
|  |  * @param pci_bus pointer to the bus structure | ||||||
|  |  * @return The maximum bus number found, after scanning all subordinate busses | ||||||
|  |  */ | ||||||
|  | static unsigned int pci_scan_bridge(struct device *bus, unsigned int max) | ||||||
|  | { | ||||||
|  | 	uint32_t buses; | ||||||
|  | 	uint16_t cr; | ||||||
|  | 	/* Set up the primary, secondary and subordinate bus numbers. We have | ||||||
|  | 	 * no idea how many buses are behind this bridge yet, so we set the | ||||||
|  | 	 * subordinate bus number to 0xff for the moment  | ||||||
|  | 	 */ | ||||||
|  | 	bus->secondary = ++max; | ||||||
|  | 	bus->subordinate = 0xff; | ||||||
|  | 	 | ||||||
|  | 	/* Clear all status bits and turn off memory, I/O and master enables. */ | ||||||
|  | 	pci_read_config_word(bus, PCI_COMMAND, &cr); | ||||||
|  | 	pci_write_config_word(bus, PCI_COMMAND, 0x0000); | ||||||
|  | 	pci_write_config_word(bus, PCI_STATUS, 0xffff); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Read the existing primary/secondary/subordinate bus | ||||||
|  | 	 * number configuration. | ||||||
|  | 	 */ | ||||||
|  | 	pci_read_config_dword(bus, PCI_PRIMARY_BUS, &buses); | ||||||
|  |  | ||||||
|  | 	/* Configure the bus numbers for this bridge: the configuration | ||||||
|  | 	 * transactions will not be propagated by the bridge if it is not | ||||||
|  | 	 * correctly configured  | ||||||
|  | 	 */ | ||||||
|  | 	buses &= 0xff000000; | ||||||
|  | 	buses |= (((unsigned int) (bus->bus->secondary) << 0) | | ||||||
|  | 		((unsigned int) (bus->secondary) << 8) | | ||||||
|  | 		((unsigned int) (bus->subordinate) << 16)); | ||||||
|  | 	pci_write_config_dword(bus, PCI_PRIMARY_BUS, buses); | ||||||
|  | 	 | ||||||
|  | 	/* Now we can scan all subordinate buses i.e. the bus hehind the bridge */ | ||||||
|  | 	max = pci_scan_bus(bus, max); | ||||||
|  | 	 | ||||||
|  | 	/* We know the number of buses behind this bridge. Set the subordinate | ||||||
|  | 	 *  bus number to its real value  | ||||||
|  | 	 */ | ||||||
|  | 	bus->subordinate = max; | ||||||
|  | 	buses = (buses & 0xff00ffff) | | ||||||
|  | 		((unsigned int) (bus->subordinate) << 16); | ||||||
|  | 	pci_write_config_dword(bus, PCI_PRIMARY_BUS, buses); | ||||||
|  | 	pci_write_config_word(bus, PCI_COMMAND, cr); | ||||||
|  | 		 | ||||||
|  | 	return max; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void pci_root_read_resources(struct device *bus) | ||||||
|  | { | ||||||
|  | 	int res = 0; | ||||||
|  | 	/* Initialize the system wide io space constraints */ | ||||||
|  | 	bus->resource[res].base  = 0x400; | ||||||
|  | 	bus->resource[res].size  = 0; | ||||||
|  | 	bus->resource[res].align = 0; | ||||||
|  | 	bus->resource[res].gran  = 0; | ||||||
|  | 	bus->resource[res].limit = 0xffffUL; | ||||||
|  | 	bus->resource[res].flags = IORESOURCE_IO; | ||||||
|  | 	bus->resource[res].index = PCI_IO_BASE; | ||||||
|  | 	compute_allocate_resource(bus, &bus->resource[res],  | ||||||
|  | 		IORESOURCE_IO, IORESOURCE_IO); | ||||||
|  | 	res++; | ||||||
|  |  | ||||||
|  | 	/* Initialize the system wide memory resources constraints */ | ||||||
|  | 	bus->resource[res].base  = 0; | ||||||
|  | 	bus->resource[res].size  = 0; | ||||||
|  | 	bus->resource[res].align = 0; | ||||||
|  | 	bus->resource[res].gran  = 0; | ||||||
|  | 	bus->resource[res].limit = 0xffffffffUL; | ||||||
|  | 	bus->resource[res].flags = IORESOURCE_MEM; | ||||||
|  | 	bus->resource[res].index = PCI_MEMORY_BASE; | ||||||
|  | 	compute_allocate_resource(bus, &bus->resource[res],  | ||||||
|  | 		IORESOURCE_MEM, IORESOURCE_MEM); | ||||||
|  | 	res++; | ||||||
|  |  | ||||||
|  | 	bus->resources = res; | ||||||
|  | } | ||||||
|  | static void pci_root_set_resources(struct device *bus) | ||||||
|  | { | ||||||
|  | 	compute_allocate_resource(bus, | ||||||
|  | 		&bus->resource[0], IORESOURCE_IO, IORESOURCE_IO); | ||||||
|  | 	compute_allocate_resource(bus,  | ||||||
|  | 		&bus->resource[1], IORESOURCE_MEM, IORESOURCE_MEM); | ||||||
|  | 	assign_resources(bus); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct device_operations default_pci_ops_root = { | ||||||
|  | 	.read_resources = pci_root_read_resources, | ||||||
|  | 	.set_resources = pci_root_set_resources, | ||||||
|  | 	.init = 0, | ||||||
|  | 	.scan_bus = pci_scan_bus, | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										401
									
								
								src/include/boot/elf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								src/include/boot/elf.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,401 @@ | |||||||
|  | #ifndef ELF_H | ||||||
|  | #define	ELF_H | ||||||
|  |  | ||||||
|  | /* Standard ELF types.  */ | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <arch/boot/boot.h> | ||||||
|  |  | ||||||
|  | /* Type for a 16-bit quantity.  */ | ||||||
|  | typedef uint16_t Elf32_Half; | ||||||
|  | typedef uint16_t Elf64_Half; | ||||||
|  |  | ||||||
|  | /* Types for signed and unsigned 32-bit quantities.  */ | ||||||
|  | typedef uint32_t Elf32_Word; | ||||||
|  | typedef	int32_t  Elf32_Sword; | ||||||
|  | typedef uint32_t Elf64_Word; | ||||||
|  | typedef	int32_t  Elf64_Sword; | ||||||
|  |  | ||||||
|  | /* Types for signed and unsigned 64-bit quantities.  */ | ||||||
|  | typedef uint64_t Elf32_Xword; | ||||||
|  | typedef	int64_t  Elf32_Sxword; | ||||||
|  | typedef uint64_t Elf64_Xword; | ||||||
|  | typedef	int64_t  Elf64_Sxword; | ||||||
|  |  | ||||||
|  | /* Type of addresses.  */ | ||||||
|  | typedef uint32_t Elf32_Addr; | ||||||
|  | typedef uint64_t Elf64_Addr; | ||||||
|  |  | ||||||
|  | /* Type of file offsets.  */ | ||||||
|  | typedef uint32_t Elf32_Off; | ||||||
|  | typedef uint64_t Elf64_Off; | ||||||
|  |  | ||||||
|  | /* Type for section indices, which are 16-bit quantities.  */ | ||||||
|  | typedef uint16_t Elf32_Section; | ||||||
|  | typedef uint16_t Elf64_Section; | ||||||
|  |  | ||||||
|  | /* Type of symbol indices.  */ | ||||||
|  | typedef uint32_t Elf32_Symndx; | ||||||
|  | typedef uint64_t Elf64_Symndx; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* The ELF file header.  This appears at the start of every ELF file.  */ | ||||||
|  |  | ||||||
|  | #define EI_NIDENT (16) | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */ | ||||||
|  |   Elf32_Half	e_type;			/* Object file type */ | ||||||
|  |   Elf32_Half	e_machine;		/* Architecture */ | ||||||
|  |   Elf32_Word	e_version;		/* Object file version */ | ||||||
|  |   Elf32_Addr	e_entry;		/* Entry point virtual address */ | ||||||
|  |   Elf32_Off	e_phoff;		/* Program header table file offset */ | ||||||
|  |   Elf32_Off	e_shoff;		/* Section header table file offset */ | ||||||
|  |   Elf32_Word	e_flags;		/* Processor-specific flags */ | ||||||
|  |   Elf32_Half	e_ehsize;		/* ELF header size in bytes */ | ||||||
|  |   Elf32_Half	e_phentsize;		/* Program header table entry size */ | ||||||
|  |   Elf32_Half	e_phnum;		/* Program header table entry count */ | ||||||
|  |   Elf32_Half	e_shentsize;		/* Section header table entry size */ | ||||||
|  |   Elf32_Half	e_shnum;		/* Section header table entry count */ | ||||||
|  |   Elf32_Half	e_shstrndx;		/* Section header string table index */ | ||||||
|  | } Elf32_Ehdr; | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */ | ||||||
|  |   Elf64_Half	e_type;			/* Object file type */ | ||||||
|  |   Elf64_Half	e_machine;		/* Architecture */ | ||||||
|  |   Elf64_Word	e_version;		/* Object file version */ | ||||||
|  |   Elf64_Addr	e_entry;		/* Entry point virtual address */ | ||||||
|  |   Elf64_Off	e_phoff;		/* Program header table file offset */ | ||||||
|  |   Elf64_Off	e_shoff;		/* Section header table file offset */ | ||||||
|  |   Elf64_Word	e_flags;		/* Processor-specific flags */ | ||||||
|  |   Elf64_Half	e_ehsize;		/* ELF header size in bytes */ | ||||||
|  |   Elf64_Half	e_phentsize;		/* Program header table entry size */ | ||||||
|  |   Elf64_Half	e_phnum;		/* Program header table entry count */ | ||||||
|  |   Elf64_Half	e_shentsize;		/* Section header table entry size */ | ||||||
|  |   Elf64_Half	e_shnum;		/* Section header table entry count */ | ||||||
|  |   Elf64_Half	e_shstrndx;		/* Section header string table index */ | ||||||
|  | } Elf64_Ehdr; | ||||||
|  |  | ||||||
|  | /* Fields in the e_ident array.  The EI_* macros are indices into the | ||||||
|  |    array.  The macros under each EI_* macro are the values the byte | ||||||
|  |    may have.  */ | ||||||
|  |  | ||||||
|  | #define EI_MAG0		0		/* File identification byte 0 index */ | ||||||
|  | #define ELFMAG0		0x7f		/* Magic number byte 0 */ | ||||||
|  |  | ||||||
|  | #define EI_MAG1		1		/* File identification byte 1 index */ | ||||||
|  | #define ELFMAG1		'E'		/* Magic number byte 1 */ | ||||||
|  |  | ||||||
|  | #define EI_MAG2		2		/* File identification byte 2 index */ | ||||||
|  | #define ELFMAG2		'L'		/* Magic number byte 2 */ | ||||||
|  |  | ||||||
|  | #define EI_MAG3		3		/* File identification byte 3 index */ | ||||||
|  | #define ELFMAG3		'F'		/* Magic number byte 3 */ | ||||||
|  |  | ||||||
|  | /* Conglomeration of the identification bytes, for easy testing as a word.  */ | ||||||
|  | #define	ELFMAG		"\177ELF" | ||||||
|  | #define	SELFMAG		4 | ||||||
|  |  | ||||||
|  | #define EI_CLASS	4		/* File class byte index */ | ||||||
|  | #define ELFCLASSNONE	0		/* Invalid class */ | ||||||
|  | #define ELFCLASS32	1		/* 32-bit objects */ | ||||||
|  | #define ELFCLASS64	2		/* 64-bit objects */ | ||||||
|  | #define ELFCLASSNUM	3 | ||||||
|  |  | ||||||
|  | #define EI_DATA		5		/* Data encoding byte index */ | ||||||
|  | #define ELFDATANONE	0		/* Invalid data encoding */ | ||||||
|  | #define ELFDATA2LSB	1		/* 2's complement, little endian */ | ||||||
|  | #define ELFDATA2MSB	2		/* 2's complement, big endian */ | ||||||
|  | #define ELFDATANUM	3 | ||||||
|  |  | ||||||
|  | #define EI_VERSION	6		/* File version byte index */ | ||||||
|  | 					/* Value must be EV_CURRENT */ | ||||||
|  |  | ||||||
|  | #define EI_OSABI	7		/* OS ABI identification */ | ||||||
|  | #define ELFOSABI_SYSV		0	/* UNIX System V ABI */ | ||||||
|  | #define ELFOSABI_HPUX		1	/* HP-UX */ | ||||||
|  | #define ELFOSABI_ARM		97	/* ARM */ | ||||||
|  | #define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */ | ||||||
|  |  | ||||||
|  | #define EI_ABIVERSION	8		/* ABI version */ | ||||||
|  |  | ||||||
|  | #define EI_PAD		9		/* Byte index of padding bytes */ | ||||||
|  |  | ||||||
|  | /* Legal values for e_type (object file type).  */ | ||||||
|  |  | ||||||
|  | #define ET_NONE		0		/* No file type */ | ||||||
|  | #define ET_REL		1		/* Relocatable file */ | ||||||
|  | #define ET_EXEC		2		/* Executable file */ | ||||||
|  | #define ET_DYN		3		/* Shared object file */ | ||||||
|  | #define ET_CORE		4		/* Core file */ | ||||||
|  | #define	ET_NUM		5		/* Number of defined types */ | ||||||
|  | #define ET_LOPROC	0xff00		/* Processor-specific */ | ||||||
|  | #define ET_HIPROC	0xffff		/* Processor-specific */ | ||||||
|  |  | ||||||
|  | /* Legal values for e_machine (architecture).  */ | ||||||
|  |  | ||||||
|  | #define EM_NONE		 0		/* No machine */ | ||||||
|  | #define EM_M32		 1		/* AT&T WE 32100 */ | ||||||
|  | #define EM_SPARC	 2		/* SUN SPARC */ | ||||||
|  | #define EM_386		 3		/* Intel 80386 */ | ||||||
|  | #define EM_68K		 4		/* Motorola m68k family */ | ||||||
|  | #define EM_88K		 5		/* Motorola m88k family */ | ||||||
|  | #define EM_486		 6		/* Intel 80486 */ | ||||||
|  | #define EM_860		 7		/* Intel 80860 */ | ||||||
|  | #define EM_MIPS		 8		/* MIPS R3000 big-endian */ | ||||||
|  | #define EM_S370		 9		/* Amdahl */ | ||||||
|  | #define EM_MIPS_RS4_BE	10		/* MIPS R4000 big-endian */ | ||||||
|  | #define EM_RS6000	11		/* RS6000 */ | ||||||
|  |  | ||||||
|  | #define EM_PARISC	15		/* HPPA */ | ||||||
|  | #define EM_nCUBE	16		/* nCUBE */ | ||||||
|  | #define EM_VPP500	17		/* Fujitsu VPP500 */ | ||||||
|  | #define EM_SPARC32PLUS	18		/* Sun's "v8plus" */ | ||||||
|  | #define EM_960		19		/* Intel 80960 */ | ||||||
|  | #define EM_PPC		20		/* PowerPC */ | ||||||
|  |  | ||||||
|  | #define EM_V800		36		/* NEC V800 series */ | ||||||
|  | #define EM_FR20		37		/* Fujitsu FR20 */ | ||||||
|  | #define EM_RH32		38		/* TRW RH32 */ | ||||||
|  | #define EM_MMA		39		/* Fujitsu MMA */ | ||||||
|  | #define EM_ARM		40		/* ARM */ | ||||||
|  | #define EM_FAKE_ALPHA	41		/* Digital Alpha */ | ||||||
|  | #define EM_SH		42		/* Hitachi SH */ | ||||||
|  | #define EM_SPARCV9	43		/* SPARC v9 64-bit */ | ||||||
|  | #define EM_TRICORE	44		/* Siemens Tricore */ | ||||||
|  | #define EM_ARC		45		/* Argonaut RISC Core */ | ||||||
|  | #define EM_H8_300	46		/* Hitachi H8/300 */ | ||||||
|  | #define EM_H8_300H	47		/* Hitachi H8/300H */ | ||||||
|  | #define EM_H8S		48		/* Hitachi H8S */ | ||||||
|  | #define EM_H8_500	49		/* Hitachi H8/500 */ | ||||||
|  | #define EM_IA_64	50		/* Intel Merced */ | ||||||
|  | #define EM_MIPS_X	51		/* Stanford MIPS-X */ | ||||||
|  | #define EM_COLDFIRE	52		/* Motorola Coldfire */ | ||||||
|  | #define EM_68HC12	53		/* Motorola M68HC12 */ | ||||||
|  | #define EM_NUM		54 | ||||||
|  |  | ||||||
|  | /* If it is necessary to assign new unofficial EM_* values, please | ||||||
|  |    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the | ||||||
|  |    chances of collision with official or non-GNU unofficial values.  */ | ||||||
|  |  | ||||||
|  | #define EM_ALPHA	0x9026 | ||||||
|  |  | ||||||
|  | /* Legal values for e_version (version).  */ | ||||||
|  |  | ||||||
|  | #define EV_NONE		0		/* Invalid ELF version */ | ||||||
|  | #define EV_CURRENT	1		/* Current version */ | ||||||
|  | #define EV_NUM		2 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Program segment header.  */ | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   Elf32_Word	p_type;			/* Segment type */ | ||||||
|  |   Elf32_Off	p_offset;		/* Segment file offset */ | ||||||
|  |   Elf32_Addr	p_vaddr;		/* Segment virtual address */ | ||||||
|  |   Elf32_Addr	p_paddr;		/* Segment physical address */ | ||||||
|  |   Elf32_Word	p_filesz;		/* Segment size in file */ | ||||||
|  |   Elf32_Word	p_memsz;		/* Segment size in memory */ | ||||||
|  |   Elf32_Word	p_flags;		/* Segment flags */ | ||||||
|  |   Elf32_Word	p_align;		/* Segment alignment */ | ||||||
|  | } Elf32_Phdr; | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   Elf64_Word	p_type;			/* Segment type */ | ||||||
|  |   Elf64_Word	p_flags;		/* Segment flags */ | ||||||
|  |   Elf64_Off	p_offset;		/* Segment file offset */ | ||||||
|  |   Elf64_Addr	p_vaddr;		/* Segment virtual address */ | ||||||
|  |   Elf64_Addr	p_paddr;		/* Segment physical address */ | ||||||
|  |   Elf64_Xword	p_filesz;		/* Segment size in file */ | ||||||
|  |   Elf64_Xword	p_memsz;		/* Segment size in memory */ | ||||||
|  |   Elf64_Xword	p_align;		/* Segment alignment */ | ||||||
|  | } Elf64_Phdr; | ||||||
|  |  | ||||||
|  | /* Legal values for p_type (segment type).  */ | ||||||
|  |  | ||||||
|  | #define	PT_NULL		0		/* Program header table entry unused */ | ||||||
|  | #define PT_LOAD		1		/* Loadable program segment */ | ||||||
|  | #define PT_DYNAMIC	2		/* Dynamic linking information */ | ||||||
|  | #define PT_INTERP	3		/* Program interpreter */ | ||||||
|  | #define PT_NOTE		4		/* Auxiliary information */ | ||||||
|  | #define PT_SHLIB	5		/* Reserved */ | ||||||
|  | #define PT_PHDR		6		/* Entry for header table itself */ | ||||||
|  | #define	PT_NUM		7		/* Number of defined types.  */ | ||||||
|  | #define PT_LOOS		0x60000000	/* Start of OS-specific */ | ||||||
|  | #define PT_HIOS		0x6fffffff	/* End of OS-specific */ | ||||||
|  | #define PT_LOPROC	0x70000000	/* Start of processor-specific */ | ||||||
|  | #define PT_HIPROC	0x7fffffff	/* End of processor-specific */ | ||||||
|  |  | ||||||
|  | /* Legal values for p_flags (segment flags).  */ | ||||||
|  |  | ||||||
|  | #define PF_X		(1 << 0)	/* Segment is executable */ | ||||||
|  | #define PF_W		(1 << 1)	/* Segment is writable */ | ||||||
|  | #define PF_R		(1 << 2)	/* Segment is readable */ | ||||||
|  | #define PF_MASKPROC	0xf0000000	/* Processor-specific */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Note section contents.  Each entry in the note section begins with | ||||||
|  |    a header of a fixed form.  */ | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   Elf32_Word n_namesz;			/* Length of the note's name.  */ | ||||||
|  |   Elf32_Word n_descsz;			/* Length of the note's descriptor.  */ | ||||||
|  |   Elf32_Word n_type;			/* Type of the note.  */ | ||||||
|  | } Elf32_Nhdr; | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   Elf64_Word n_namesz;			/* Length of the note's name.  */ | ||||||
|  |   Elf64_Word n_descsz;			/* Length of the note's descriptor.  */ | ||||||
|  |   Elf64_Word n_type;			/* Type of the note.  */ | ||||||
|  | } Elf64_Nhdr; | ||||||
|  |  | ||||||
|  | /* Known names of notes.  */ | ||||||
|  |  | ||||||
|  | /* Solaris entries in the note section have this name.  */ | ||||||
|  | #define ELF_NOTE_SOLARIS	"SUNW Solaris" | ||||||
|  |  | ||||||
|  | /* Note entries for GNU systems have this name.  */ | ||||||
|  | #define ELF_NOTE_GNU		"GNU" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Defined types of notes for Solaris.  */ | ||||||
|  |  | ||||||
|  | /* Value of descriptor (one word) is desired pagesize for the binary.  */ | ||||||
|  | #define ELF_NOTE_PAGESIZE_HINT	1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Defined note types for GNU systems.  */ | ||||||
|  |  | ||||||
|  | /* ABI information.  The descriptor consists of words: | ||||||
|  |    word 0: OS descriptor | ||||||
|  |    word 1: major version of the ABI | ||||||
|  |    word 2: minor version of the ABI | ||||||
|  |    word 3: subminor version of the ABI | ||||||
|  | */ | ||||||
|  | #define ELF_NOTE_ABI		1 | ||||||
|  |  | ||||||
|  | /* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI | ||||||
|  |    note section entry.  */ | ||||||
|  | #define ELF_NOTE_OS_LINUX	0 | ||||||
|  | #define ELF_NOTE_OS_GNU		1 | ||||||
|  | #define ELF_NOTE_OS_SOLARIS2	2 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Motorola 68k specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* Intel 80386 specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* SUN SPARC specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* Values for Elf64_Ehdr.e_flags.  */ | ||||||
|  |  | ||||||
|  | #define EF_SPARCV9_MM		3 | ||||||
|  | #define EF_SPARCV9_TSO		0 | ||||||
|  | #define EF_SPARCV9_PSO		1 | ||||||
|  | #define EF_SPARCV9_RMO		2 | ||||||
|  | #define EF_SPARC_EXT_MASK	0xFFFF00 | ||||||
|  | #define EF_SPARC_SUN_US1	0x000200 | ||||||
|  | #define EF_SPARC_HAL_R1		0x000400 | ||||||
|  |  | ||||||
|  | /* MIPS R3000 specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* Legal values for e_flags field of Elf32_Ehdr.  */ | ||||||
|  |  | ||||||
|  | #define EF_MIPS_NOREORDER   1		/* A .noreorder directive was used */ | ||||||
|  | #define EF_MIPS_PIC	    2		/* Contains PIC code */ | ||||||
|  | #define EF_MIPS_CPIC	    4		/* Uses PIC calling sequence */ | ||||||
|  | #define EF_MIPS_XGOT	    8 | ||||||
|  | #define EF_MIPS_64BIT_WHIRL 16 | ||||||
|  | #define EF_MIPS_ABI2	    32 | ||||||
|  | #define EF_MIPS_ABI_ON32    64 | ||||||
|  | #define EF_MIPS_ARCH	    0xf0000000	/* MIPS architecture level */ | ||||||
|  |  | ||||||
|  | /* Legal values for MIPS architecture level.  */ | ||||||
|  |  | ||||||
|  | #define EF_MIPS_ARCH_1	    0x00000000	/* -mips1 code.  */ | ||||||
|  | #define EF_MIPS_ARCH_2	    0x10000000	/* -mips2 code.  */ | ||||||
|  | #define EF_MIPS_ARCH_3	    0x20000000	/* -mips3 code.  */ | ||||||
|  | #define EF_MIPS_ARCH_4	    0x30000000	/* -mips4 code.  */ | ||||||
|  | #define EF_MIPS_ARCH_5	    0x40000000	/* -mips5 code.  */ | ||||||
|  |  | ||||||
|  | /* Legal values for p_type field of Elf32_Phdr.  */ | ||||||
|  |  | ||||||
|  | #define PT_MIPS_REGINFO	0x70000000	/* Register usage information */ | ||||||
|  | #define PT_MIPS_RTPROC  0x70000001	/* Runtime procedure table. */ | ||||||
|  | #define PT_MIPS_OPTIONS 0x70000002 | ||||||
|  |  | ||||||
|  | /* Special program header types.  */ | ||||||
|  |  | ||||||
|  | #define PF_MIPS_LOCAL	0x10000000 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* HPPA specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* Legal values for e_flags field of Elf32_Ehdr.  */ | ||||||
|  |  | ||||||
|  | #define EF_PARISC_TRAPNL	1	/* Trap nil pointer dereference.  */ | ||||||
|  | #define EF_PARISC_EXT		2	/* Program uses arch. extensions.  */ | ||||||
|  | #define EF_PARISC_ARCH		0xffff0000 /* Architecture version.  */ | ||||||
|  | /* Defined values are: | ||||||
|  | 				0x020b	PA-RISC 1.0 big-endian | ||||||
|  | 				0x0210	PA-RISC 1.1 big-endian | ||||||
|  | 				0x028b	PA-RISC 1.0 little-endian | ||||||
|  | 				0x0290	PA-RISC 1.1 little-endian | ||||||
|  | */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Alpha specific definitions.  */ | ||||||
|  |  | ||||||
|  | /* Legal values for e_flags field of Elf64_Ehdr.  */ | ||||||
|  |  | ||||||
|  | #define EF_ALPHA_32BIT		1	/* All addresses must be < 2GB.  */ | ||||||
|  | #define EF_ALPHA_CANRELAX	2	/* Relocations for relaxing exist.  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* PowerPC specific declarations */ | ||||||
|  |  | ||||||
|  | /* ARM specific declarations */ | ||||||
|  |  | ||||||
|  | /* Processor specific flags for the ELF header e_flags field.  */ | ||||||
|  | #define EF_ARM_RELEXEC     0x01 | ||||||
|  | #define EF_ARM_HASENTRY    0x02 | ||||||
|  | #define EF_ARM_INTERWORK   0x04 | ||||||
|  | #define EF_ARM_APCS_26     0x08 | ||||||
|  | #define EF_ARM_APCS_FLOAT  0x10 | ||||||
|  | #define EF_ARM_PIC         0x20 | ||||||
|  | #define EF_ALIGN8          0x40		/* 8-bit structure alignment is in use */ | ||||||
|  | #define EF_NEW_ABI         0x80 | ||||||
|  | #define EF_OLD_ABI         0x100 | ||||||
|  |  | ||||||
|  | /* ARM-specific program header flags */ | ||||||
|  | #define PF_ARM_SB          0x10000000   /* Segment contains the location | ||||||
|  | 					   addressed by the static base */ | ||||||
|  |  | ||||||
|  | #if ELF_CLASS == ELFCLASS32 | ||||||
|  | typedef Elf32_Ehdr Elf_ehdr; | ||||||
|  | typedef Elf32_Phdr Elf_phdr; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ELF_CLASS == ELFCLASS64 | ||||||
|  | typedef Elf64_Ehdr Elf_ehdr; | ||||||
|  | typedef Elf64_Phdr Elf_phdr; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | extern int elf_check_arch(Elf_ehdr *ehdr); | ||||||
|  | extern void jmp_to_elf_entry(void *entry, unsigned long buffer); | ||||||
|  | struct lb_memory; | ||||||
|  | extern int elfboot(struct lb_memory *mem); | ||||||
|  |  | ||||||
|  | #define FIRMWARE_TYPE "LinuxBIOS" | ||||||
|  | #define BOOTLOADER "elfboot" | ||||||
|  | #define BOOTLOADER_VERSION "1.3" | ||||||
|  |  | ||||||
|  | #endif	/* elf.h */ | ||||||
							
								
								
									
										89
									
								
								src/include/boot/elf_boot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/include/boot/elf_boot.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | #ifndef ELF_BOOT_H  | ||||||
|  | #define ELF_BOOT_H  | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /* This defines the structure of a table of parameters useful for ELF | ||||||
|  |  * bootable images.  These parameters are all passed and generated | ||||||
|  |  * by the bootloader to the booted image.  For simplicity and | ||||||
|  |  * consistency the Elf Note format is reused. | ||||||
|  |  * | ||||||
|  |  * All of the information must be Position Independent Data. | ||||||
|  |  * That is it must be safe to relocate the whole ELF boot parameter | ||||||
|  |  * block without changing the meaning or correctnes of the data. | ||||||
|  |  * Additionally it must be safe to permute the order of the ELF notes | ||||||
|  |  * to any possible permutation without changing the meaning or correctness | ||||||
|  |  * of the data. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define ELF_HEAD_SIZE		(8*1024) | ||||||
|  | #define ELF_BOOT_MAGIC		0x0E1FB007 | ||||||
|  |  | ||||||
|  | typedef uint16_t Elf_Half; | ||||||
|  | typedef uint32_t Elf_Word; | ||||||
|  | typedef uint64_t Elf_Xword; | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  | 	Elf_Word b_signature; /* "0x0E1FB007" */ | ||||||
|  | 	Elf_Word b_size; | ||||||
|  | 	Elf_Half b_checksum; | ||||||
|  | 	Elf_Half b_records; | ||||||
|  | } Elf_Bhdr; | ||||||
|  |  | ||||||
|  | typedef struct  | ||||||
|  | { | ||||||
|  | 	Elf_Word n_namesz;		/* Length of the note's name.  */ | ||||||
|  | 	Elf_Word n_descsz;		/* Length of the note's descriptor.  */ | ||||||
|  | 	Elf_Word n_type;		/* Type of the note.  */ | ||||||
|  | } Elf_Nhdr; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* For standard notes n_namesz must be zero */ | ||||||
|  | /* All of the following standard note types provide a single null | ||||||
|  |  * terminated string in the descriptor. | ||||||
|  |  */ | ||||||
|  | #define EBN_FIRMWARE_TYPE	0x00000001 | ||||||
|  | /* On platforms that support multiple classes of firmware this field | ||||||
|  |  * specifies the class of firmware you are loaded under. | ||||||
|  |  */ | ||||||
|  | #define EBN_BOOTLOADER_NAME	0x00000002 | ||||||
|  | /* This specifies just the name of the bootloader for easy comparison */ | ||||||
|  | #define EBN_BOOTLOADER_VERSION	0x00000003 | ||||||
|  | /* This specifies the version of the bootlader */ | ||||||
|  | #define EBN_COMMAND_LINE	0x00000004 | ||||||
|  | /* This specifies a command line that can be set by user interaction, | ||||||
|  |  * and is provided as a free form string to the loaded image. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Standardized Elf image notes for booting... The name for all of these is ELFBoot */ | ||||||
|  |  | ||||||
|  | #define ELF_NOTE_BOOT		"ELFBoot" | ||||||
|  |  | ||||||
|  | #define EIN_PROGRAM_NAME	0x00000001 | ||||||
|  | /* The program in this ELF file */ | ||||||
|  | #define EIN_PROGRAM_VERSION	0x00000002 | ||||||
|  | /* The version of the program in this ELF file */ | ||||||
|  | #define EIN_PROGRAM_CHECKSUM	0x00000003 | ||||||
|  | /* ip style checksum of the memory image. */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Linux image notes for booting... The name for all of these is Linux */ | ||||||
|  |  | ||||||
|  | #define LINUX_NOTE_BOOT		"Linux" | ||||||
|  |  | ||||||
|  | #define LIN_COMMAND_LINE	0x00000001 | ||||||
|  | /* The command line to pass to the loaded kernel. */ | ||||||
|  | #define LIN_ROOT_DEV		0x00000002 | ||||||
|  | /* The root dev to pass to the loaded kernel. */ | ||||||
|  | #define LIN_RAMDISK_FLAGS	0x00000003 | ||||||
|  | /* Various old ramdisk flags */ | ||||||
|  | #define LIN_INITRD_START	0x00000004 | ||||||
|  | /* Start of the ramdisk in bytes */ | ||||||
|  | #define LIN_INITRD_SIZE		0x00000005 | ||||||
|  | /* Size of the ramdisk in bytes */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* ELF_BOOT_H */ | ||||||
							
								
								
									
										183
									
								
								src/include/boot/linuxbios_tables.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/include/boot/linuxbios_tables.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | |||||||
|  | #ifndef LINUXBIOS_TABLES_H | ||||||
|  | #define LINUXBIOS_TABLES_H | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /* The linuxbios table information is for conveying information | ||||||
|  |  * from the firmware to the loaded OS image.  Primarily this | ||||||
|  |  * is expected to be information that cannot be discovered by | ||||||
|  |  * other means, such as quering the hardware directly. | ||||||
|  |  * | ||||||
|  |  * All of the information should be Position Independent Data.   | ||||||
|  |  * That is it should be safe to relocated any of the information | ||||||
|  |  * without it's meaning/correctnes changing.   For table that | ||||||
|  |  * can reasonably be used on multiple architectures the data | ||||||
|  |  * size should be fixed.  This should ease the transition between | ||||||
|  |  * 32 bit and 64 bit architectures etc. | ||||||
|  |  * | ||||||
|  |  * The completeness test for the information in this table is: | ||||||
|  |  * - Can all of the hardware be detected? | ||||||
|  |  * - Are the per motherboard constants available? | ||||||
|  |  * - Is there enough to allow a kernel to run that was written before | ||||||
|  |  *   a particular motherboard is constructed? (Assuming the kernel | ||||||
|  |  *   has drivers for all of the hardware but it does not have | ||||||
|  |  *   assumptions on how the hardware is connected together). | ||||||
|  |  * | ||||||
|  |  * With this test it should be straight forward to determine if a | ||||||
|  |  * table entry is required or not.  This should remove much of the | ||||||
|  |  * long term compatibility burden as table entries which are | ||||||
|  |  * irrelevant or have been replaced by better alternatives may be | ||||||
|  |  * dropped.  Of course it is polite and expidite to include extra | ||||||
|  |  * table entries and be backwards compatible, but it is not required. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct lb_header | ||||||
|  | { | ||||||
|  | 	uint8_t  signature[4]; /* LBIO */ | ||||||
|  | 	uint32_t header_bytes; | ||||||
|  | 	uint32_t header_checksum; | ||||||
|  | 	uint32_t table_bytes; | ||||||
|  | 	uint32_t table_checksum; | ||||||
|  | 	uint32_t table_entries; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Every entry in the boot enviroment list will correspond to a boot | ||||||
|  |  * info record.  Encoding both type and size.  The type is obviously | ||||||
|  |  * so you can tell what it is.  The size allows you to skip that | ||||||
|  |  * boot enviroment record if you don't know what it easy.  This allows | ||||||
|  |  * forward compatibility with records not yet defined. | ||||||
|  |  */ | ||||||
|  | struct lb_record { | ||||||
|  | 	uint32_t tag;		/* tag ID */ | ||||||
|  | 	uint32_t size;		/* size of record (in bytes) */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define LB_TAG_UNUSED	0x0000 | ||||||
|  |  | ||||||
|  | #define LB_TAG_MEMORY	0x0001 | ||||||
|  |  | ||||||
|  | struct lb_memory_range { | ||||||
|  | 	uint64_t start; | ||||||
|  | 	uint64_t size; | ||||||
|  | 	uint32_t type; | ||||||
|  | #define LB_MEM_RAM       1	/* Memory anyone can use */ | ||||||
|  | #define LB_MEM_RESERVED  2	/* Don't use this memory region */ | ||||||
|  | #define LB_MEM_TABLE     16	/* Ram configuration tables are kept in */ | ||||||
|  | 	 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct lb_memory { | ||||||
|  | 	uint32_t tag; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	struct lb_memory_range map[0]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define LB_TAG_HWRPB	0x0002 | ||||||
|  | struct lb_hwrpb { | ||||||
|  | 	uint32_t tag; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint64_t hwrpb; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define LB_TAG_MAINBOARD	0x0003 | ||||||
|  | struct lb_mainboard { | ||||||
|  | 	uint32_t tag; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint8_t  vendor_idx; | ||||||
|  | 	uint8_t  part_number_idx; | ||||||
|  | 	uint8_t  strings[0]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define LB_TAG_VERSION		0x0004 | ||||||
|  | #define LB_TAG_EXTRA_VERSION	0x0005 | ||||||
|  | #define LB_TAG_BUILD		0x0006 | ||||||
|  | #define LB_TAG_COMPILE_TIME	0x0007 | ||||||
|  | #define LB_TAG_COMPILE_BY	0x0008 | ||||||
|  | #define LB_TAG_COMPILE_HOST	0x0009 | ||||||
|  | #define LB_TAG_COMPILE_DOMAIN	0x000a | ||||||
|  | #define LB_TAG_COMPILER		0x000b | ||||||
|  | #define LB_TAG_LINKER		0x000c | ||||||
|  | #define LB_TAG_ASSEMBLER	0x000d | ||||||
|  | struct lb_string { | ||||||
|  | 	uint32_t tag; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint8_t  string[0]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* The following structures are for the cmos definitions table */ | ||||||
|  | #define LB_TAG_CMOS_OPTION_TABLE 200 | ||||||
|  | /* cmos header record */ | ||||||
|  | struct cmos_option_table { | ||||||
|  | 	uint32_t tag;               /* CMOS definitions table type */ | ||||||
|  | 	uint32_t size;               /* size of the entire table */ | ||||||
|  | 	uint32_t header_length;      /* length of header */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* cmos entry record | ||||||
|  |         This record is variable length.  The name field may be | ||||||
|  |         shorter than CMOS_MAX_NAME_LENGTH. The entry may start | ||||||
|  |         anywhere in the byte, but can not span bytes unless it | ||||||
|  |         starts at the beginning of the byte and the length is | ||||||
|  |         fills complete bytes. | ||||||
|  | */ | ||||||
|  | #define LB_TAG_OPTION 201 | ||||||
|  | struct cmos_entries { | ||||||
|  | 	uint32_t tag;                /* entry type */ | ||||||
|  | 	uint32_t size;               /* length of this record */ | ||||||
|  | 	uint32_t bit;                /* starting bit from start of image */ | ||||||
|  | 	uint32_t length;             /* length of field in bits */ | ||||||
|  | 	uint32_t config;             /* e=enumeration, h=hex, r=reserved */ | ||||||
|  | 	uint32_t config_id;          /* a number linking to an enumeration record */ | ||||||
|  | #define CMOS_MAX_NAME_LENGTH 32 | ||||||
|  | 	uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name of entry in ascii,  | ||||||
|  | 					       variable length int aligned */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* cmos enumerations record | ||||||
|  |         This record is variable length.  The text field may be | ||||||
|  |         shorter than CMOS_MAX_TEXT_LENGTH. | ||||||
|  | */ | ||||||
|  | #define LB_TAG_OPTION_ENUM 202 | ||||||
|  | struct cmos_enums { | ||||||
|  | 	uint32_t tag;		     /* enumeration type */ | ||||||
|  | 	uint32_t size; 		     /* length of this record */ | ||||||
|  | 	uint32_t config_id;          /* a number identifying the config id */ | ||||||
|  | 	uint32_t value;              /* the value associated with the text */ | ||||||
|  | #define CMOS_MAX_TEXT_LENGTH 32 | ||||||
|  | 	uint8_t text[CMOS_MAX_TEXT_LENGTH]; /* enum description in ascii,  | ||||||
|  | 						variable length int aligned */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* cmos defaults record | ||||||
|  |         This record contains default settings for the cmos ram. | ||||||
|  | */ | ||||||
|  | #define LB_TAG_OPTION_DEFAULTS 203 | ||||||
|  | struct cmos_defaults { | ||||||
|  | 	uint32_t tag;                /* default type */ | ||||||
|  | 	uint32_t size;               /* length of this record */ | ||||||
|  | 	uint32_t name_length;        /* length of the following name field */ | ||||||
|  | 	uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name identifying the default */ | ||||||
|  | #define CMOS_IMAGE_BUFFER_SIZE 128 | ||||||
|  | 	uint8_t default_set[CMOS_IMAGE_BUFFER_SIZE]; /* default settings */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define LB_TAG_OPTION_CHECKSUM 204 | ||||||
|  | struct	cmos_checksum { | ||||||
|  | 	uint32_t tag; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	/* In practice everything is byte aligned, but things are measured | ||||||
|  | 	 * in bits to be consistent. | ||||||
|  | 	 */ | ||||||
|  | 	uint32_t range_start;	/* First bit that is checksummed (byte aligned) */ | ||||||
|  | 	uint32_t range_end;	/* Last bit that is checksummed (byte aligned) */ | ||||||
|  | 	uint32_t location;	/* First bit of the checksum (byte aligned) */ | ||||||
|  | 	uint32_t type;		/* Checksum algorithm that is used */ | ||||||
|  | #define CHECKSUM_NONE	0 | ||||||
|  | #define CHECKSUM_PCBIOS	1 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* LINUXBIOS_TABLES_H */ | ||||||
							
								
								
									
										9
									
								
								src/include/boot/tables.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/include/boot/tables.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | #ifndef BOOT_TABLES_H | ||||||
|  | #define BOOT_TABLES_H | ||||||
|  |  | ||||||
|  | #include <mem.h> | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  |  | ||||||
|  | struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_map); | ||||||
|  |  | ||||||
|  | #endif /* BOOT_TABLES_H */ | ||||||
							
								
								
									
										76
									
								
								src/include/console/console.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/include/console/console.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | #ifndef CONSOLE_CONSOLE_H_ | ||||||
|  | #define CONSOLE_CONSOLE_H_ | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <console/loglevel.h> | ||||||
|  |  | ||||||
|  | void console_init(void); | ||||||
|  | void console_tx_byte(unsigned char byte); | ||||||
|  | void console_tx_flush(void); | ||||||
|  | void post_code(uint8_t value); | ||||||
|  | void die(char *msg); | ||||||
|  |  | ||||||
|  | struct console_driver { | ||||||
|  | 	void (*init)(void); | ||||||
|  | 	void (*tx_byte)(unsigned char byte); | ||||||
|  | 	void (*tx_flush)(void); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define __console	__attribute__((unused, __section__ (".rodata.console_drivers"))) | ||||||
|  |  | ||||||
|  | /* Defined by the linker... */ | ||||||
|  | extern struct console_driver console_drivers[]; | ||||||
|  | extern struct console_driver econsole_drivers[]; | ||||||
|  |  | ||||||
|  | extern int console_loglevel; | ||||||
|  | int do_printk(int msg_level, const char *fmt, ...); | ||||||
|  |  | ||||||
|  | #define printk_emerg(fmt, arg...)   do_printk(BIOS_EMERG   ,fmt, ##arg) | ||||||
|  | #define printk_alert(fmt, arg...)   do_printk(BIOS_ALERT   ,fmt, ##arg) | ||||||
|  | #define printk_crit(fmt, arg...)    do_printk(BIOS_CRIT    ,fmt, ##arg) | ||||||
|  | #define printk_err(fmt, arg...)     do_printk(BIOS_ERR     ,fmt, ##arg) | ||||||
|  | #define printk_warning(fmt, arg...) do_printk(BIOS_WARNING ,fmt, ##arg) | ||||||
|  | #define printk_notice(fmt, arg...)  do_printk(BIOS_NOTICE  ,fmt, ##arg) | ||||||
|  | #define printk_info(fmt, arg...)    do_printk(BIOS_INFO    ,fmt, ##arg) | ||||||
|  | #define printk_debug(fmt, arg...)   do_printk(BIOS_DEBUG   ,fmt, ##arg) | ||||||
|  | #define printk_spew(fmt, arg...)    do_printk(BIOS_SPEW    ,fmt, ##arg) | ||||||
|  |  | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_EMERG | ||||||
|  | #undef  printk_emerg | ||||||
|  | #define printk_emerg(fmt, arg...)   do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_ALERT | ||||||
|  | #undef  printk_alert | ||||||
|  | #define printk_alart(fmt, arg...)   do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_CRIT | ||||||
|  | #undef  printk_crit | ||||||
|  | #define printk_crit(fmt, arg...)    do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_ERR | ||||||
|  | #undef  printk_err | ||||||
|  | #define printk_err(fmt, arg...)     do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_WARNING | ||||||
|  | #undef  printk_warning | ||||||
|  | #define printk_warning(fmt, arg...) do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_NOTICE | ||||||
|  | #undef  printk_notice | ||||||
|  | #define printk_notice(fmt, arg...)  do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_INFO | ||||||
|  | #undef  printk_info | ||||||
|  | #define printk_info(fmt, arg...)    do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_DEBUG | ||||||
|  | #undef  printk_debug | ||||||
|  | #define printk_debug(fmt, arg...)   do {} while(0) | ||||||
|  | #endif | ||||||
|  | #if MAXIMUM_CONSOLE_LOGLEVEL <= BIOS_SPEW | ||||||
|  | #undef  printk_spew | ||||||
|  | #define printk_spew(fmt, arg...)    do {} while(0) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* CONSOLE_CONSOLE_H_ */ | ||||||
							
								
								
									
										30
									
								
								src/include/console/loglevel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/include/console/loglevel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | #ifndef LOGLEVEL_H | ||||||
|  | #define LOGLEVEL_H | ||||||
|  |  | ||||||
|  | /* Safe for inclusion in assembly */ | ||||||
|  |  | ||||||
|  | #ifndef MAXIMUM_CONSOLE_LOGLEVEL | ||||||
|  | #define MAXIMUM_CONSOLE_LOGLEVEL 8 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef DEFAULT_CONSOLE_LOGLEVEL | ||||||
|  | #define DEFAULT_CONSOLE_LOGLEVEL 8 /* anything MORE serious than BIOS_SPEW */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if (DEFAULT_CONSOLE_LOGLEVEL <= MAXIMUM_CONSOLE_LOGLEVEL) | ||||||
|  | #define ASM_CONSOLE_LOGLEVEL DEFAULT_CONSOLE_LOGLEVEL | ||||||
|  | #else | ||||||
|  | #define ASM_CONSOLE_LOGLEVEL MAXIMUM_CONSOLE_LOGLEVEL | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define BIOS_EMERG      0   /* system is unusable                   */ | ||||||
|  | #define BIOS_ALERT      1   /* action must be taken immediately     */ | ||||||
|  | #define BIOS_CRIT       2   /* critical conditions                  */ | ||||||
|  | #define BIOS_ERR        3   /* error conditions                     */ | ||||||
|  | #define BIOS_WARNING    4   /* warning conditions                   */ | ||||||
|  | #define BIOS_NOTICE     5   /* normal but significant condition     */ | ||||||
|  | #define BIOS_INFO       6   /* informational                        */ | ||||||
|  | #define BIOS_DEBUG      7   /* debug-level messages                 */ | ||||||
|  | #define BIOS_SPEW       8   /* Way too many details                 */ | ||||||
|  |  | ||||||
|  | #endif /* LOGLEVEL_H */ | ||||||
							
								
								
									
										11
									
								
								src/include/cpu/cpu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/include/cpu/cpu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | #ifndef CPU_CPU_H | ||||||
|  | #define CPU_CPU_H | ||||||
|  |  | ||||||
|  | #include <mem.h> | ||||||
|  |  | ||||||
|  | unsigned long cpu_initialize(struct mem_range *mem); | ||||||
|  | #define CPU_ENABLED		1	/* Processor is available */ | ||||||
|  | #define CPU_BOOTPROCESSOR	2	/* Processor is the BP */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* CPU_CPU_H */ | ||||||
							
								
								
									
										24
									
								
								src/include/cpu/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/include/cpu/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #ifndef CPU_CPUFIXUP_H | ||||||
|  | #define CPU_CPUFIXUP_H | ||||||
|  |  | ||||||
|  | struct mem_range; | ||||||
|  |  | ||||||
|  | #include <cpu/k8/cpufixup.h> | ||||||
|  | #include <cpu/k7/cpufixup.h> | ||||||
|  | #include <cpu/p6/cpufixup.h> | ||||||
|  |  | ||||||
|  | #if CPU_FIXUP == 1  | ||||||
|  | #  if defined(k8) | ||||||
|  | #    define cpufixup(mem) k8_cpufixup(mem) | ||||||
|  | #  elif defined(k7) | ||||||
|  | #    define cpufixup(mem) k7_cpufixup(mem) | ||||||
|  | #  elif defined(i786) | ||||||
|  | #    define cpufixup(mem) i786_cpufixup(mem) | ||||||
|  | #  elif defined(i686) | ||||||
|  | #    define cpufixup(mem) p6_cpufixup(mem) | ||||||
|  | #  endif | ||||||
|  | #else | ||||||
|  | #  define cpufixup(mem) do {} while(0) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* CPU_CPUFIXUP_H */ | ||||||
							
								
								
									
										6
									
								
								src/include/cpu/k7/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/include/cpu/k7/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #ifndef CPU_K7_CPUFIXUP_H | ||||||
|  | #define CPU_K7_CPUFIXUP_H | ||||||
|  |  | ||||||
|  | void k7_cpufixup(struct mem_range *mem); | ||||||
|  |  | ||||||
|  | #endif /* CPU_K7_CPUFIXUP_H */ | ||||||
							
								
								
									
										42
									
								
								src/include/cpu/k7/mtrr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/include/cpu/k7/mtrr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | #ifndef CPU_K7_MTRR_H | ||||||
|  | #define CPU_K7_MTRR_H | ||||||
|  |  | ||||||
|  | #include <cpu/p6/mtrr.h> | ||||||
|  |  | ||||||
|  | #define IORR_FIRST 0xC0010016 | ||||||
|  | #define IORR_LAST  0xC0010019 | ||||||
|  | #define SYSCFG     0xC0010010 | ||||||
|  |  | ||||||
|  | #define MTRR_READ_MEM			(1 << 4) | ||||||
|  | #define MTRR_WRITE_MEM			(1 << 3) | ||||||
|  |  | ||||||
|  | #define SYSCFG_MSR			0xC0010010 | ||||||
|  | #define SYSCFG_MSR_EvictEn		(1 << 22) | ||||||
|  | #define SYSCFG_MSR_TOM2En		(1 << 21) | ||||||
|  | #define SYSCFG_MSR_MtrrVarDramEn	(1 << 20) | ||||||
|  | #define SYSCFG_MSR_MtrrFixDramModEn	(1 << 19) | ||||||
|  | #define SYSCFG_MSR_MtrrFixDramEn	(1 << 18) | ||||||
|  | #define SYSCFG_MSR_UcLockEn		(1 << 17) | ||||||
|  | #define SYSCFG_MSR_ChxToDirtyDis	(1 << 16) | ||||||
|  | #define SYSCFG_MSR_SysEccEn		(1 << 15) | ||||||
|  | #define SYSCFG_MSR_RdBlkL2WayEn		(1 << 14) | ||||||
|  | #define SYSCFG_MSR_SysFillValIsD1	(1 << 13) | ||||||
|  | #define SYSCFG_MSR_IcInclusive		(1 << 12) | ||||||
|  | #define SYSCFG_MSR_ClVicBlkEn		(1 << 11) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnO		(1 << 10) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnS		(1 <<  9) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnE		(1 <<  8) | ||||||
|  | #define SYSCFG_MSR_SysVicLimitMask	((1 << 8) - (1 << 5)) | ||||||
|  | #define SYSCFG_MSR_SysAckLimitMask	((1 << 5) - (1 << 0)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define IORR0_BASE			0xC0010016 | ||||||
|  | #define IORR0_MASK			0xC0010017 | ||||||
|  | #define IORR1_BASE			0xC0010018 | ||||||
|  | #define IORR1_MASK			0xC0010019 | ||||||
|  | #define TOP_MEM				0xC001001A | ||||||
|  | #define TOP_MEM2			0xC001001D | ||||||
|  | #define HWCR_MSR			0xC0010015 | ||||||
|  |  | ||||||
|  | #endif /* CPU_K7_MTRR_H */ | ||||||
							
								
								
									
										6
									
								
								src/include/cpu/k8/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/include/cpu/k8/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #ifndef CPU_K8_CPUFIXUP_H | ||||||
|  | #define CPU_K8_CPUFIXUP_H | ||||||
|  |  | ||||||
|  | void k8_cpufixup(struct mem_range *mem); | ||||||
|  |  | ||||||
|  | #endif /* CPU_K8_CPUFIXUP_H */ | ||||||
							
								
								
									
										45
									
								
								src/include/cpu/k8/mtrr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/include/cpu/k8/mtrr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | #ifndef CPU_K8_MTRR_H | ||||||
|  | #define CPU_K8_MTRR_H | ||||||
|  |  | ||||||
|  | #include <cpu/k7/mtrr.h> | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | #define IORR_FIRST 0xC0010016 | ||||||
|  | #define IORR_LAST  0xC0010019 | ||||||
|  | #define SYSCFG     0xC0010010 | ||||||
|  |  | ||||||
|  | #define MTRR_READ_MEM			(1 << 4) | ||||||
|  | #define MTRR_WRITE_MEM			(1 << 3) | ||||||
|  |  | ||||||
|  | #define SYSCFG_MSR			0xC0010010 | ||||||
|  | #define SYSCFG_MSR_EvictEn		(1 << 22) | ||||||
|  | #define SYSCFG_MSR_TOM2En		(1 << 21) | ||||||
|  | #define SYSCFG_MSR_MtrrVarDramEn	(1 << 20) | ||||||
|  | #define SYSCFG_MSR_MtrrFixDramModEn	(1 << 19) | ||||||
|  | #define SYSCFG_MSR_MtrrFixDramEn	(1 << 18) | ||||||
|  | #define SYSCFG_MSR_UcLockEn		(1 << 17) | ||||||
|  | #define SYSCFG_MSR_ChxToDirtyDis	(1 << 16) | ||||||
|  | #define SYSCFG_MSR_SysEccEn		(1 << 15) | ||||||
|  | #define SYSCFG_MSR_RdBlkL2WayEn		(1 << 14) | ||||||
|  | #define SYSCFG_MSR_SysFillValIsD1	(1 << 13) | ||||||
|  | #define SYSCFG_MSR_IcInclusive		(1 << 12) | ||||||
|  | #define SYSCFG_MSR_ClVicBlkEn		(1 << 11) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnO		(1 << 10) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnS		(1 <<  9) | ||||||
|  | #define SYSCFG_MSR_SetDirtyEnE		(1 <<  8) | ||||||
|  | #define SYSCFG_MSR_SysVicLimitMask	((1 << 8) - (1 << 5)) | ||||||
|  | #define SYSCFG_MSR_SysAckLimitMask	((1 << 5) - (1 << 0)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define IORR0_BASE			0xC0010016 | ||||||
|  | #define IORR0_MASK			0xC0010017 | ||||||
|  | #define IORR1_BASE			0xC0010018 | ||||||
|  | #define IORR1_MASK			0xC0010019 | ||||||
|  | #define TOP_MEM				0xC001001A | ||||||
|  | #define TOP_MEM2			0xC001001D | ||||||
|  | #define HWCR_MSR			0xC0010015 | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* CPU_K8_MTRR_H */ | ||||||
							
								
								
									
										25
									
								
								src/include/cpu/p5/cpuid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/include/cpu/p5/cpuid.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | #ifndef CPU_P5_CPUID_H | ||||||
|  | #define CPU_P5_CPUID_H | ||||||
|  |  | ||||||
|  | int mtrr_check(void); | ||||||
|  | void display_cpuid(void); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  *      Generic CPUID function. copied from Linux kernel headers | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) | ||||||
|  | { | ||||||
|  |         __asm__("pushl %%ebx\n\t" | ||||||
|  | 		"cpuid\n\t" | ||||||
|  | 		"movl	%%ebx, %%esi\n\t" | ||||||
|  | 		"popl	%%ebx\n\t" | ||||||
|  |                 : "=a" (*eax), | ||||||
|  |                   "=S" (*ebx), | ||||||
|  |                   "=c" (*ecx), | ||||||
|  |                   "=d" (*edx) | ||||||
|  |                 : "a" (op) | ||||||
|  |                 : "cc"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif /* CPU_P5_CPUID_H */ | ||||||
							
								
								
									
										175
									
								
								src/include/cpu/p6/apic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								src/include/cpu/p6/apic.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | |||||||
|  | #ifndef APIC_H | ||||||
|  | #define APIC_H | ||||||
|  |  | ||||||
|  | #define APIC_BASE_MSR 0x1B | ||||||
|  | #define APIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8) | ||||||
|  | #define APIC_BASE_MSR_ENABLE (1 << 11) | ||||||
|  | #define APIC_BASE_MSR_ADDR_MASK 0xFFFFF000 | ||||||
|  |  | ||||||
|  | #define APIC_DEFAULT_BASE 0xfee00000 | ||||||
|  |  | ||||||
|  | #define APIC_ID		0x020 | ||||||
|  | #define APIC_LVR	0x030 | ||||||
|  | #define APIC_ARBID	0x090 | ||||||
|  | #define	APIC_RRR	0x0C0 | ||||||
|  | #define APIC_SVR	0x0f0 | ||||||
|  | #define APIC_SPIV	0x0f0 | ||||||
|  | #define 	APIC_SPIV_ENABLE  0x100 | ||||||
|  | #define APIC_ESR	0x280 | ||||||
|  | #define		APIC_ESR_SEND_CS	0x00001 | ||||||
|  | #define		APIC_ESR_RECV_CS	0x00002 | ||||||
|  | #define		APIC_ESR_SEND_ACC	0x00004 | ||||||
|  | #define		APIC_ESR_RECV_ACC	0x00008 | ||||||
|  | #define		APIC_ESR_SENDILL	0x00020 | ||||||
|  | #define		APIC_ESR_RECVILL	0x00040 | ||||||
|  | #define		APIC_ESR_ILLREGA	0x00080 | ||||||
|  | #define APIC_ICR 	0x300 | ||||||
|  | #define		APIC_DEST_SELF		0x40000 | ||||||
|  | #define		APIC_DEST_ALLINC	0x80000 | ||||||
|  | #define		APIC_DEST_ALLBUT	0xC0000 | ||||||
|  | #define		APIC_ICR_RR_MASK	0x30000 | ||||||
|  | #define		APIC_ICR_RR_INVALID	0x00000 | ||||||
|  | #define		APIC_ICR_RR_INPROG	0x10000 | ||||||
|  | #define		APIC_ICR_RR_VALID	0x20000 | ||||||
|  | #define		APIC_INT_LEVELTRIG	0x08000 | ||||||
|  | #define		APIC_INT_ASSERT		0x04000 | ||||||
|  | #define		APIC_ICR_BUSY		0x01000 | ||||||
|  | #define		APIC_DEST_LOGICAL	0x00800 | ||||||
|  | #define		APIC_DM_FIXED		0x00000 | ||||||
|  | #define		APIC_DM_LOWEST		0x00100 | ||||||
|  | #define		APIC_DM_SMI		0x00200 | ||||||
|  | #define		APIC_DM_REMRD		0x00300 | ||||||
|  | #define		APIC_DM_NMI		0x00400 | ||||||
|  | #define		APIC_DM_INIT		0x00500 | ||||||
|  | #define		APIC_DM_STARTUP		0x00600 | ||||||
|  | #define		APIC_DM_EXTINT		0x00700 | ||||||
|  | #define		APIC_VECTOR_MASK	0x000FF | ||||||
|  | #define APIC_ICR2	0x310 | ||||||
|  | #define		GET_APIC_DEST_FIELD(x)	(((x)>>24)&0xFF) | ||||||
|  | #define		SET_APIC_DEST_FIELD(x)	((x)<<24) | ||||||
|  | #define APIC_LVTT	0x320 | ||||||
|  | #define APIC_LVTPC	0x340 | ||||||
|  | #define APIC_LVT0	0x350 | ||||||
|  | #define		APIC_LVT_TIMER_BASE_MASK	(0x3<<18) | ||||||
|  | #define		GET_APIC_TIMER_BASE(x)		(((x)>>18)&0x3) | ||||||
|  | #define		SET_APIC_TIMER_BASE(x)		(((x)<<18)) | ||||||
|  | #define		APIC_TIMER_BASE_CLKIN		0x0 | ||||||
|  | #define		APIC_TIMER_BASE_TMBASE		0x1 | ||||||
|  | #define		APIC_TIMER_BASE_DIV		0x2 | ||||||
|  | #define		APIC_LVT_TIMER_PERIODIC		(1<<17) | ||||||
|  | #define		APIC_LVT_MASKED			(1<<16) | ||||||
|  | #define		APIC_LVT_LEVEL_TRIGGER		(1<<15) | ||||||
|  | #define		APIC_LVT_REMOTE_IRR		(1<<14) | ||||||
|  | #define		APIC_INPUT_POLARITY		(1<<13) | ||||||
|  | #define		APIC_SEND_PENDING		(1<<12) | ||||||
|  | #define		APIC_LVT_RESERVED_1		(1<<11) | ||||||
|  | #define		APIC_DELIVERY_MODE_MASK		(7<<8) | ||||||
|  | #define		APIC_DELIVERY_MODE_FIXED	(0<<8) | ||||||
|  | #define		APIC_DELIVERY_MODE_NMI		(4<<8) | ||||||
|  | #define		APIC_DELIVERY_MODE_EXTINT	(7<<8) | ||||||
|  | #define		GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7) | ||||||
|  | #define		SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8)) | ||||||
|  | #define			APIC_MODE_FIXED		0x0 | ||||||
|  | #define			APIC_MODE_NMI		0x4 | ||||||
|  | #define			APIC_MODE_EXINT		0x7 | ||||||
|  | #define APIC_LVT1	0x360 | ||||||
|  | #define APIC_LVTERR	0x370 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if !defined(ASSEMBLY) | ||||||
|  |  | ||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) | ||||||
|  |  | ||||||
|  | struct __xchg_dummy { unsigned long a[100]; }; | ||||||
|  | #define __xg(x) ((struct __xchg_dummy *)(x)) | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway | ||||||
|  |  * Note 2: xchg has side effect, so that attribute volatile is necessary, | ||||||
|  |  *	  but generally the primitive is invalid, *ptr is output argument. --ANK | ||||||
|  |  */ | ||||||
|  | static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) | ||||||
|  | { | ||||||
|  | 	switch (size) { | ||||||
|  | 		case 1: | ||||||
|  | 			__asm__ __volatile__("xchgb %b0,%1" | ||||||
|  | 				:"=q" (x) | ||||||
|  | 				:"m" (*__xg(ptr)), "0" (x) | ||||||
|  | 				:"memory"); | ||||||
|  | 			break; | ||||||
|  | 		case 2: | ||||||
|  | 			__asm__ __volatile__("xchgw %w0,%1" | ||||||
|  | 				:"=r" (x) | ||||||
|  | 				:"m" (*__xg(ptr)), "0" (x) | ||||||
|  | 				:"memory"); | ||||||
|  | 			break; | ||||||
|  | 		case 4: | ||||||
|  | 			__asm__ __volatile__("xchgl %0,%1" | ||||||
|  | 				:"=r" (x) | ||||||
|  | 				:"m" (*__xg(ptr)), "0" (x) | ||||||
|  | 				:"memory"); | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 	return x; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static inline unsigned long apic_read(unsigned long reg) | ||||||
|  | { | ||||||
|  | 	return *((volatile unsigned long *)(APIC_DEFAULT_BASE+reg)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | extern inline void apic_write_atomic(unsigned long reg, unsigned long v) | ||||||
|  | { | ||||||
|  | 	xchg((volatile unsigned long *)(APIC_DEFAULT_BASE+reg), v); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void apic_write(unsigned long reg, unsigned long v) | ||||||
|  | { | ||||||
|  | 	*((volatile unsigned long *)(APIC_DEFAULT_BASE+reg)) = v; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void apic_wait_icr_idle(void) | ||||||
|  | { | ||||||
|  | 	do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_X86_GOOD_APIC | ||||||
|  | # define FORCE_READ_AROUND_WRITE 0 | ||||||
|  | # define apic_read_around(x) apic_read(x) | ||||||
|  | # define apic_write_around(x,y) apic_write((x),(y)) | ||||||
|  | #else | ||||||
|  | # define FORCE_READ_AROUND_WRITE 1 | ||||||
|  | # define apic_read_around(x) apic_read(x) | ||||||
|  | # define apic_write_around(x,y) apic_write_atomic((x),(y)) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static inline int apic_remote_read(int apicid, int reg, unsigned long *pvalue) | ||||||
|  | { | ||||||
|  | 	int timeout; | ||||||
|  | 	unsigned long status; | ||||||
|  | 	int result; | ||||||
|  | 	apic_wait_icr_idle(); | ||||||
|  | 	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); | ||||||
|  | 	apic_write_around(APIC_ICR, APIC_DM_REMRD | (reg >> 4)); | ||||||
|  | 	timeout = 0; | ||||||
|  | 	do { | ||||||
|  | #if 0 | ||||||
|  | 		udelay(100); | ||||||
|  | #endif | ||||||
|  | 		status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK; | ||||||
|  | 	} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000); | ||||||
|  |  | ||||||
|  | 	result = -1; | ||||||
|  | 	if (status == APIC_ICR_RR_VALID) { | ||||||
|  | 		*pvalue = apic_read(APIC_RRR); | ||||||
|  | 		result = 0; | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | #endif /* ASSEMBLY */ | ||||||
|  |  | ||||||
|  | #endif /* APIC_H */ | ||||||
							
								
								
									
										6
									
								
								src/include/cpu/p6/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/include/cpu/p6/cpufixup.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #ifndef CPU_P6_CPUFIXUP_H | ||||||
|  | #define CPU_P6_CPUFIXUP_H | ||||||
|  |  | ||||||
|  | void p6_cpufixup(struct mem_range *mem); | ||||||
|  |  | ||||||
|  | #endif /* CPU_P6_CPUFIXUP_H */ | ||||||
							
								
								
									
										33
									
								
								src/include/cpu/p6/msr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/include/cpu/p6/msr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | #ifndef CPU_P6_MSR_H | ||||||
|  | #define CPU_P6_MSR_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Access to machine-specific registers (available on 586 and better only) | ||||||
|  |  * Note: the rd* operations modify the parameters directly (without using | ||||||
|  |  * pointer indirection), this allows gcc to optimize better | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define rdmsr(msr,val1,val2) \ | ||||||
|  |        __asm__ __volatile__("rdmsr" \ | ||||||
|  | 			    : "=a" (val1), "=d" (val2) \ | ||||||
|  | 			    : "c" (msr)) | ||||||
|  |  | ||||||
|  | #define wrmsr(msr,val1,val2) \ | ||||||
|  |      __asm__ __volatile__("wrmsr" \ | ||||||
|  | 			  : /* no outputs */ \ | ||||||
|  | 			  : "c" (msr), "a" (val1), "d" (val2)) | ||||||
|  |  | ||||||
|  | #define rdtsc(low,high) \ | ||||||
|  |      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) | ||||||
|  |  | ||||||
|  | #define rdtscl(low) \ | ||||||
|  |      __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") | ||||||
|  |  | ||||||
|  | #define rdtscll(val) \ | ||||||
|  |      __asm__ __volatile__ ("rdtsc" : "=A" (val)) | ||||||
|  |  | ||||||
|  | #define rdpmc(counter,low,high) \ | ||||||
|  |      __asm__ __volatile__("rdpmc" \ | ||||||
|  | 			  : "=a" (low), "=d" (high) \ | ||||||
|  | 			  : "c" (counter)) | ||||||
|  | #endif /* CPU_P6_MSR_H */ | ||||||
							
								
								
									
										44
									
								
								src/include/cpu/p6/mtrr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/include/cpu/p6/mtrr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | #ifndef __LINUXBIOS_CPU_P6_MTRR_H | ||||||
|  | #define __LINUXBIOS_CPU_P6_MTRR_H | ||||||
|  |  | ||||||
|  | /*  These are the region types  */ | ||||||
|  | #define MTRR_TYPE_UNCACHABLE 0 | ||||||
|  | #define MTRR_TYPE_WRCOMB     1 | ||||||
|  | /*#define MTRR_TYPE_         2*/ | ||||||
|  | /*#define MTRR_TYPE_         3*/ | ||||||
|  | #define MTRR_TYPE_WRTHROUGH  4 | ||||||
|  | #define MTRR_TYPE_WRPROT     5 | ||||||
|  | #define MTRR_TYPE_WRBACK     6 | ||||||
|  | #define MTRR_NUM_TYPES       7 | ||||||
|  |  | ||||||
|  | #define MTRRcap_MSR     0x0fe | ||||||
|  | #define MTRRdefType_MSR 0x2ff | ||||||
|  |  | ||||||
|  | #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) | ||||||
|  | #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) | ||||||
|  |  | ||||||
|  | #define NUM_FIXED_RANGES 88 | ||||||
|  | #define MTRRfix64K_00000_MSR 0x250 | ||||||
|  | #define MTRRfix16K_80000_MSR 0x258 | ||||||
|  | #define MTRRfix16K_A0000_MSR 0x259 | ||||||
|  | #define MTRRfix4K_C0000_MSR 0x268 | ||||||
|  | #define MTRRfix4K_C8000_MSR 0x269 | ||||||
|  | #define MTRRfix4K_D0000_MSR 0x26a | ||||||
|  | #define MTRRfix4K_D8000_MSR 0x26b | ||||||
|  | #define MTRRfix4K_E0000_MSR 0x26c | ||||||
|  | #define MTRRfix4K_E8000_MSR 0x26d | ||||||
|  | #define MTRRfix4K_F0000_MSR 0x26e | ||||||
|  | #define MTRRfix4K_F8000_MSR 0x26f | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if !defined(ASSEMBLY) | ||||||
|  |  | ||||||
|  | void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type); | ||||||
|  | #if defined(INTEL_PPRO_MTRR)  | ||||||
|  | struct mem_range; | ||||||
|  | void setup_mtrrs(struct mem_range *mem); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* ASSEMBLY */ | ||||||
|  |  | ||||||
|  | #endif /* __LINUXBIOS_CPU_P6_MTRR_H */ | ||||||
							
								
								
									
										8
									
								
								src/include/delay.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/include/delay.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | #ifndef DELAY_H | ||||||
|  | #define DELAY_H | ||||||
|  |  | ||||||
|  | void udelay(int usecs); | ||||||
|  | void mdelay(int msecs); | ||||||
|  | void delay(int secs); | ||||||
|  |  | ||||||
|  | #endif /* DELAY_H */ | ||||||
							
								
								
									
										7
									
								
								src/include/ip_checksum.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/include/ip_checksum.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #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 */ | ||||||
							
								
								
									
										13
									
								
								src/include/mem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/include/mem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | #ifndef MEM_H | ||||||
|  | #define MEM_H | ||||||
|  |  | ||||||
|  | struct mem_range { | ||||||
|  | 	unsigned long basek; | ||||||
|  | 	unsigned long sizek; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* mem_range arrays are non-overlapping, in ascending order and null terminated */ | ||||||
|  |  | ||||||
|  | struct mem_range *sizeram(void); | ||||||
|  |  | ||||||
|  | #endif /* MEM_H */ | ||||||
							
								
								
									
										16
									
								
								src/include/part/fallback_boot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/include/part/fallback_boot.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | #ifndef PART_FALLBACK_BOOT_H | ||||||
|  | #define PART_FALLBACK_BOOT_H | ||||||
|  |  | ||||||
|  | #ifndef ASSEMBLY | ||||||
|  |  | ||||||
|  | #if HAVE_FALLBACK_BOOT | ||||||
|  | void boot_successful(void); | ||||||
|  | #else | ||||||
|  | #define boot_successful() | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* ASSEMBLY */ | ||||||
|  |  | ||||||
|  | #define RTC_BOOT_BYTE	48 | ||||||
|  |  | ||||||
|  | #endif /* PART_FALLBACK_BOOT_H */ | ||||||
							
								
								
									
										7
									
								
								src/include/part/sizeram.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/include/part/sizeram.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #ifndef PART_SIZERAM_H | ||||||
|  | #define PART_SIZERAM_H | ||||||
|  |  | ||||||
|  | struct mem_rang; | ||||||
|  | struct mem_range *sizeram(void); | ||||||
|  |  | ||||||
|  | #endif /* PART_SIZERAM_H */ | ||||||
							
								
								
									
										110
									
								
								src/include/pc80/mc146818rtc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/include/pc80/mc146818rtc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | |||||||
|  | #ifndef PC80_MC146818RTC_H | ||||||
|  | #define PC80_MC146818RTC_H | ||||||
|  |  | ||||||
|  | #ifndef RTC_BASE_PORT | ||||||
|  | #define RTC_BASE_PORT 0x70 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define RTC_PORT(x)	(RTC_BASE_PORT + (x)) | ||||||
|  |  | ||||||
|  | /* On PCs, the checksum is built only over bytes 16..45 */ | ||||||
|  | #define PC_CKS_RANGE_START	16 | ||||||
|  | #define PC_CKS_RANGE_END	45 | ||||||
|  | #define PC_CKS_LOC		46 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Linux bios checksum is built only over bytes 49..125 */ | ||||||
|  | #define LB_CKS_RANGE_START	49 | ||||||
|  | #define LB_CKS_RANGE_END	125 | ||||||
|  | #define LB_CKS_LOC		126 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* control registers - Moto names | ||||||
|  |  */ | ||||||
|  | #define RTC_REG_A		10 | ||||||
|  | #define RTC_REG_B		11 | ||||||
|  | #define RTC_REG_C		12 | ||||||
|  | #define RTC_REG_D		13 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /********************************************************************** | ||||||
|  |  * register details | ||||||
|  |  **********************************************************************/ | ||||||
|  | #define RTC_FREQ_SELECT	RTC_REG_A | ||||||
|  |  | ||||||
|  | /* update-in-progress  - set to "1" 244 microsecs before RTC goes off the bus, | ||||||
|  |  * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, | ||||||
|  |  * totalling to a max high interval of 2.228 ms. | ||||||
|  |  */ | ||||||
|  | # define RTC_UIP		0x80 | ||||||
|  | # define RTC_DIV_CTL		0x70 | ||||||
|  |    /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ | ||||||
|  | #  define RTC_REF_CLCK_4MHZ	0x00 | ||||||
|  | #  define RTC_REF_CLCK_1MHZ	0x10 | ||||||
|  | #  define RTC_REF_CLCK_32KHZ	0x20 | ||||||
|  |    /* 2 values for divider stage reset, others for "testing purposes only" */ | ||||||
|  | #  define RTC_DIV_RESET1	0x60 | ||||||
|  | #  define RTC_DIV_RESET2	0x70 | ||||||
|  |   /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ | ||||||
|  | # define RTC_RATE_SELECT 	0x0F | ||||||
|  | #  define RTC_RATE_NONE		0x00 | ||||||
|  | #  define RTC_RATE_32786HZ	0x01 | ||||||
|  | #  define RTC_RATE_16384HZ	0x02 | ||||||
|  | #  define RTC_RATE_8192HZ	0x03 | ||||||
|  | #  define RTC_RATE_4096HZ	0x04 | ||||||
|  | #  define RTC_RATE_2048HZ	0x05 | ||||||
|  | #  define RTC_RATE_1024HZ	0x06 | ||||||
|  | #  define RTC_RATE_512HZ	0x07 | ||||||
|  | #  define RTC_RATE_256HZ	0x08 | ||||||
|  | #  define RTC_RATE_128HZ	0x09 | ||||||
|  | #  define RTC_RATE_64HZ		0x0a | ||||||
|  | #  define RTC_RATE_32HZ		0x0b | ||||||
|  | #  define RTC_RATE_16HZ		0x0c | ||||||
|  | #  define RTC_RATE_8HZ		0x0d | ||||||
|  | #  define RTC_RATE_4HZ		0x0e | ||||||
|  | #  define RTC_RATE_2HZ		0x0f | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_CONTROL	RTC_REG_B | ||||||
|  | # define RTC_SET 0x80		/* disable updates for clock setting */ | ||||||
|  | # define RTC_PIE 0x40		/* periodic interrupt enable */ | ||||||
|  | # define RTC_AIE 0x20		/* alarm interrupt enable */ | ||||||
|  | # define RTC_UIE 0x10		/* update-finished interrupt enable */ | ||||||
|  | # define RTC_SQWE 0x08		/* enable square-wave output */ | ||||||
|  | # define RTC_DM_BINARY 0x04	/* all time/date values are BCD if clear */ | ||||||
|  | # define RTC_24H 0x02		/* 24 hour mode - else hours bit 7 means pm */ | ||||||
|  | # define RTC_DST_EN 0x01	/* auto switch DST - works f. USA only */ | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_INTR_FLAGS	RTC_REG_C | ||||||
|  | /* caution - cleared by read */ | ||||||
|  | # define RTC_IRQF 0x80		/* any of the following 3 is active */ | ||||||
|  | # define RTC_PF 0x40 | ||||||
|  | # define RTC_AF 0x20 | ||||||
|  | # define RTC_UF 0x10 | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_VALID	RTC_REG_D | ||||||
|  | # define RTC_VRT 0x80		/* valid RAM and time */ | ||||||
|  | /**********************************************************************/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* On PCs, the checksum is built only over bytes 16..45 */ | ||||||
|  | #define PC_CKS_RANGE_START	16 | ||||||
|  | #define PC_CKS_RANGE_END	45 | ||||||
|  | #define PC_CKS_LOC		46 | ||||||
|  |  | ||||||
|  | #define LB_CKS_RANGE_START	49 | ||||||
|  | #define LB_CKS_RANGE_END	125 | ||||||
|  | #define LB_CKS_LOC		126 | ||||||
|  |  | ||||||
|  | #if !defined(ASSEMBLY) | ||||||
|  | void rtc_init(int invalid); | ||||||
|  | #if USE_OPTION_TABLE == 1 | ||||||
|  | int get_option(void *dest, char *name); | ||||||
|  | #else | ||||||
|  | #define get_option(dest, name) (-2) | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /*  PC80_MC146818RTC_H */ | ||||||
							
								
								
									
										53
									
								
								src/include/smp/atomic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/include/smp/atomic.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | #ifndef SMP_ATOMIC_H | ||||||
|  | #define SMP_ATOMIC_H | ||||||
|  |  | ||||||
|  | #ifdef SMP | ||||||
|  | #include <arch/smp/atomic.h> | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | typedef struct { int counter; } atomic_t; | ||||||
|  | #define ATOMIC_INIT(i) { (i) } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * atomic_read - read atomic variable | ||||||
|  |  * @v: pointer of type atomic_t | ||||||
|  |  *  | ||||||
|  |  * Atomically reads the value of @v.  Note that the guaranteed | ||||||
|  |  * useful range of an atomic_t is only 24 bits. | ||||||
|  |  */  | ||||||
|  | #define atomic_read(v)		((v)->counter) | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * atomic_set - set atomic variable | ||||||
|  |  * @v: pointer of type atomic_t | ||||||
|  |  * @i: required value | ||||||
|  |  *  | ||||||
|  |  * Atomically sets the value of @v to @i.  Note that the guaranteed | ||||||
|  |  * useful range of an atomic_t is only 24 bits. | ||||||
|  |  */  | ||||||
|  | #define atomic_set(v,i)		(((v)->counter) = (i)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * atomic_inc - increment atomic variable | ||||||
|  |  * @v: pointer of type atomic_t | ||||||
|  |  *  | ||||||
|  |  * Atomically increments @v by 1.  Note that the guaranteed | ||||||
|  |  * useful range of an atomic_t is only 24 bits. | ||||||
|  |  */  | ||||||
|  | #define atomic_inc(v)	(((v)->counter)++) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * atomic_dec - decrement atomic variable | ||||||
|  |  * @v: pointer of type atomic_t | ||||||
|  |  *  | ||||||
|  |  * Atomically decrements @v by 1.  Note that the guaranteed | ||||||
|  |  * useful range of an atomic_t is only 24 bits. | ||||||
|  |  */  | ||||||
|  | #define atomic_dec(v)	(((v)->counter)--) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* SMP */ | ||||||
|  |  | ||||||
|  | #endif /* SMP_ATOMIC_H */ | ||||||
							
								
								
									
										24
									
								
								src/include/smp/spinlock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/include/smp/spinlock.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #ifndef SMP_SPINLOCK_H | ||||||
|  | #define SMP_SPINLOCK_H | ||||||
|  |  | ||||||
|  | #ifdef SMP | ||||||
|  | #include <arch/smp/spinlock.h> | ||||||
|  | #else /* !SMP */ | ||||||
|  |  | ||||||
|  | /* Most GCC versions have a nasty bug with empty initializers */ | ||||||
|  | #if (__GNUC__ > 2)  | ||||||
|  | typedef struct { } spinlock_t; | ||||||
|  | #define SPIN_LOCK_UNLOCKED (spinlock_t) { } | ||||||
|  | #else | ||||||
|  | typedef struct { int gcc_is_buggy; } spinlock_t; | ||||||
|  | #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define barrier()		do {} while(0) | ||||||
|  | #define spin_is_locked(lock)	0 | ||||||
|  | #define spin_unlock_wait(lock)	do {} while(0) | ||||||
|  | #define spin_lock(lock)		do {} while(0) | ||||||
|  | #define spin_unlock(lock)	do {} while(0) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* SMP_SPINLOCK_H */ | ||||||
							
								
								
									
										17
									
								
								src/include/smp/start_stop.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/include/smp/start_stop.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #ifndef SMP_START_STOP_H | ||||||
|  | #define SMP_START_STOP_H | ||||||
|  |  | ||||||
|  | #if SMP == 1 | ||||||
|  | #include <smp/atomic.h> | ||||||
|  | unsigned long this_processors_id(void); | ||||||
|  | int processor_index(unsigned long processor_id); | ||||||
|  | void stop_cpu(unsigned long processor_id); | ||||||
|  | int start_cpu(unsigned long processor_id); | ||||||
|  | void startup_other_cpus(unsigned long *processor_map); | ||||||
|  | #else | ||||||
|  | #define this_processors_id()	0 | ||||||
|  | #define startup_other_cpus(p)	do {} while(0) | ||||||
|  | #define processor_index(p) 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* SMP_START_STOP_H */ | ||||||
							
								
								
									
										14
									
								
								src/include/stdlib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/include/stdlib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | #ifndef STDLIB_H | ||||||
|  | #define STDLIB_H | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | extern void *malloc(size_t size); | ||||||
|  | void free(void *ptr); | ||||||
|  |  | ||||||
|  | /* Extensions to malloc... */ | ||||||
|  | typedef size_t malloc_mark_t; | ||||||
|  | void malloc_mark(malloc_mark_t *place); | ||||||
|  | void malloc_release(malloc_mark_t *place); | ||||||
|  |  | ||||||
|  | #endif /* STDLIB_H */ | ||||||
							
								
								
									
										13
									
								
								src/include/stream/read_bytes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/include/stream/read_bytes.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | #ifndef STREAM_READ_BYTES_H | ||||||
|  | #define STREAM_READ_BYTES_H | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | typedef long byte_offset_t; | ||||||
|  |  | ||||||
|  | extern int stream_init(void); | ||||||
|  | extern byte_offset_t stream_read(void *vdest, byte_offset_t count); | ||||||
|  | extern byte_offset_t stream_skip(byte_offset_t count); | ||||||
|  | extern void stream_fini(void); | ||||||
|  |  | ||||||
|  | #endif /* STREAM_READ_BYTES_H */ | ||||||
							
								
								
									
										36
									
								
								src/include/string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/include/string.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | #ifndef STRING_H | ||||||
|  | #define STRING_H | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | // yes, linux has fancy ones. We don't care. This stuff gets used  | ||||||
|  | // hardly at all. And the pain of including those files is just too high. | ||||||
|  |  | ||||||
|  | //extern inline void strcpy(char *dst, char *src) {while (*src) *dst++ = *src++;} | ||||||
|  |  | ||||||
|  | //extern inline int strlen(char *src) { int i = 0; while (*src++) i++; return i;} | ||||||
|  |  | ||||||
|  | static inline size_t strnlen(const char *src, size_t max)  | ||||||
|  | {  | ||||||
|  | 	size_t i = 0; | ||||||
|  | 	while((*src++) && (i < max)) { | ||||||
|  | 		i++; | ||||||
|  | 	} | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline size_t strlen(const char *src) | ||||||
|  | { | ||||||
|  | 	size_t i = 0; | ||||||
|  | 	while(*src++) { | ||||||
|  | 		i++; | ||||||
|  | 	} | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | extern void *memcpy(void *dest, const void *src, size_t n); | ||||||
|  | extern void *memset(void *s, int c, size_t n); | ||||||
|  | extern int memcmp(const void *s1, const void *s2, size_t n); | ||||||
|  |  | ||||||
|  | extern int sprintf(char * buf, const char *fmt, ...); | ||||||
|  | #endif /* STRING_H */ | ||||||
							
								
								
									
										7
									
								
								src/include/uart8250.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/include/uart8250.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #ifndef UART8250_H | ||||||
|  | #define UART8250_H | ||||||
|  |  | ||||||
|  | void uart8250_tx_byte(unsigned base_port, unsigned char data); | ||||||
|  | void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs); | ||||||
|  |  | ||||||
|  | #endif /* UART8250_H */ | ||||||
							
								
								
									
										22
									
								
								src/include/version.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/include/version.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | #ifndef VERSION_H | ||||||
|  | #define VERSION_H | ||||||
|  |  | ||||||
|  | /* Motherboard Information */ | ||||||
|  | extern const char mainboard_vendor[]; | ||||||
|  | extern const char mainboard_part_number[]; | ||||||
|  |  | ||||||
|  | /* LinuxBIOS Version */ | ||||||
|  | extern const char linuxbios_version[]; | ||||||
|  | extern const char linuxbios_extra_version[]; | ||||||
|  | extern const char linuxbios_build[]; | ||||||
|  |  | ||||||
|  | /* When LinuxBIOS was compiled */ | ||||||
|  | extern const char linuxbios_compile_time[]; | ||||||
|  | extern const char linuxbios_compile_by[]; | ||||||
|  | extern const char linuxbios_compile_host[]; | ||||||
|  | extern const char linuxbios_compile_domain[]; | ||||||
|  | extern const char linuxbios_compiler[]; | ||||||
|  | extern const char linuxbios_linker[]; | ||||||
|  | extern const char linuxbios_assembler[]; | ||||||
|  |  | ||||||
|  | #endif /* VERSION_H */ | ||||||
							
								
								
									
										18
									
								
								src/lib/clog2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/lib/clog2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  | unsigned long log2(unsigned long x) | ||||||
|  | { | ||||||
|  |         // assume 8 bits per byte. | ||||||
|  |         unsigned long i = 1 << (sizeof(x)*8 - 1); | ||||||
|  |         unsigned long pow = sizeof(x) * 8 - 1; | ||||||
|  |  | ||||||
|  |         if (! x) { | ||||||
|  |                 printk_warning("%s called with invalid parameter of 0\n", | ||||||
|  | 			__FUNCTION__); | ||||||
|  |                 return -1; | ||||||
|  |         } | ||||||
|  |         for(; i > x; i >>= 1, pow--) | ||||||
|  |                 ; | ||||||
|  |  | ||||||
|  |         return pow; | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								src/lib/compute_ip_checksum.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/lib/compute_ip_checksum.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | #include <stdint.h> | ||||||
|  | #include <ip_checksum.h> | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								src/lib/delay.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/lib/delay.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | #include <delay.h> | ||||||
|  | void mdelay(int msecs) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < msecs; i++) { | ||||||
|  | 		udelay(1000); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | void delay(int secs) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	for(i = 0; i < secs; i++) { | ||||||
|  | 		mdelay(1000); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								src/lib/fallback_boot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/lib/fallback_boot.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <part/fallback_boot.h> | ||||||
|  | #include <pc80/mc146818rtc.h> | ||||||
|  | #include <arch/io.h> | ||||||
|  |  | ||||||
|  | void boot_successful(void) | ||||||
|  | { | ||||||
|  | 	/* Remember I succesfully booted by setting | ||||||
|  | 	 * the initial boot direction | ||||||
|  | 	 * to the direction that I booted. | ||||||
|  | 	 */ | ||||||
|  | 	unsigned char index, byte; | ||||||
|  | 	index = inb(RTC_PORT(0)) & 0x80; | ||||||
|  | 	index |= RTC_BOOT_BYTE; | ||||||
|  | 	outb(index, RTC_PORT(0)); | ||||||
|  |  | ||||||
|  | 	byte = inb(RTC_PORT(1)); | ||||||
|  | 	byte &= 0xfe; | ||||||
|  | 	byte |= (byte & 2) >> 1; | ||||||
|  |  | ||||||
|  | 	/* If we are in normal mode set the boot count to 0 */ | ||||||
|  | 	if(byte & 1) | ||||||
|  | 		byte &= 0x0f; | ||||||
|  | 	outb(byte, RTC_PORT(1)); | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								src/lib/malloc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/lib/malloc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include <console/console.h> | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | #define MALLOCDBG(x) | ||||||
|  | #else | ||||||
|  | #define MALLOCDBG(x) printk_spew x | ||||||
|  | #endif | ||||||
|  | extern unsigned char _heap, _eheap; | ||||||
|  | static size_t free_mem_ptr = (size_t)&_heap;		/* Start of heap */ | ||||||
|  | static size_t free_mem_end_ptr = (size_t)&_eheap;	/* End of heap */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void malloc_mark(malloc_mark_t *place) | ||||||
|  | { | ||||||
|  | 	*place = free_mem_ptr; | ||||||
|  | 	printk_spew("malloc_mark 0x%08lx\n", (unsigned long)free_mem_ptr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void malloc_release(malloc_mark_t *ptr) | ||||||
|  | { | ||||||
|  | 	free_mem_ptr = *ptr; | ||||||
|  | 	printk_spew("malloc_release 0x%08lx\n", (unsigned long)free_mem_ptr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *malloc(size_t size) | ||||||
|  | { | ||||||
|  | 	void *p; | ||||||
|  |  | ||||||
|  | 	MALLOCDBG(("%s Enter, size %d, free_mem_ptr %p\n", __FUNCTION__, size, free_mem_ptr)); | ||||||
|  | 	if (size < 0) | ||||||
|  | 		die("Error! malloc: Size < 0"); | ||||||
|  | 	if (free_mem_ptr <= 0) | ||||||
|  | 		die("Error! malloc: Free_mem_ptr <= 0"); | ||||||
|  |  | ||||||
|  | 	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */ | ||||||
|  |  | ||||||
|  | 	p = (void *) free_mem_ptr; | ||||||
|  | 	free_mem_ptr += size; | ||||||
|  |  | ||||||
|  | 	if (free_mem_ptr >= free_mem_end_ptr) | ||||||
|  | 		die("Error! malloc: Free_mem_ptr >= free_mem_end_ptr"); | ||||||
|  |  | ||||||
|  | 	MALLOCDBG(("malloc 0x%08lx\n", (unsigned long)p)); | ||||||
|  |  | ||||||
|  | 	return p; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void free(void *where) | ||||||
|  | { | ||||||
|  | 	/* Don't care */ | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								src/lib/memcmp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/lib/memcmp.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | int memcmp(const void *src1, const void *src2, size_t bytes) | ||||||
|  | { | ||||||
|  | 	const unsigned char *s1, *s2; | ||||||
|  | 	int result; | ||||||
|  | 	s1 = src1; | ||||||
|  | 	s2 = src2; | ||||||
|  | 	result = 0; | ||||||
|  | 	while((bytes > 0) && (result == 0)) { | ||||||
|  | 		result = *s1 - *s2; | ||||||
|  | 		bytes--; | ||||||
|  | 		s1++; | ||||||
|  | 		s2++; | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								src/lib/memcpy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/lib/memcpy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | #include <string.h> | ||||||
|  | void *memcpy(void *__dest, __const void *__src, size_t __n) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	char *d = (char *) __dest, *s = (char *) __src; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < __n; i++) | ||||||
|  | 		d[i] = s[i]; | ||||||
|  |  | ||||||
|  | 	return __dest; | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								src/lib/memset.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/lib/memset.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | void *memset(void *s, int c, size_t n) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	char *ss = (char *) s; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < n; i++) | ||||||
|  | 		ss[i] = c; | ||||||
|  |  | ||||||
|  | 	return s; | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								src/lib/uart8250.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/lib/uart8250.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #ifndef lint | ||||||
|  | static char rcsid[] = "$Id$"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* Should support 8250, 16450, 16550, 16550A type uarts */ | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <uart8250.h> | ||||||
|  |  | ||||||
|  | /* Data */ | ||||||
|  | #define UART_RBR 0x00 | ||||||
|  | #define UART_TBR 0x00 | ||||||
|  |  | ||||||
|  | /* Control */ | ||||||
|  | #define UART_IER 0x01 | ||||||
|  | #define UART_IIR 0x02 | ||||||
|  | #define UART_FCR 0x02 | ||||||
|  | #define UART_LCR 0x03 | ||||||
|  | #define UART_MCR 0x04 | ||||||
|  | #define UART_DLL 0x00 | ||||||
|  | #define UART_DLM 0x01 | ||||||
|  |  | ||||||
|  | /* Status */ | ||||||
|  | #define UART_LSR 0x05 | ||||||
|  | #define UART_MSR 0x06 | ||||||
|  | #define UART_SCR 0x07 | ||||||
|  |  | ||||||
|  | static inline int uart8250_can_tx_byte(unsigned base_port) | ||||||
|  | { | ||||||
|  | 	return inb(base_port + UART_LSR) & 0x20; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void uart8250_wait_to_tx_byte(unsigned base_port) | ||||||
|  | { | ||||||
|  | 	while(!uart8250_can_tx_byte(base_port)) | ||||||
|  | 		; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void uart8250_wait_until_sent(unsigned base_port) | ||||||
|  | { | ||||||
|  | 	while(!(inb(base_port + UART_LSR) & 0x40))  | ||||||
|  | 		; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void uart8250_tx_byte(unsigned base_port, unsigned char data) | ||||||
|  | { | ||||||
|  | 	uart8250_wait_to_tx_byte(base_port); | ||||||
|  | 	outb(data, base_port + UART_TBR); | ||||||
|  | 	/* Make certain the data clears the fifos */ | ||||||
|  | 	uart8250_wait_until_sent(base_port); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs) | ||||||
|  | { | ||||||
|  | 	lcs &= 0x7f; | ||||||
|  | 	/* disable interrupts */ | ||||||
|  | 	outb(0x0, base_port + UART_IER); | ||||||
|  | 	/* enable fifo's */ | ||||||
|  | 	outb(0x01, base_port + UART_FCR); | ||||||
|  | 	/* Set Baud Rate Divisor to 12 ==> 115200 Baud */ | ||||||
|  | 	outb(0x80 | lcs, base_port + UART_LCR); | ||||||
|  | 	outb(divisor & 0xFF,   base_port + UART_DLL); | ||||||
|  | 	outb((divisor >> 8) & 0xFF,    base_port + UART_DLM); | ||||||
|  | 	outb(lcs, base_port + UART_LCR); | ||||||
|  | } | ||||||
							
								
								
									
										62
									
								
								src/lib/version.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/lib/version.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | #include <version.h> | ||||||
|  |  | ||||||
|  | #define __STR(X) #X | ||||||
|  | #define STR(X) __STR(X) | ||||||
|  |  | ||||||
|  | #ifndef MAINBOARD_VENDOR | ||||||
|  | #error MAINBOARD_VENDOR not defined | ||||||
|  | #endif | ||||||
|  | #ifndef MAINBOARD_PART_NUMBER | ||||||
|  | #error  MAINBOARD_PART_NUMBER not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LINUXBIOS_VERSION | ||||||
|  | #error  LINUXBIOS_VERSION not defined | ||||||
|  | #endif | ||||||
|  | #ifndef LINUXBIOS_BUILD | ||||||
|  | #error  LINUXBIOS_BUILD not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LINUXBIOS_COMPILE_TIME | ||||||
|  | #error  LINUXBIOS_COMPILE_TIME not defined | ||||||
|  | #endif | ||||||
|  | #ifndef LINUXBIOS_COMPILE_BY | ||||||
|  | #error  LINUXBIOS_COMPILE_BY not defined | ||||||
|  | #endif | ||||||
|  | #ifndef LINUXBIOS_COMPILE_HOST | ||||||
|  | #error  LINUXBIOS_COMPILE_HOST not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef LINUXBIOS_COMPILER | ||||||
|  | #error  LINUXBIOS_COMPILER not defined | ||||||
|  | #endif | ||||||
|  | #ifndef LINUXBIOS_LINKER | ||||||
|  | #error  LINUXBIOS_LINKER not defined | ||||||
|  | #endif | ||||||
|  | #ifndef LINUXBIOS_ASSEMBLER | ||||||
|  | #error  LINUXBIOS_ASSEMBLER not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef  LINUXBIOS_EXTRA_VERSION | ||||||
|  | #define LINUXBIOS_EXTRA_VERSION | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | const char mainboard_vendor[] = STR(MAINBOARD_VENDOR); | ||||||
|  | const char mainboard_part_number[] = STR(MAINBOARD_PART_NUMBER); | ||||||
|  |  | ||||||
|  | const char linuxbios_version[] = STR(LINUXBIOS_VERSION); | ||||||
|  | const char linuxbios_extra_version[] = STR(LINUXBIOS_EXTRA_VERSION); | ||||||
|  | const char linuxbios_build[] = STR(LINUXBIOS_BUILD); | ||||||
|  |  | ||||||
|  | const char linuxbios_compile_time[]   = STR(LINUXBIOS_COMPILE_TIME); | ||||||
|  | const char linuxbios_compile_by[]     = STR(LINUXBIOS_COMPILE_BY); | ||||||
|  | const char linuxbios_compile_host[]   = STR(LINUXBIOS_COMPILE_HOST); | ||||||
|  | const char linuxbios_compile_domain[] = STR(LINUXBIOS_COMPILE_DOMAIN); | ||||||
|  | const char linuxbios_compiler[]       = STR(LINUXBIOS_COMPILER); | ||||||
|  | const char linuxbios_linker[]         = STR(LINUXBIOS_LINKER); | ||||||
|  | const char linuxbios_assembler[]      = STR(LINUXBIOS_ASSEMBLER); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										1070
									
								
								src/mainboard/amd/solo/auto.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1070
									
								
								src/mainboard/amd/solo/auto.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										74
									
								
								src/mainboard/amd/solo/cmos.layout
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/mainboard/amd/solo/cmos.layout
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | entries | ||||||
|  |  | ||||||
|  | #start-bit length  config config-ID    name | ||||||
|  | #0            8       r       0        seconds | ||||||
|  | #8            8       r       0        alarm_seconds | ||||||
|  | #16           8       r       0        minutes | ||||||
|  | #24           8       r       0        alarm_minutes | ||||||
|  | #32           8       r       0        hours | ||||||
|  | #40           8       r       0        alarm_hours | ||||||
|  | #48           8       r       0        day_of_week | ||||||
|  | #56           8       r       0        day_of_month | ||||||
|  | #64           8       r       0        month | ||||||
|  | #72           8       r       0        year | ||||||
|  | #80           4       r       0        rate_select | ||||||
|  | #84           3       r       0        REF_Clock | ||||||
|  | #87           1       r       0        UIP | ||||||
|  | #88           1       r       0        auto_switch_DST | ||||||
|  | #89           1       r       0        24_hour_mode | ||||||
|  | #90           1       r       0        binary_values_enable | ||||||
|  | #91           1       r       0        square-wave_out_enable | ||||||
|  | #92           1       r       0        update_finished_enable | ||||||
|  | #93           1       r       0        alarm_interrupt_enable | ||||||
|  | #94           1       r       0        periodic_interrupt_enable | ||||||
|  | #95           1       r       0        disable_clock_updates | ||||||
|  | #96         288       r       0        temporary_filler | ||||||
|  | 0          384       r       0        reserved_memory | ||||||
|  | 384          1       e       4        boot_option | ||||||
|  | 385          1       e       4        last_boot | ||||||
|  | 386          1       e       1        ECC_memory | ||||||
|  | 388          4       r       0        reboot_bits | ||||||
|  | 392          3       e       5        baud_rate | ||||||
|  | 400          1       e       1        power_on_after_fail | ||||||
|  | 412          4       e       6        debug_level | ||||||
|  | 416          4       e       7        boot_first | ||||||
|  | 420          4       e       7        boot_second | ||||||
|  | 424          4       e       7        boot_third | ||||||
|  | 428          4       h       0        boot_index | ||||||
|  | 432	     8       h       0        boot_countdown | ||||||
|  | 1008         16      h       0        check_sum | ||||||
|  |  | ||||||
|  | enumerations | ||||||
|  |  | ||||||
|  | #ID value   text | ||||||
|  | 1     0     Disable | ||||||
|  | 1     1     Enable | ||||||
|  | 2     0     Enable | ||||||
|  | 2     1     Disable | ||||||
|  | 4     0     Fallback | ||||||
|  | 4     1     Normal | ||||||
|  | 5     0     115200 | ||||||
|  | 5     1     57600 | ||||||
|  | 5     2     38400 | ||||||
|  | 5     3     19200 | ||||||
|  | 5     4     9600 | ||||||
|  | 5     5     4800 | ||||||
|  | 5     6     2400 | ||||||
|  | 5     7     1200 | ||||||
|  | 6     6     Notice | ||||||
|  | 6     7     Info | ||||||
|  | 6     8     Debug | ||||||
|  | 6     9     Spew | ||||||
|  | 7     0     Network | ||||||
|  | 7     1     HDD | ||||||
|  | 7     2     Floppy | ||||||
|  | 7     8     Fallback_Network | ||||||
|  | 7     9     Fallback_HDD | ||||||
|  | 7     10    Fallback_Floppy | ||||||
|  | #7     3     ROM | ||||||
|  |  | ||||||
|  | checksums | ||||||
|  |  | ||||||
|  | checksum 392 1007 1008 | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/mainboard/amd/solo/mainboard.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/mainboard/amd/solo/mainboard.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | #if 0 | ||||||
|  | #include <printk.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | void | ||||||
|  | mainboard_fixup(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | final_mainboard_fixup(void) | ||||||
|  | { | ||||||
|  | #if 0 | ||||||
|  | //	void final_southbridge_fixup(void); | ||||||
|  | //	void final_superio_fixup(void); | ||||||
|  |  | ||||||
|  | 	printk_info("AMD Solo initializing..."); | ||||||
|  |  | ||||||
|  | //	final_southbridge_fixup(); | ||||||
|  |  | ||||||
|  | //#ifndef USE_NEW_SUPERIO_INTERFACE | ||||||
|  | //final_superio_fixup(); | ||||||
|  | //#endif | ||||||
|  | #endif | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/northbridge/amd/amdk8/northbridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/northbridge/amd/amdk8/northbridge.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | #include <arch/io.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <mem.h> | ||||||
|  | #include <part/sizeram.h> | ||||||
|  |  | ||||||
|  | struct mem_range *sizeram(void) | ||||||
|  | { | ||||||
|  | 	static struct mem_range mem[3]; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	/* Convert size in bytes to size in K */ | ||||||
|  | 	/* FIXME  hardcoded for now */ | ||||||
|  | 	size = 512*1024; | ||||||
|  |  | ||||||
|  | 	mem[0].basek = 0; | ||||||
|  | 	mem[0].sizek = 640; | ||||||
|  | 	mem[1].basek = 1024; | ||||||
|  | 	mem[1].sizek = size - mem[1].basek; | ||||||
|  | 	mem[2].basek = 0; | ||||||
|  | 	mem[2].sizek = 0; | ||||||
|  | 	return mem; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										249
									
								
								src/pc80/mc146818rtc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/pc80/mc146818rtc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | |||||||
|  | #include <console/console.h> | ||||||
|  | #include <arch/io.h> | ||||||
|  | #include <pc80/mc146818rtc.h> | ||||||
|  | #include <boot/linuxbios_tables.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #define CMOS_READ(addr) ({ \ | ||||||
|  | outb((addr),RTC_PORT(0)); \ | ||||||
|  | inb(RTC_PORT(1)); \ | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | #define CMOS_WRITE(val, addr) ({ \ | ||||||
|  | outb((addr),RTC_PORT(0)); \ | ||||||
|  | outb((val),RTC_PORT(1)); \ | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | /* control registers - Moto names | ||||||
|  |  */ | ||||||
|  | #define RTC_REG_A		10 | ||||||
|  | #define RTC_REG_B		11 | ||||||
|  | #define RTC_REG_C		12 | ||||||
|  | #define RTC_REG_D		13 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /********************************************************************** | ||||||
|  |  * register details | ||||||
|  |  **********************************************************************/ | ||||||
|  | #define RTC_FREQ_SELECT	RTC_REG_A | ||||||
|  |  | ||||||
|  | /* update-in-progress  - set to "1" 244 microsecs before RTC goes off the bus, | ||||||
|  |  * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, | ||||||
|  |  * totalling to a max high interval of 2.228 ms. | ||||||
|  |  */ | ||||||
|  | # define RTC_UIP		0x80 | ||||||
|  | # define RTC_DIV_CTL		0x70 | ||||||
|  |    /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ | ||||||
|  | #  define RTC_REF_CLCK_4MHZ	0x00 | ||||||
|  | #  define RTC_REF_CLCK_1MHZ	0x10 | ||||||
|  | #  define RTC_REF_CLCK_32KHZ	0x20 | ||||||
|  |    /* 2 values for divider stage reset, others for "testing purposes only" */ | ||||||
|  | #  define RTC_DIV_RESET1	0x60 | ||||||
|  | #  define RTC_DIV_RESET2	0x70 | ||||||
|  |   /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ | ||||||
|  | # define RTC_RATE_SELECT 	0x0F | ||||||
|  | #  define RTC_RATE_NONE		0x00 | ||||||
|  | #  define RTC_RATE_32786HZ	0x01 | ||||||
|  | #  define RTC_RATE_16384HZ	0x02 | ||||||
|  | #  define RTC_RATE_8192HZ	0x03 | ||||||
|  | #  define RTC_RATE_4096HZ	0x04 | ||||||
|  | #  define RTC_RATE_2048HZ	0x05 | ||||||
|  | #  define RTC_RATE_1024HZ	0x06 | ||||||
|  | #  define RTC_RATE_512HZ	0x07 | ||||||
|  | #  define RTC_RATE_256HZ	0x08 | ||||||
|  | #  define RTC_RATE_128HZ	0x09 | ||||||
|  | #  define RTC_RATE_64HZ		0x0a | ||||||
|  | #  define RTC_RATE_32HZ		0x0b | ||||||
|  | #  define RTC_RATE_16HZ		0x0c | ||||||
|  | #  define RTC_RATE_8HZ		0x0d | ||||||
|  | #  define RTC_RATE_4HZ		0x0e | ||||||
|  | #  define RTC_RATE_2HZ		0x0f | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_CONTROL	RTC_REG_B | ||||||
|  | # define RTC_SET 0x80		/* disable updates for clock setting */ | ||||||
|  | # define RTC_PIE 0x40		/* periodic interrupt enable */ | ||||||
|  | # define RTC_AIE 0x20		/* alarm interrupt enable */ | ||||||
|  | # define RTC_UIE 0x10		/* update-finished interrupt enable */ | ||||||
|  | # define RTC_SQWE 0x08		/* enable square-wave output */ | ||||||
|  | # define RTC_DM_BINARY 0x04	/* all time/date values are BCD if clear */ | ||||||
|  | # define RTC_24H 0x02		/* 24 hour mode - else hours bit 7 means pm */ | ||||||
|  | # define RTC_DST_EN 0x01	/* auto switch DST - works f. USA only */ | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_INTR_FLAGS	RTC_REG_C | ||||||
|  | /* caution - cleared by read */ | ||||||
|  | # define RTC_IRQF 0x80		/* any of the following 3 is active */ | ||||||
|  | # define RTC_PF 0x40 | ||||||
|  | # define RTC_AF 0x20 | ||||||
|  | # define RTC_UF 0x10 | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | #define RTC_VALID	RTC_REG_D | ||||||
|  | # define RTC_VRT 0x80		/* valid RAM and time */ | ||||||
|  | /**********************************************************************/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int rtc_checksum_valid(int range_start, int range_end, int cks_loc) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	unsigned sum, old_sum; | ||||||
|  | 	sum = 0; | ||||||
|  | 	for(i = range_start; i <= range_end; i++) { | ||||||
|  | 		sum += CMOS_READ(i); | ||||||
|  | 	} | ||||||
|  | 	sum = (~sum)&0x0ffff; | ||||||
|  | 	old_sum = ((CMOS_READ(cks_loc)<<8) | CMOS_READ(cks_loc+1))&0x0ffff; | ||||||
|  | 	return sum == old_sum; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void rtc_set_checksum(int range_start, int range_end, int cks_loc) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	unsigned sum; | ||||||
|  | 	sum = 0; | ||||||
|  | 	for(i = range_start; i <= range_end; i++) { | ||||||
|  | 		sum += CMOS_READ(i); | ||||||
|  | 	} | ||||||
|  | 	sum = ~(sum & 0x0ffff); | ||||||
|  | 	CMOS_WRITE(((sum >> 8) & 0x0ff), cks_loc); | ||||||
|  | 	CMOS_WRITE(((sum >> 0) & 0x0ff), cks_loc+1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define RTC_CONTROL_DEFAULT (RTC_24H) | ||||||
|  | #define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) | ||||||
|  |  | ||||||
|  | #if 0 /* alpha setup */ | ||||||
|  | #undef RTC_CONTROL_DEFAULT | ||||||
|  | #undef RTC_FREQ_SELECT_DEFAULT | ||||||
|  | #define RTC_CONTROL_DEFAULT (RTC_SQWE | RTC_24H) | ||||||
|  | #define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) | ||||||
|  | #endif | ||||||
|  | void rtc_init(int invalid) | ||||||
|  | { | ||||||
|  | 	unsigned char x; | ||||||
|  | 	int cmos_invalid, checksum_invalid; | ||||||
|  |  | ||||||
|  |   printk_debug("RTC Init\n"); | ||||||
|  | 	/* See if there has been a CMOS power problem. */ | ||||||
|  | 	x = CMOS_READ(RTC_VALID); | ||||||
|  | 	cmos_invalid = !(x & RTC_VRT); | ||||||
|  |  | ||||||
|  | 	/* See if there is a CMOS checksum error */ | ||||||
|  | 	checksum_invalid = !rtc_checksum_valid(PC_CKS_RANGE_START, | ||||||
|  | 			PC_CKS_RANGE_END,PC_CKS_LOC); | ||||||
|  |  | ||||||
|  | 	if (invalid || cmos_invalid || checksum_invalid) { | ||||||
|  | 		int i; | ||||||
|  | 		printk_warning("RTC:%s%s%s zeroing cmos\n", | ||||||
|  | 			invalid?" Clear requested":"",  | ||||||
|  | 			cmos_invalid?" Power Problem":"", | ||||||
|  | 			checksum_invalid?" Checksum invalid":""); | ||||||
|  | #if 0 | ||||||
|  | 		CMOS_WRITE(0, 0x01); | ||||||
|  | 		CMOS_WRITE(0, 0x03); | ||||||
|  | 		CMOS_WRITE(0, 0x05); | ||||||
|  | 		for(i = 10; i < 48; i++) { | ||||||
|  | 			CMOS_WRITE(0, i); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		if (cmos_invalid) { | ||||||
|  | 			/* Now setup a default date of Sat 1 January 2000 */ | ||||||
|  | 			CMOS_WRITE(0, 0x00); /* seconds */ | ||||||
|  | 			CMOS_WRITE(0, 0x02); /* minutes */ | ||||||
|  | 			CMOS_WRITE(1, 0x04); /* hours */ | ||||||
|  | 			CMOS_WRITE(7, 0x06); /* day of week */ | ||||||
|  | 			CMOS_WRITE(1, 0x07); /* day of month */ | ||||||
|  | 			CMOS_WRITE(1, 0x08); /* month */ | ||||||
|  | 			CMOS_WRITE(0, 0x09); /* year */ | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  | 	/* See if there is a LB CMOS checksum error */ | ||||||
|  | 	checksum_invalid = !rtc_checksum_valid(LB_CKS_RANGE_START, | ||||||
|  | 			LB_CKS_RANGE_END,LB_CKS_LOC); | ||||||
|  | 	if(checksum_invalid) | ||||||
|  | 		printk_debug("Invalid CMOS LB checksum\n"); | ||||||
|  |  | ||||||
|  | 	/* Setup the real time clock */ | ||||||
|  | 	CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL); | ||||||
|  | 	/* Setup the frequency it operates at */ | ||||||
|  | 	CMOS_WRITE(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT); | ||||||
|  | 	/* Make certain we have a valid checksum */ | ||||||
|  | 	rtc_set_checksum(PC_CKS_RANGE_START, | ||||||
|  |                         PC_CKS_RANGE_END,PC_CKS_LOC); | ||||||
|  | 	/* Clear any pending interrupts */ | ||||||
|  | 	(void) CMOS_READ(RTC_INTR_FLAGS); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if USE_OPTION_TABLE == 1 | ||||||
|  | /* This routine returns the value of the requested bits | ||||||
|  | 	input bit = bit count from the beginning of the cmos image | ||||||
|  | 	      length = number of bits to include in the value | ||||||
|  | 	      ret = a character pointer to where the value is to be returned | ||||||
|  | 	output the value placed in ret | ||||||
|  | 	      returns 0 = successful, -1 = an error occurred | ||||||
|  | */ | ||||||
|  | static int get_cmos_value(unsigned long bit, unsigned long length, void *vret) | ||||||
|  | { | ||||||
|  | 	unsigned char *ret; | ||||||
|  | 	unsigned long byte,byte_bit; | ||||||
|  | 	unsigned long i; | ||||||
|  | 	unsigned char uchar; | ||||||
|  |  | ||||||
|  | 	/* The table is checked when it is built to ensure all  | ||||||
|  | 		values are valid. */ | ||||||
|  | 	ret = vret; | ||||||
|  | 	byte=bit/8;	/* find the byte where the data starts */ | ||||||
|  | 	byte_bit=bit%8; /* find the bit in the byte where the data starts */ | ||||||
|  | 	if(length<9) {	/* one byte or less */ | ||||||
|  | 		uchar = CMOS_READ(byte); /* load the byte */ | ||||||
|  | 		uchar >>= byte_bit;	/* shift the bits to byte align */ | ||||||
|  | 		/* clear unspecified bits */ | ||||||
|  | 		ret[0] = uchar & ((1 << length) -1); | ||||||
|  | 	} | ||||||
|  | 	else {	/* more that one byte so transfer the whole bytes */ | ||||||
|  | 		for(i=0;length;i++,length-=8,byte++) { | ||||||
|  | 			/* load the byte */ | ||||||
|  | 			ret[i]=CMOS_READ(byte); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int get_option(void *dest, char *name) | ||||||
|  | { | ||||||
|  | 	extern struct cmos_option_table option_table; | ||||||
|  | 	struct cmos_option_table *ct; | ||||||
|  | 	struct cmos_entries *ce; | ||||||
|  | 	size_t namelen; | ||||||
|  | 	int found=0; | ||||||
|  |  | ||||||
|  | 	/* Figure out how long name is */ | ||||||
|  | 	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); | ||||||
|  | 	 | ||||||
|  | 	/* find the requested entry record */ | ||||||
|  | 	ct=&option_table; | ||||||
|  | 	ce=(struct cmos_entries*)((unsigned char *)ct + ct->header_length); | ||||||
|  | 	for(;ce->tag==LB_TAG_OPTION; | ||||||
|  | 		ce=(struct cmos_entries*)((unsigned char *)ce + ce->size)) { | ||||||
|  | 		if (memcmp(ce->name, name, namelen) == 0) { | ||||||
|  | 			found=1; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if(!found) { | ||||||
|  | 		printk_err("ERROR: No cmos option '%s'\n", name); | ||||||
|  | 		return(-2); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if(get_cmos_value(ce->bit, ce->length, dest)) | ||||||
|  | 		return(-3); | ||||||
|  | 	if(!rtc_checksum_valid(LB_CKS_RANGE_START, | ||||||
|  | 			LB_CKS_RANGE_END,LB_CKS_LOC)) | ||||||
|  | 		return(-4); | ||||||
|  | 	return(0); | ||||||
|  | } | ||||||
|  | #endif /* USE_OPTION_TABLE */ | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user