- 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