- 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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user