Lots and Lots of changes. Mainly bugfixes for the supermicro p4dc6,

and a bunch of generic changes.
- Started playing with automatic scanning memory for LinuxBIOS tables.
- Converted the fill_inbuf drivers to stream drivers.  This allows
  for pure data copying operations to be faster, and it allows skipping
  of unneeded data on platforms that support it.
- Added a section .rodata.streams for the stream driver control structures.
  This is preparation for building a bootloader that shares source code
  with LinuxBIOS.
- Added a driver command to NLBConfig.py for objects that should
  always be linked into LinuxBIOS if they are compiled at all.
- Moved the boot_successful logic down into the guts of the
  bootloaders.
- Modified the ip style checksum logic so it isn't specific to uniform
  boot headers...
- Added a function ndelay that uses the RTC (this is i786 specific for now).
- Added a function to delay in seconds for the braindead harddrive
  spinup logic.
- Added a floppy stream driver.
- Added a ide stream driver.
- Broke out the ram initialization for the p4dc6 into multiple c files.
- Stupidly adapted linuxbiosmain and do_inflate to the new stream
  interface.  get_byte is now a slow function call so it might be able
  to use some optimization.
- Updated the ELF bootloader to the new stream interface and adding a
  ELF header scanning function so we can boot off of harddrives and
  not smash their partition tables.
- Removed some bogus unlook ahead code from inflate.c
- Fixed a problem where we did not enable I/O resources on VGA
  compatible chips.  This caused a trident card to lock up the system
  when it's memory mapped resources were enabled.
- Correctly set up nested pci busses.  Before this a pci bus behind a
  pci bus would not get enabled.
- Config changes to the p4dc6
- Added more interrupt sources to the p4dc6 interrupt table
- Converted all of the inbuf drivers to stream drivers.
  All have good conversions except the doc_millenium.
This commit is contained in:
Eric W. Biederman 2001-12-20 04:04:42 +00:00
parent b5516dc586
commit cb232f1e04
38 changed files with 3398 additions and 295 deletions

View file

@ -11,6 +11,7 @@
static struct {
struct uniform_boot_header header;
struct linuxbios_header lb_header;
struct {
struct {
struct ube_memory memory;
@ -27,6 +28,14 @@ static struct {
.env = (unsigned long)&ube_all.env,
.env_bytes = sizeof(ube_all.env),
},
.lb_header = {
.signature = { 'L', 'B', 'I', 'O' },
.header_bytes = sizeof(ube_all.lb_header),
.header_checksum = 0,
.env_bytes = sizeof(ube_all.env),
.env_checksum = 0,
.env_entries = 0,
},
.env = {
.mem = {
.memory = {
@ -65,6 +74,11 @@ void *get_ube_pointer(unsigned long totalram)
ube_all.header.header_checksum = 0;
ube_all.header.header_checksum =
uniform_boot_compute_header_checksum(&ube_all.header);
ube_all.lb_header.env_entries = 1; /* FIXME remove this hardcode.. */
ube_all.lb_header.env_checksum =
compute_checksum(&ube_all.env, sizeof(ube_all.env));
ube_all.lb_header.header_checksum =
compute_checksum(&ube_all.lb_header, sizeof(ube_all.lb_header));
return &ube_all.header;
}

View file

@ -46,6 +46,9 @@ SECTIONS
}
.rodata (.) : {
_rodata = .;
streams = . ;
*(.rodata.streams)
estreams = .;
*(.rodata)
*(.rodata.*)
_erodata = .;

View file

@ -49,7 +49,6 @@ static char rcsid[] = "$Id$";
#include <part/floppy.h>
#include <part/sizeram.h>
#include <part/hard_reset.h>
#include <part/fallback_boot.h>
#include <arch/ioapic.h>
#include <pc80/i8259.h>
#include <pc80/keyboard.h>
@ -290,9 +289,6 @@ void hardwaremain(int boot_complete)
post_code(0x96);
write_smp_table((void *)16, processor_map);
/* Reset to booting from this image as late as possible */
boot_successful();
#ifdef LINUXBIOS
printk_info("Jumping to linuxbiosmain()...\n");
// we could go to argc, argv, for main but it seems like overkill.

View file

@ -16,7 +16,7 @@ makerule ldoptions : Makefile.settings ; perl -e 'foreach $$var (split(" ", $$EN
makerule linuxbios.strip: linuxbios ; objcopy -O binary linuxbios linuxbios.strip
makerule linuxbios.o : crt0.o linuxbios.a $(LIBGCC_FILE_NAME) ; $(CC) -nostdlib -r -o $@ crt0.o linuxbios.a $(LIBGCC_FILE_NAME)
makerule linuxbios.o : crt0.o $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME) ; $(CC) -nostdlib -r -o $@ crt0.o $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME)
makerule linuxbios: linuxbios.o ldscript.ld ; $(CC) -nostdlib -nostartfiles -static -o $@ -T ldscript.ld linuxbios.o

View file

@ -1 +1,3 @@
option i786
object delay_i786.o

18
src/cpu/i786/delay_i786.c Normal file
View file

@ -0,0 +1,18 @@
#include <cpu/p6/msr.h>
void ndelay(unsigned long ns)
{
unsigned long long count;
unsigned long long stop;
unsigned long long ticks;
/* FIXME calibrate this... don't just estimage 2Ghz */
ticks = ns << 1;
rdtscll(count);
stop = ticks + count;
while(stop > count) {
rdtscll(count);
}
}

View file

@ -3,5 +3,6 @@
void udelay(int usecs);
void mdelay(int msecs);
void delay(int secs);
#endif /* DELAY_H */

View file

@ -0,0 +1,9 @@
#ifndef FLOPPY_SUBR_H
#define FLOPPY_SUBR_H
int floppy_init(void);
int floppy_read(char *dest, unsigned long offset, unsigned long length);
void floppy_fini(void);
#endif /* FLOPPY_SUBR_H */

View file

@ -0,0 +1,15 @@
void display_rdram_regs(int);
void display_spd_dev_row_col_bank(u8*, u8*, u8*);
void display_rdram_regs_tparm(int);
void display_smbus_spd(void);
void display_mch_regs(void);
void init_memory(void);
struct rdram_reg_values {
u16 channel_a;
u16 channel_b;
};
void rdram_read_reg(u8, u16, u16, struct rdram_reg_values*);

View file

@ -0,0 +1,21 @@
#ifndef ROM_READ_BYTES_H
#define ROM_READ_BYTES_H
#include <stdint.h>
typedef long byte_offset_t;
struct stream {
int (*init)(void);
byte_offset_t (*read)(void *vdest, byte_offset_t count);
byte_offset_t (*skip)(byte_offset_t count);
void (*fini)(void);
};
#define __stream __attribute__ ((unused,__section__ (".rodata.streams")))
/* Defined by the linker... */
extern struct stream streams[];
extern struct stream estreams[];
#endif /* ROM_READ_BYTES_H */

View file

@ -13,5 +13,6 @@ object memcmp.o
object malloc.o
object elfboot.o
object do_inflate.o
object floppy_subr.o
object delay.o
object fallback_boot.o USE_FALLBACK_BOOT

View file

@ -61,3 +61,10 @@ void mdelay(int msecs)
udelay(1000);
}
}
void delay(int secs)
{
int i;
for(i = 0; i < secs; i++) {
mdelay(1000);
}
}

View file

@ -1,7 +1,7 @@
#include <printk.h>
#include <string.h>
#include <stdlib.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <subr.h>
#include "definitions.h"
#include "do_inflate.h"
@ -24,6 +24,16 @@ static unsigned char window[WSIZE]; /* Sliding window buffer */
static unsigned char *window; /* Sliding window buffer */
#endif
static unsigned char get_byte(void)
{
unsigned char result;
if (streams->read(&result, 1) != 1) {
printk_err("Unexpected! Out of bytes...\n");
while(1) ;
}
return result;
}
/*
* gzip declarations

View file

@ -1,10 +1,13 @@
#if USE_ELF_BOOT
#include <printk.h>
#include <part/fallback_boot.h>
#include <boot/elf.h>
#include <boot/uniform_boot.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <string.h>
#include <subr.h>
#include <stdint.h>
extern unsigned char _text;
extern unsigned char _etext;
@ -60,37 +63,55 @@ int elfboot(size_t totalram)
unsigned long offset;
Elf_ehdr *ehdr;
Elf_phdr *phdr;
int header_offset;
void *ptr, *entry;
int i;
printk_info("\n");
printk_info("Welcome to elfboot, the open sourced starter.\n");
printk_info("Febuary 2001, Eric Biederman.\n");
printk_info("Version 0.99\n");
printk_info("Version 0.9999\n");
printk_info("\n");
if (streams->init() < 0) {
printk_err("Could not initialize driver...\n");
goto out;
}
ptr = get_ube_pointer(totalram);
post_code(0xf8);
/* Read in the initial 512 bytes */
for(offset = 0; offset < 512; offset++) {
header[offset] = get_byte();
}
ehdr = (Elf_ehdr *)(&header[0]);
entry = (void *)(ehdr->e_entry);
/* Sanity check the elf header */
if ((memcmp(ehdr->e_ident, ELFMAG, 4) != 0) ||
(ehdr->e_type != ET_EXEC) ||
(!elf_check_arch(ehdr)) ||
(ehdr->e_ident[EI_VERSION] != EV_CURRENT) ||
(ehdr->e_version != EV_CURRENT) ||
(ehdr->e_phoff > ELF_HEAD_SIZE) ||
(ehdr->e_phentsize != sizeof(Elf_phdr)) ||
((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) >
ELF_HEAD_SIZE)) {
/* Read in the initial ELF_HEAD_SIZE bytes */
if (streams->read(header, ELF_HEAD_SIZE) != ELF_HEAD_SIZE) {
printk_err("Read failed...\n");
goto out;
}
phdr = (Elf_phdr *)&header[ehdr->e_phoff];
/* Scan for an elf header */
header_offset = -1;
for(i = 0; i < ELF_HEAD_SIZE - (sizeof(Elf_ehdr) + sizeof(Elf_phdr)); i+=16) {
ehdr = (Elf_ehdr *)(&header[i]);
if (memcmp(ehdr->e_ident, ELFMAG, 4) != 0) {
continue;
}
printk_debug("Found ELF candiate at offset %d\n", i);
/* Sanity check the elf header */
if ((ehdr->e_type == ET_EXEC) &&
elf_check_arch(ehdr) &&
(ehdr->e_ident[EI_VERSION] == EV_CURRENT) &&
(ehdr->e_version == EV_CURRENT) &&
(ehdr->e_ehsize == sizeof(Elf_ehdr)) &&
(ehdr->e_phentsize = sizeof(Elf_phdr)) &&
(ehdr->e_phoff < (ELF_HEAD_SIZE - i)) &&
((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) <=
(ELF_HEAD_SIZE - i))) {
header_offset = i;
break;
}
ehdr = 0;
}
if (header_offset == -1) {
goto out;
}
entry = (void *)(ehdr->e_entry);
phdr = (Elf_phdr *)&header[ehdr->e_phoff + header_offset];
/* Sanity check the segments and zero the extra bytes */
for(i = 0; i < ehdr->e_phnum; i++) {
@ -115,7 +136,6 @@ int elfboot(size_t totalram)
}
}
}
offset = 0;
while(1) {
@ -143,6 +163,7 @@ int elfboot(size_t totalram)
}
}
}
/* If we are out of sections we are done */
if (!cur_phdr) {
break;
@ -161,22 +182,23 @@ int elfboot(size_t totalram)
start_offset = cur_phdr->p_offset;
/* Skip intial buffer unused bytes */
if (offset < ELF_HEAD_SIZE) {
if (start_offset < ELF_HEAD_SIZE) {
if (offset < (ELF_HEAD_SIZE - header_offset)) {
if (start_offset < (ELF_HEAD_SIZE - header_offset)) {
offset = start_offset;
} else {
offset = ELF_HEAD_SIZE;
offset = (ELF_HEAD_SIZE - header_offset);
}
}
/* Skip the unused bytes */
while(offset < start_offset) {
offset++;
get_byte();
if (streams->skip(start_offset - offset) != (start_offset - offset)) {
printk_err("skip failed\n");
goto out;
}
offset = start_offset;
/* Copy data from the initial buffer */
if (offset < ELF_HEAD_SIZE) {
if (offset < (ELF_HEAD_SIZE - header_offset)) {
size_t len;
if ((cur_phdr->p_filesz + start_offset) > ELF_HEAD_SIZE) {
len = ELF_HEAD_SIZE - start_offset;
@ -184,18 +206,24 @@ int elfboot(size_t totalram)
else {
len = cur_phdr->p_filesz;
}
memcpy(dest, &header[start_offset], len);
memcpy(dest, &header[header_offset + start_offset], len);
dest += len;
}
/* Read the section into memory */
while(dest < middle) {
*(dest++) = get_byte();
if (streams->read(dest, middle - dest) != (middle - dest)) {
printk_err("Read failed...\n");
goto out;
}
offset += cur_phdr->p_filesz;
/* The extra bytes between dest & end have been zeroed */
}
/* Reset to booting from this image as late as possible */
streams->fini();
boot_successful();
printk_debug("Jumping to boot code\n");
post_code(0xfe);
@ -212,6 +240,12 @@ int elfboot(size_t totalram)
}
printk_err("\n");
/* Reset to booting from this image as late as possible */
streams->fini();
#if 0
boot_successful();
#endif
return 0;
}
#endif /* USE_ELF_BOOT */

1038
src/lib/floppy_subr.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -986,14 +986,6 @@ STATIC int inflate()
h = hufts;
} while (!e);
/* Undo too much lookahead. The next read will be byte aligned so we
* can discard unused bits in the last meaningful byte.
*/
while (bk >= 8) {
bk -= 8;
inptr--;
}
/* flush out slide */
flush_output(wp);

View file

@ -18,9 +18,10 @@
*/
#include <printk.h>
#include <part/fallback_boot.h>
#include <params.h>
#include <subr.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <string.h>
#include <stdlib.h>
@ -92,6 +93,7 @@ int linuxbiosmain(unsigned long base, unsigned long totalram)
printk_notice("\nnetboot_init test complete, all is well (I hope!)\n");
#endif /* USE_TFTP */
streams->init();
printk_debug("Gunzip setup\n");
gunzip_setup();
printk_debug("Gunzipping boot code\n");
@ -100,6 +102,7 @@ int linuxbiosmain(unsigned long base, unsigned long totalram)
post_code(0xff);
return 0;
}
streams->fini();
post_code(0xf8);
#ifdef TFTP_INITRD
@ -156,6 +159,8 @@ int linuxbiosmain(unsigned long base, unsigned long totalram)
set_display(empty_zero_page, 25, 80);
set_initrd(empty_zero_page, initrd_start, initrd_size);
/* Reset to booting from this image as late as possible */
boot_successful();
printk_debug("Jumping to boot code\n");
post_code(0xfe);

View file

@ -461,8 +461,20 @@ void compute_allocate_io(struct pci_bus *bus)
curbus->number, io_base);
}
/* Walk through all the devices on current bus and oompute IO address space.*/
/* Walk through all the devices on current bus and compute IO address space.*/
for (curdev = bus->devices; curdev; curdev = curdev->sibling) {
u32 class_revision;
/* FIXME Special case for VGA for now just note
* we have an I/O resource later make certain
* we don't have a device conflict.
*/
pci_read_config_dword(curdev, PCI_CLASS_REVISION, &class_revision);
if (((class_revision >> 24) == 0x03) &&
((class_revision >> 16) != 0x380)) {
printk_debug("Running VGA fix...\n");
/* All legacy VGA cards have I/O space registers */
curdev->command |= PCI_COMMAND_IO;
}
for (i = 0; i < 6; i++) {
unsigned long size = curdev->size[i];
if (size & PCI_BASE_ADDRESS_SPACE_IO) {
@ -690,8 +702,8 @@ void assign_resources(struct pci_bus *bus)
curbus->iobase >> 8);
pci_write_config_byte(curbus->self, PCI_IO_LIMIT,
curbus->iolimit >> 8);
printk_debug("Bus 0x%x iobase to 0x%x iolimit 0x%x\n",
bus->number, curbus->iobase, curbus->iolimit);
printk_debug("Bus 0x%x Child Bus %x iobase to 0x%x iolimit 0x%x\n",
bus->number,curbus->number, curbus->iobase, curbus->iolimit);
}
// set the memory range
@ -701,8 +713,8 @@ void assign_resources(struct pci_bus *bus)
curbus->membase >> 16);
pci_write_config_word(curbus->self, PCI_MEMORY_LIMIT,
curbus->memlimit >> 16);
printk_debug("Bus 0x%x membase to 0x%x memlimit 0x%x\n",
bus->number, curbus->membase, curbus->memlimit);
printk_debug("Bus 0x%x Child Bus %x membase to 0x%x memlimit 0x%x\n",
bus->number,curbus->number, curbus->membase, curbus->memlimit);
}
@ -713,15 +725,16 @@ void assign_resources(struct pci_bus *bus)
curbus->prefmembase >> 16);
pci_write_config_word(curbus->self, PCI_PREF_MEMORY_LIMIT,
curbus->prefmemlimit >> 16);
printk_debug("Bus 0x%x prefmembase to 0x%x prefmemlimit 0x%x\n",
bus->number, curbus->prefmembase, curbus->prefmemlimit);
printk_debug("Bus 0x%x Child Bus %x prefmembase to 0x%x prefmemlimit 0x%x\n",
bus->number,curbus->number, curbus->prefmembase,
curbus->prefmemlimit);
}
curbus->self->command |= PCI_COMMAND_MASTER;
assign_resources(curbus);
}
for (curdev = pci_devices; curdev; curdev = curdev->next) {
for (curdev = bus->devices; curdev; curdev = curdev->sibling) {
int i;
for (i = 0; i < 6; i++) {
unsigned long reg;

View file

@ -16,6 +16,9 @@ nooption USE_DEFAULT_LAYOUT
option STACK_SIZE=0x2000
option USE_FALLBACK_BOOT=1
option USE_RAMTEST=1
dir /src/ram
#/* falback */
option ZKERNEL_START=0xffff0000
option _ROMBASE= 0xffff8000
@ -57,7 +60,7 @@ option NO_KEYBOARD
option ENABLE_FIXED_AND_VARIABLE_MTRRS
#option FINAL_MAINBOARD_FIXUP
object cacheramtest.o
#object cacheramtest.o
object mainboard.o
object mtrr_values.o
object mptable.o HAVE_MP_TABLE

View file

@ -8,6 +8,16 @@
#include <pc80/isa_dma.h>
#include <cpu/i786/multiplier.h>
#include <superio/w83627hf.h>
#include <superio/generic.h>
#include <subr.h>
#include <smbus.h>
#include <ramtest.h>
#include <northbridge/intel/82860/rdram.h>
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
extern int rdram_chips; /* number of ram chips on the rimms */
unsigned long initial_apicid[MAX_CPUS] =
{
@ -38,3 +48,92 @@ void hard_reset(void)
ich2_hard_reset();
}
static void select_rdram_i2c(void)
{
unsigned char byte;
w83627hf_enter_pnp(SIO_BASE);
byte = pnp_read_config(SIO_BASE, 0x2b);
byte |= 0x30;
pnp_write_config(SIO_BASE, byte, 0x2b);
pnp_set_logical_device(SIO_BASE, GPIO_PORT2_DEVICE);
pnp_set_enable(SIO_BASE, 1);
byte = pnp_read_config(SIO_BASE, 0xf0);
byte &= ~(1 << 3);
pnp_write_config(SIO_BASE, byte, 0xf0);
w83627hf_exit_pnp(SIO_BASE);
}
void cache_ram_start(void)
{
int error;
error = 0;
/* displayinit MUST PRECEDE ALL PRINTK! */
displayinit();
printk_info("printk: Testing %d %s\n", 123, "testing!!!");
printk_info("Finding PCI configuration type.\n");
pci_set_method();
printk_info("Setting up smbus controller\n");
smbus_setup();
ich2_rtc_init();
printk_info("Selecting rdram i2c bus\n");
select_rdram_i2c();
display_smbus_spd();
init_memory();
#if 1
{
unsigned long addr;
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_fill(addr, addr + 0x400);
}
/* Do some dummy writes to flush a write cache, in the
* processor.
*/
ram_fill(0xc0000000, 0xc0000400);
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_verify(addr, addr + 0x400, 1);
}
}
#endif
error |= ramcheck(0x00000000, 0x00080000, 20);
error |= ramcheck(0x02000000, 0x02080000, 20);
error |= ramcheck(0x04000000, 0x04080000, 20);
error |= ramcheck(0x06000000, 0x06080000, 20);
error |= ramcheck(0x08000000, 0x08080000, 20);
error |= ramcheck(0x0a000000, 0x0a080000, 20);
error |= ramcheck(0x0c000000, 0x0c080000, 20);
error |= ramcheck(0x0e000000, 0x0e080000, 20);
error |= ramcheck(0x10000000, 0x10080000, 20);
error |= ramcheck(0x12000000, 0x12080000, 20);
error |= ramcheck(0x14000000, 0x14080000, 20);
error |= ramcheck(0x16000000, 0x16080000, 20);
error |= ramcheck(0x18000000, 0x18080000, 20);
error |= ramcheck(0x1a000000, 0x1a080000, 20);
error |= ramcheck(0x1c000000, 0x1c080000, 20);
error |= ramcheck(0x1e000000, 0x1e080000, 20);
#if 0
error |= ramcheck(0x00000000, 0x00080000, 20);
#endif
#if 1
display_rdram_regs(rdram_chips );
#endif
#if 1
display_mch_regs();
#endif
if (error) {
printk_err("Something isn't working!!!\n");
while(1);
} else {
printk_info("Leaving cacheram...\n");
}
}

View file

@ -55,6 +55,34 @@ void smp_write_config_table(void *v, unsigned long * processor_map)
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (4 <<2)|0, 0x02, 0x10);
/* Four standard PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (7 <<2)|0, 0x02, 0x10);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (1 <<2)|0, 0x02, 0x11);
/* Slot 3 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (2 <<2)|0, 0x02, 0x12);
/* Slot 4 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (3 <<2)|0, 0x02, 0x13);
/* Two 64 bit PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (1 <<2)|0, 0x02, 0x12);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (2 <<2)|0, 0x02, 0x12);
/* Two SCSI */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|0, 0x02, 0x12);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|1, 0x02, 0x12);
/* ISA backward compatibility interrupts */
smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x00, 0x02, 0x00);
@ -66,6 +94,8 @@ void smp_write_config_table(void *v, unsigned long * processor_map)
0x05, 0x03, 0x02, 0x03);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x04, 0x02, 0x04);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x05, 0x02, 0x05);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x06, 0x02, 0x06);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,

View file

@ -2,3 +2,5 @@ mainboardinit arch/i386/lib/set_memory_size_noop.inc
mainboardinit arch/i386/lib/cpu_reset.inc
object northbridge.o
object rdram_setup.o
object rdram_debug.o

View file

@ -0,0 +1,301 @@
#include <printk.h>
#include <stdarg.h>
#include <types.h>
#include <string.h>
#include <subr.h>
#include <serial_subr.h>
#include <pci.h>
#include <arch/io.h>
#include <cpu/p6/msr.h>
#include <cpu/p6/mtrr.h>
#include <arch/cache_ram.h>
#include <smbus.h>
#include <ramtest.h>
#include <southbridge/intel/82801.h>
#include <superio/generic.h>
#include <superio/w83627hf.h>
#include <northbridge/intel/82860/rdram.h>
#define LPC_BUS 0
#define LPC_DEVFN ((0x1f << 3) + 0)
#define ICH2HUB_BUS 0
#define ICH2HUB_DEVFN ((0x1e << 3) + 0)
#define I860MCH_BUS 0
#define I860MCH_DEVFN ((0x00 << 3) + 0)
#define I860HUBA_BUS 0
#define I860HUBA_DEVFN ((0x01 << 3) + 0)
#define I860HUBB_BUS 0
#define I860HUBB_DEVFN ((0x02 << 3) + 0)
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
#define TSCYCLE_SLOW 1000 /* ns */
#define TSCYCLE_FAST 10 /* ns */
#define I860_MCH_BUS 0
#define I860_MCH_DEVFN 0
#define MCH_GAR0 0x40
#define MCH_GAR1 0x41
#define MCH_GAR2 0x42
#define MCH_GAR3 0x43
#define MCH_GAR4 0x44
#define MCH_GAR5 0x45
#define MCH_GAR6 0x46
#define MCH_GAR7 0x47
#define MCH_GAR8 0x48
#define MCH_GAR9 0x49
#define MCH_GAR10 0x4a
#define MCH_GAR11 0x4b
#define MCH_GAR12 0x4c
#define MCH_GAR13 0x4d
#define MCH_GAR14 0x4e
#define MCH_GAR15 0x4f
#define MCH_MCHCFG 0x50
#define MCH_FDHC 0x58
#define MCH_PAM0 0x59
#define MCH_PAM1 0x5a
#define MCH_PAM2 0x5b
#define MCH_PAM3 0x5c
#define MCH_PAM4 0x5d
#define MCH_PAM5 0x5e
#define MCH_PAM6 0x5f
#define MCH_GBA0 0x60
#define MCH_GBA1 0x62
#define MCH_GBA2 0x64
#define MCH_GBA3 0x66
#define MCH_GBA4 0x68
#define MCH_GBA5 0x6a
#define MCH_GBA6 0x6c
#define MCH_GBA7 0x6e
#define MCH_GBA8 0x70
#define MCH_GBA9 0x72
#define MCH_GBA10 0x74
#define MCH_GBA11 0x76
#define MCH_GBA12 0x78
#define MCH_GBA13 0x7a
#define MCH_GBA14 0x7c
#define MCH_GBA15 0x7e
#define MCH_RDPS 0x88
#define MCH_DRD 0x90
#define MCH_RICM 0x94
#define MCH_SMRAM 0x9d
#define MCH_ESMRAM 0x9e
#define MCH_RDT 0xbe
#define MCH_TOM 0xc4
#define MCH_ERRSTS 0xc8
#define MCH_ERRCMD 0xca
#define MCH_SMICMD 0xcc
#define MCH_SCICMD 0xce
#define MCH_DRAMRC 0xdc
#define MCH_DERRCTL 0xe2
#define MCH_EAP 0xe4
#define RICM_BUSY (1 << 23)
#define RICM_DONE (1 << 27)
#define __S(NAME) NAME##_SHIFT
#define __B(NAME) NAME##_BITS
#define __BIT_MASK(SHIFT, BITS) ((1 << (BITS + SHIFT)) - (1 << (SHIFT)))
#define MASK(NAME) __BIT_MASK(__S(NAME), __B(NAME))
#define NVAL(NAME, VAL) (MASK(NAME) & ((VAL) << __S(NAME)))
#define VAL(NAME, VALUE) ((MASK(NAME) & VALUE) >> __S(NAME))
#define RICM_CMD_SHIFT 0
#define RICM_CMD_BITS 5
#define RICM_ADDR_SHIFT 5
#define RICM_ADDR_BITS 5
#define RICM_REG_SHIFT 10
#define RICM_REG_BITS 9
#define RICM_BROADCAST_SHIFT 19
#define RICM_BROADCAST_BITS 1
#define RICM_CHANNEL_SHIFT 20
#define RICM_CHANNEL_BITS 2
#define CMD_RDRAM_READ_REG 0
#define CMD_RDRAM_WRITE_REG 1
#define CMD_RDRAM_SET_RESET 2
#define CMD_SET_FAST_CLK 4
#define CMD_TEMP_CALIBRATE_ENABLE 5
#define CMD_TEMP_CALIBRATE 6
#define CMD_MRH_REDIRECT_NEXT_SIO 8
#define CMD_MRH_STICK_SIO_RESET 9
#define CMD_RDRAM_CLEAR_RESET 11
#define CMD_RDRAM_CURRENT_CALIBRATION 16
#define CMD_RDRAM_SIO_RESET 17
#define CMD_RDRAM_POWERDOWN_EXIT 18
#define CMD_RDRAM_POWERDOWN_ENTRY 19
#define CMD_RDRAM_NAP_ENTRY 20
#define CMD_RDRAM_NAP_EXIT 21
#define CMD_RDRAM_REFRESH 22
#define CMD_RDRAM_PRECHARGE 23
#define CMD_MANUAL_CURRENT_CALIBRATION 24
#define CMD_MCH_RAC_LOAD_RACA_CONFIG 25
#define CMD_MCH_RAC_LOAD_RACB_CONFIG 26
#define CMD_MCH_INITIALIZE_RAC 27
#define CMD_MCH_RAC_CURRENT_CALIBRATION 28
#define CMD_MCH_RAC_TEMP_CALIBRATE 29
#define CMD_POWERUP_ALL_SEQUENCE 31
#define REG_INIT 0x21
#define REG_TEST34 0x22
#define REG_CNFGA 0x23
#define REG_CNFGB 0x24
#define REG_DEVID 0x40
#define REG_REFB 0x41
#define REG_REFR 0x42
#define REG_CCA 0x43
#define REG_CCB 0x44
#define REG_NAPX 0x45
#define REG_PDNXA 0x46
#define REG_PDNX 0x47
#define REG_TPARM 0x48
#define REG_TFRM 0x49
#define REG_TCDLY1 0x4a
#define REG_SKIP 0x4b
#define REG_TCYCLE 0x4c
#define REG_TEST77 0x4d
#define REG_TEST78 0x4e
#define REG_TEST79 0x4f
#define BCAST 0xffff
//int rdram_chips=0; /* number of ram chips on the rimms */
//static u32 total_rdram; /* Total rdram found */
u16 rdram_regs[] = {
REG_INIT,
REG_TEST34,
REG_CNFGA,
REG_CNFGB,
REG_DEVID,
REG_REFB,
REG_REFR,
REG_CCA,
REG_CCB,
REG_NAPX,
REG_PDNXA,
REG_PDNX,
REG_TPARM,
REG_TFRM,
REG_TCDLY1,
REG_SKIP,
REG_TCYCLE,
REG_TEST77,
REG_TEST78,
REG_TEST79,
};
char *rdram_reg_names[] = {
"INIT",
"TEST34",
"CNFGA",
"CNFGB",
"DEVID",
"REFB",
"REFR",
"CCA",
"CCB",
"NAPX",
"PDNXA",
"PDNX",
"TPARM",
"TFRM",
"TCDLY1",
"SKIP",
"TCYCLE",
"TEST77",
"TEST78",
"TEST79",
};
void display_spd_dev_row_col_bank(u8 *spd_devices, u8 *spd_row_col, u8 *spd_banks)
{
int i;
for(i=0;i<4;i++)
printk_debug("Devices %d, Row Bits %d, Col Bits %d, Bank Bits %d\n",
spd_devices[i],(spd_row_col[i]>>4),(spd_row_col[i]&0x0f),spd_banks[i]);
}
void display_rdram_regs_tparm(int rdram_chips)
{
int i,j;
for(i = 0; i < rdram_chips; i++) {
for(j = 12; j < 15; j+=2) {
struct rdram_reg_values values;
u16 reg = rdram_regs[j];
rdram_read_reg(0, i, reg, &values);
printk_debug("rdram: %2d reg: %02x %10s a: 0x%04x b: 0x%04x\n",
i, reg, rdram_reg_names[j], values.channel_a, values.channel_b); }
}
}
void display_rdram_regs(int rdram_chips )
{
int i,j;
for(i = 0; i < rdram_chips; i++) {
for(j = 0; j < sizeof(rdram_regs)/sizeof(rdram_regs[0]); j++) {
struct rdram_reg_values values;
u16 reg = rdram_regs[j];
rdram_read_reg(0, i, reg, &values);
printk_debug("rdram: %2d reg: %02x %10s a: 0x%04x b: 0x%04x\n",
i, reg, rdram_reg_names[j], values.channel_a, values.channel_b);
}
}
}
void display_smbus_spd(void)
{
int i,j;
for(j = SMBUS_MEM_DEVICE_0; j < SMBUS_MEM_DEVICE_0 + 4; j++) {
int status = 0;
if ((j == 0x1b) || 0) {
printk_debug("skipping device: %02x\n", j);
continue;
}
printk_debug("smbus_device: %02x\n", j);
for(i = 0; (i < 128) && (status == 0); i++) {
unsigned char byte;
status = smbus_read_byte(j, i, &byte);
if (status != 0) {
printk_debug("bad device\n");
continue;
}
printk_debug("0x%02x ", byte);
if ((i &0x0f) == 0x0f) {
printk_debug("\n");
}
}
}
printk_debug("\n");
}
void display_mch_regs(void)
{
int i,j;
printk_debug("MCH Register Dump\n");
for(i = 0; i < 16; i++) {
printk_debug("%02x: ", i << 4);
for(j = 0; j < 16; j++) {
u8 byte;
u8 addr = (i << 4) | j;
pcibios_read_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, addr, &byte);
printk_debug("%02x ", byte);
}
printk_debug("\n");
}
}

View file

@ -0,0 +1,866 @@
#include <printk.h>
#include <stdarg.h>
#include <types.h>
#include <string.h>
#include <subr.h>
#include <serial_subr.h>
#include <pci.h>
#include <arch/io.h>
#include <cpu/p6/msr.h>
#include <cpu/p6/mtrr.h>
#include <arch/cache_ram.h>
#include <smbus.h>
#include <ramtest.h>
#include <southbridge/intel/82801.h>
#include <superio/generic.h>
#include <superio/w83627hf.h>
#include <northbridge/intel/82860/rdram.h>
#define LPC_BUS 0
#define LPC_DEVFN ((0x1f << 3) + 0)
#define ICH2HUB_BUS 0
#define ICH2HUB_DEVFN ((0x1e << 3) + 0)
#define I860MCH_BUS 0
#define I860MCH_DEVFN ((0x00 << 3) + 0)
#define I860HUBA_BUS 0
#define I860HUBA_DEVFN ((0x01 << 3) + 0)
#define I860HUBB_BUS 0
#define I860HUBB_DEVFN ((0x02 << 3) + 0)
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
#define TSCYCLE_SLOW 1000 /* ns */
#define TSCYCLE_FAST 10 /* ns */
void ndelay(unsigned long);
#define I860_MCH_BUS 0
#define I860_MCH_DEVFN 0
#define MCH_GAR0 0x40
#define MCH_GAR1 0x41
#define MCH_GAR2 0x42
#define MCH_GAR3 0x43
#define MCH_GAR4 0x44
#define MCH_GAR5 0x45
#define MCH_GAR6 0x46
#define MCH_GAR7 0x47
#define MCH_GAR8 0x48
#define MCH_GAR9 0x49
#define MCH_GAR10 0x4a
#define MCH_GAR11 0x4b
#define MCH_GAR12 0x4c
#define MCH_GAR13 0x4d
#define MCH_GAR14 0x4e
#define MCH_GAR15 0x4f
#define MCH_MCHCFG 0x50
#define MCH_FDHC 0x58
#define MCH_PAM0 0x59
#define MCH_PAM1 0x5a
#define MCH_PAM2 0x5b
#define MCH_PAM3 0x5c
#define MCH_PAM4 0x5d
#define MCH_PAM5 0x5e
#define MCH_PAM6 0x5f
#define MCH_GBA0 0x60
#define MCH_GBA1 0x62
#define MCH_GBA2 0x64
#define MCH_GBA3 0x66
#define MCH_GBA4 0x68
#define MCH_GBA5 0x6a
#define MCH_GBA6 0x6c
#define MCH_GBA7 0x6e
#define MCH_GBA8 0x70
#define MCH_GBA9 0x72
#define MCH_GBA10 0x74
#define MCH_GBA11 0x76
#define MCH_GBA12 0x78
#define MCH_GBA13 0x7a
#define MCH_GBA14 0x7c
#define MCH_GBA15 0x7e
#define MCH_RDPS 0x88
#define MCH_DRD 0x90
#define MCH_RICM 0x94
#define MCH_SMRAM 0x9d
#define MCH_ESMRAM 0x9e
#define MCH_RDT 0xbe
#define MCH_TOM 0xc4
#define MCH_ERRSTS 0xc8
#define MCH_ERRCMD 0xca
#define MCH_SMICMD 0xcc
#define MCH_SCICMD 0xce
#define MCH_DRAMRC 0xdc
#define MCH_DERRCTL 0xe2
#define MCH_EAP 0xe4
#define RICM_BUSY (1 << 23)
#define RICM_DONE (1 << 27)
#define __S(NAME) NAME##_SHIFT
#define __B(NAME) NAME##_BITS
#define __BIT_MASK(SHIFT, BITS) ((1 << (BITS + SHIFT)) - (1 << (SHIFT)))
#define MASK(NAME) __BIT_MASK(__S(NAME), __B(NAME))
#define NVAL(NAME, VAL) (MASK(NAME) & ((VAL) << __S(NAME)))
#define VAL(NAME, VALUE) ((MASK(NAME) & VALUE) >> __S(NAME))
#define RICM_CMD_SHIFT 0
#define RICM_CMD_BITS 5
#define RICM_ADDR_SHIFT 5
#define RICM_ADDR_BITS 5
#define RICM_REG_SHIFT 10
#define RICM_REG_BITS 9
#define RICM_BROADCAST_SHIFT 19
#define RICM_BROADCAST_BITS 1
#define RICM_CHANNEL_SHIFT 20
#define RICM_CHANNEL_BITS 2
#define CMD_RDRAM_READ_REG 0
#define CMD_RDRAM_WRITE_REG 1
#define CMD_RDRAM_SET_RESET 2
#define CMD_SET_FAST_CLK 4
#define CMD_TEMP_CALIBRATE_ENABLE 5
#define CMD_TEMP_CALIBRATE 6
#define CMD_MRH_REDIRECT_NEXT_SIO 8
#define CMD_MRH_STICK_SIO_RESET 9
#define CMD_RDRAM_CLEAR_RESET 11
#define CMD_RDRAM_CURRENT_CALIBRATION 16
#define CMD_RDRAM_SIO_RESET 17
#define CMD_RDRAM_POWERDOWN_EXIT 18
#define CMD_RDRAM_POWERDOWN_ENTRY 19
#define CMD_RDRAM_NAP_ENTRY 20
#define CMD_RDRAM_NAP_EXIT 21
#define CMD_RDRAM_REFRESH 22
#define CMD_RDRAM_PRECHARGE 23
#define CMD_MANUAL_CURRENT_CALIBRATION 24
#define CMD_MCH_RAC_LOAD_RACA_CONFIG 25
#define CMD_MCH_RAC_LOAD_RACB_CONFIG 26
#define CMD_MCH_INITIALIZE_RAC 27
#define CMD_MCH_RAC_CURRENT_CALIBRATION 28
#define CMD_MCH_RAC_TEMP_CALIBRATE 29
#define CMD_POWERUP_ALL_SEQUENCE 31
#define REG_INIT 0x21
#define REG_TEST34 0x22
#define REG_CNFGA 0x23
#define REG_CNFGB 0x24
#define REG_DEVID 0x40
#define REG_REFB 0x41
#define REG_REFR 0x42
#define REG_CCA 0x43
#define REG_CCB 0x44
#define REG_NAPX 0x45
#define REG_PDNXA 0x46
#define REG_PDNX 0x47
#define REG_TPARM 0x48
#define REG_TFRM 0x49
#define REG_TCDLY1 0x4a
#define REG_SKIP 0x4b
#define REG_TCYCLE 0x4c
#define REG_TEST77 0x4d
#define REG_TEST78 0x4e
#define REG_TEST79 0x4f
#define BCAST 0xffff
static void rdram_wait_until_ready(void)
{
u32 ricm;
do {
pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, &ricm);
} while(ricm & RICM_BUSY);
ndelay(1000); /* delay after ready because the documentation says to */
}
/* rdram timing tables */
static u16 tparm[5]={0x3a,0x3a,0x3a,0x4a,0x5a};
static u16 tcdly1[5]={0,1,2,2,2};
/* serial presence detect needed variables */
/* Byte 99 number of devices for each stick */
static u8 spd_devices[4]={0,0,0,0};
/* Byte 4 # of row address bits, # of column address bits */
static u8 spd_row_col[4]={0,0,0,0};
/* Byte 5 # of bank bits lower nibble */
static u8 spd_banks[4]={0,0,0,0};
/* Byte 9 Misc. Device configuration S28, and S3 bits are used */
static u8 spd_misc_conf[4]={0,0,0,0};
/* Byte 31 power down exit max time phase A (tPDNXA,max) */
static u8 spd_pdnxa_max[4]={0,0,0,0};
/* Byte 32 power down exit max time phase B (tPDNXB,max) */
static u8 spd_pdnxb_max[4]={0,0,0,0};
/* Byte 33 Map exit max time phase A (tNAPXA,max) */
static u8 spd_napxa_max[4]={0,0,0,0};
/* Byte 34 Nap exit max time phase B (tNAPXB,max) */
static u8 spd_napxb_max[4]={0,0,0,0};
/* Byte 12 Min ras to cas cycles */
static u8 spd_rcd_min[4]={0,0,0,0};
/* Byte 100 Module data width */
static u8 spd_data_width[4]={0,0,0,0};
/* Byte 35 bits 0-3<<8 + byte 37 give the rdram max mhz rate */
static u16 spd_mhz_max[4]={0,0,0,0};
/* Byte 35 bits 4-7<<4 + byte 36 give the rdram min mhz rate */
static u16 spd_mhz_min[4]={0,0,0,0};
/* The size of each device in mega bytes. */
static u8 spd_size[2]={0,0};
int rdram_chips=0; /* number of ram chips on the rimms */
static u32 total_rdram; /* Total rdram found */
/* register index tables */
static u8 mch_gar[16] ={MCH_GAR0,MCH_GAR1,MCH_GAR2,MCH_GAR3,MCH_GAR4,MCH_GAR5,
MCH_GAR6,MCH_GAR7,MCH_GAR8,MCH_GAR9,MCH_GAR10,MCH_GAR11,
MCH_GAR12,MCH_GAR13,MCH_GAR14,MCH_GAR15};
static u8 mch_gba[16] ={MCH_GBA0,MCH_GBA1,MCH_GBA2,MCH_GBA3,MCH_GBA4,MCH_GBA5,
MCH_GBA6,MCH_GBA7,MCH_GBA8,MCH_GBA9,MCH_GBA10,MCH_GBA11,
MCH_GBA12,MCH_GBA13,MCH_GBA14,MCH_GBA15};
static void __rdram_run_command(u8 channel, u16 sdevice_id, u16 reg, u16 command)
{
u32 ricm;
int broadcast;
broadcast = 0;
if (sdevice_id == BCAST) {
broadcast = 1;
sdevice_id = 0;
}
/* Read the old register value and modify it */
pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, &ricm);
ricm &= ~(MASK(RICM_CHANNEL) | MASK(RICM_BROADCAST) | MASK(RICM_ADDR) |
MASK(RICM_REG) | MASK(RICM_CMD));
ricm |= NVAL(RICM_CHANNEL, channel);
ricm |= NVAL(RICM_BROADCAST, broadcast);
ricm |= NVAL(RICM_ADDR, sdevice_id);
ricm |= NVAL(RICM_REG, reg);
ricm |= NVAL(RICM_CMD, command);
/* Write the command */
pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, ricm);
/* Start the command running */
ricm |= RICM_BUSY;
pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, ricm);
/* Wait until the command completes */
rdram_wait_until_ready();
}
static void rdram_run_command(u8 channel, u16 sdevice_id, u16 command)
{
/* Wait until the previous cmd completes */
rdram_wait_until_ready();
/* Run the command */
__rdram_run_command(channel, sdevice_id, 0, command);
}
void rdram_read_reg(u8 channel, u16 sdevice_id, u16 reg, struct rdram_reg_values *res)
{
u32 drd;
/* Wait until the previous cmd completes */
rdram_wait_until_ready();
__rdram_run_command(channel, sdevice_id, reg, CMD_RDRAM_READ_REG);
/* Read back the register value */
pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_DRD, &drd);
res->channel_a = (drd >> 16) &0xffff;
res->channel_b = drd & 0xffff;
return;
}
static void rdram_write_reg(u8 channel, u16 sdevice_id, u16 reg,
u16 channel_a, u16 channel_b)
{
u32 drd;
/* Wait until the previous cmd completes */
rdram_wait_until_ready();
/* Write the data values */
drd = (((u32)channel_a) << 16) | channel_b;
pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_DRD, drd);
__rdram_run_command(channel, sdevice_id, reg, CMD_RDRAM_WRITE_REG);
/* Wait until the command completes */
rdram_wait_until_ready();
return;
}
static void set_sdevid(int rdram_devices)
{
int i;
/* First disable the repeater and set every RDRAM to the
* maximum address I can address
*/
rdram_write_reg(0, BCAST, REG_INIT, 0x1f, 0x1f);
for(i = 0; i < rdram_devices; i++) {
/* Set SDEVID and reenable the repeater */
rdram_write_reg(0, 0x1f, REG_INIT,
(1 << 7) | (i & 0x1f), (1 << 7) | (i & 0x1f));
}
}
static void set_devid(int rdram_devices)
{
int i;
for(i = 0; i < rdram_devices; i++) {
/* FIXME make this smarter */
/* Initially set DEVID == SDEVID */
if ((i % 4) != 5) {
rdram_write_reg(0, i, REG_DEVID, i, i );
} else {
rdram_write_reg(0, i, REG_DEVID, 0x1f, i);
}
}
}
static void set_init_bits(int rdram_devices)
{
int i;
for(i = 0; i < rdram_devices; i++) {
/* Now that the chip is up and running setup the
* power management modes.
*/
rdram_write_reg(0, i, REG_INIT,
(1 << 9) | (1 << 7) | (1 << 6) | (i & 0x1f),
(1 << 9) | (1 << 7) | (1 << 6) | (i & 0x1f)
);
}
}
static void rdram_read_domain_initialization(int rdram_devices)
{
u8 rdt=0x8d;
int i,j,k;
u32 data;
u32 *mem;
u8 adj_a[32],adj_b[32];
u8 l=20;
total_rdram=0;
if((spd_rcd_min[0]==8)||(spd_rcd_min[1]==8))
rdt=0x4d;
/* Set all the rdram devices to the fastest clock cycles */
rdram_write_reg(0, BCAST, REG_TCDLY1, 0, 0 );
rdram_write_reg(0, BCAST, REG_TPARM, 0x3a, 0x3a);
/* find the slowest RDT timming */
pcibios_write_config_byte(I860_MCH_BUS,I860_MCH_DEVFN,MCH_RDT,rdt);
mem=RAM_ADDR(0x100000);
for(j=0;j<rdram_devices;j++) {
for(k=0,i=4,data=0x00000001;k< ((2048/4)+4);k++,i++,data+=0x00000001) {
if(i>7) {
data-=00000004;
i=0;
}
mem[k]=data;
}
printk_debug("Device = %d, %x, %x\n",j,mem[0],mem[4]);
adj_a[j]=(mem[0]&0x0ff)-1;
adj_b[j]=(mem[4]&0x0ff)-1;
if(adj_a[j]<l) l=adj_a[j];
if(adj_b[j]<l) l=adj_b[j];
if(j<spd_devices[0]) {
if(spd_size[0]==32)
mem+=0x1000000; /* add 64 meg */
else
mem+=0x0800000; /* add 32 meg */
}
else {
if(spd_size[1]==32)
mem+=0x1000000; /* add 64 meg */
else
mem+=0x0800000; /* add 32 meg */
}
}
rdt-=l;
printk_debug("RDT = %x, Lowest Offset = %d\n",rdt,l);
for(i=0;i<rdram_devices;i++) {
adj_a[i]-=l;
adj_b[i]-=l;
printk_debug("Device = %d, A Offset = %d, B Offset = %d\n",
i,adj_a[i],adj_b[i]);
}
/* RDRAM Device Timing */
pcibios_write_config_byte(I860_MCH_BUS,I860_MCH_DEVFN,MCH_RDT,rdt);
for(i = 0; i < rdram_devices; i++) {
rdram_write_reg(0, i, REG_TCDLY1, tcdly1[adj_a[i]], tcdly1[adj_b[i]]);
rdram_write_reg(0, i, REG_TPARM, tparm[adj_a[i]], tparm[adj_b[i]]);
}
display_rdram_regs_tparm(rdram_chips);
#if 0
rdram_run_command(0, 0, CMD_MCH_RAC_LOAD_RACA_CONFIG);
rdram_run_command(0, 0, CMD_MCH_RAC_LOAD_RACB_CONFIG);
#endif
}
static void rdram_set_clear_reset(void)
{
int delay=0;
int tcycle;
rdram_write_reg(0, BCAST, REG_TEST78, 0x04, 0x04);
rdram_write_reg(0, BCAST, REG_TEST34, 0x40, 0x40);
rdram_run_command(0, BCAST, CMD_RDRAM_SET_RESET);
/* Compute max of 16 * Tscycle or 2816 * Tcycle */
if(spd_mhz_min[0]) {
tcycle=(999+spd_mhz_min[0])/spd_mhz_min[0];
delay=tcycle*2816;
}
if(delay>(16*TSCYCLE_SLOW))
ndelay(delay);
else
ndelay(16*TSCYCLE_SLOW);
rdram_run_command(0, BCAST, CMD_RDRAM_CLEAR_RESET);
rdram_write_reg(0, BCAST, REG_TEST34, 0, 0);
rdram_write_reg(0, BCAST, REG_TEST78, 0, 0);
}
/*
- ro CNFGA, CNFGB,
- ok REFB, REFR
- SKIP, TEST79
TEST34, TEST78,
TEST77,
TCYCLE,
INIT,
DEVID,
PDNXA, PDNX, NAPX, TPARM, TCDLY1, TFRM, REG_CCA, REG, CCB
*/
static void rdram_init(int rdram_devices)
{
u16 tcycle;
u16 pdnxa,pdnxb,pdnx,napx,napxa,napxb;
u16 tfrm;
int i;
/* 3.1/3.2 RDRAM SIO reset */
rdram_run_command(0, 0, CMD_RDRAM_SIO_RESET);
/* 3.3 Clear TEST77 */
rdram_write_reg(0, BCAST, REG_TEST77, 0, 0);
/* 3.4 Write Tcycle */
/* Calculate the Tcycle */
for(tcycle=spd_mhz_max[0],i=1;i<4;i++)
if(spd_mhz_max[i]&&(tcycle>spd_mhz_max[i]))
tcycle=spd_mhz_max[i];
tcycle = 15625 / tcycle;
rdram_write_reg(0, BCAST, REG_TCYCLE, tcycle, tcycle);
printk_debug("Tcycle = %x\n",tcycle);
/* 3.5 Set SDEVID */
set_sdevid(rdram_devices);
/* 3.6 Set DEVID */
set_devid(rdram_devices);
/* 3.7 Write PDNX, PDNXA Registers */
/* tscycle=10ns or <= 100MHz MCH datasheet pg 156 */
for(pdnxa=(u16)spd_pdnxa_max[0],i=1;i<4;i++)
if(pdnxa<spd_pdnxa_max[i])
pdnxa=spd_pdnxa_max[i];
for(pdnxb=(u16)spd_pdnxb_max[0],i=1;i<4;i++)
if(pdnxb<(u16)spd_pdnxb_max[i])
pdnxb=(u16)spd_pdnxb_max[i];
/* spd-31*1000 + 635 as a round up factor / (64*SCK) */
pdnx=(pdnxa*1000+635)/640;
printk_debug("PDNXA = %d\n",pdnx);
rdram_write_reg(0, BCAST, REG_PDNXA, pdnx, pdnx);
/* spd-31*1000 + spd-32*64 + 2555 round up factor / (256*SCK) */
pdnx=((pdnxa*1000)+(pdnxb*64)+2555)/2560;
rdram_write_reg(0, BCAST, REG_PDNX, pdnx, pdnx);
printk_debug("PDNX = %d\n",pdnx);
/* 3.8 Write NAPX */
/* (1<<10 DQS)+(((spd-33+spd-34)/SCK)<<5)+(spd-33/SCK) */
/* find the max values of the spds for napxa and napxb */
for(napxa=(u16)spd_napxa_max[0],i=1;i<4;i++)
if(napxa<spd_napxa_max[i])
napxa=spd_napxa_max[i];
for(napxb=(u16)spd_napxb_max[0],i=1;i<4;i++)
if(napxb<spd_napxb_max[i])
napxb=spd_napxb_max[i];
if(spd_misc_conf[0]&1)
napx=(1<<10);
else
napx=0;
napx+=(((napxa+napxb+9)/10)<<5)+((napxa+9)/10);
rdram_write_reg(0, BCAST, REG_NAPX, napx, napx);
printk_debug("NAPX = %x\n",napx);
/* 3.9 Write TPARM */
/* Use max times for initial timing. Then redo in step 6.2 */
rdram_write_reg(0, BCAST, REG_TPARM, 0x3a, 0x3a);
/* 3.10 Write TCDLY1 Register */
/* Use max times for initial timing. Then redo in step 6.2 */
rdram_write_reg(0, BCAST, REG_TCDLY1, 2, 2);
/* 3.11 Write TFRM Register */
/* As far as I can tell the equation for TFRM is correct, */
/* however, the documention is not clear, and some assumptions */
/* were made. If ram does not work, this would be a good */
/* CHECKME */
if(spd_rcd_min[0]) {
tfrm = spd_rcd_min[0] - 1;
while(tfrm > 10)
tfrm-=4;
}
else {
tfrm = 9;
}
rdram_write_reg(0, BCAST, REG_TFRM, tfrm, tfrm);
/* 3.12 SETR/CLRR */
rdram_set_clear_reset();
/* 3.13 Write CCA and CCB Registers */
/* Program all Current controll registers with
* an initial approximation. 1/2 their maximum is recommended.
*/
rdram_write_reg(0, BCAST, REG_CCA, 0x40, 0x40);
rdram_write_reg(0, BCAST, REG_CCB, 0x40, 0x40);
/* 3.14 Powerdown Exit */
/* test is S28IECO is set, if yes power up ram from PDN state */
if(spd_misc_conf[0]&4)
rdram_run_command(0, BCAST, CMD_RDRAM_POWERDOWN_EXIT);
/* 3.15 SETF */
rdram_run_command(0, BCAST, CMD_SET_FAST_CLK);
}
void mch_init(void)
{
u8 byte;
u16 word;
u16 top;
int bits1,bits2;
int reg,reg_last,dev;
/* Program Group Attribute Registers */
/* Calculate the GAR value */
bits1=(spd_row_col[0]>>4)+(spd_row_col[0]&0x0f)+spd_banks[0];
byte=0x80;
if(bits1==21) {
byte=0x84;
spd_size[0]=32;
}
else if(bits1==20) {
byte=0x82;
spd_size[0]=16;
}
if(byte!=0x80) {
if(spd_banks[0]==5) byte|=0x10;
if((spd_row_col[0]&0x0f)==7) byte|=0x40;
}
for(reg=dev=0;dev<spd_devices[0];reg++,dev+=4) {
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, mch_gar[reg], byte);
printk_debug("GAR reg = %x, byte = %x\n",mch_gar[reg],byte);
}
/* Test for 2nd set of rimms */
bits2=(spd_row_col[1]>>4)+(spd_row_col[1]&0x0f)+spd_banks[1];
byte=0x80;
if(bits2==21) {
byte=0x84;
spd_size[1]=32;
}
else if(bits2==20) {
byte=0x82;
spd_size[1]=16;
}
if(byte!=0x80) {
if(spd_banks[1]==5) byte|=0x10;
if((spd_row_col[1]&0x0f)==7) byte|=0x40;
}
for(dev=0;dev<spd_devices[1];reg++,dev+=4) {
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, mch_gar[reg], byte);
printk_debug("GAR reg = %x, byte = %x\n",mch_gar[reg],byte);
}
/* The rest are not used because the board has 4 slots & no repeter hubs */
for(;reg<16;reg++) {
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, mch_gar[reg], 0x80);
printk_debug("GAR reg = %x, byte = 0x80\n",mch_gar[reg]);
}
/* Memory Controller Hub Configuration */
/* 1 System Bus Stop Grant,300 or 400Mhz, Non-ECC, MDA Not Present, Apic Enabled */
pcibios_read_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_MCHCFG, &word);
word &= ~((7 << 13) | (1 << 9) | (3 << 7) | (1 << 5) | (1 << 1));
if(((spd_mhz_max[0]==400)&&(spd_mhz_max[1]==400)) ||
((spd_mhz_max[0]==400)&&(spd_mhz_max[1]==0)))
word |= (1 << 11); /* Sets ram bus speed at 400 mhz, else 300 mhz */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_MCHCFG, word);
/* Fixed DRAM Hole Control */
/* Disabled */
pcibios_read_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_FDHC, &byte);
byte &= ~(1 << 7);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_FDHC, byte);
/* Programmable Attribute Map */
/* All Ram, Except the mandatory VGA hole */
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM0, 0x30);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM1, 0x33);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM2, 0x33);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM3, 0x33);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM4, 0x33);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM5, 0x33);
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_PAM6, 0x33);
/* RDRAM Device Group Boundary Addresses */
if(bits1==21) word=16;
else word=8;
for(reg=dev=0,top=0;dev<spd_devices[0];dev+=4,reg++) {
top+=word;
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, mch_gba[reg], (reg<<11)|top);
printk_debug("GBA reg = %x, word = %x\n",mch_gba[reg],(reg<<11)|top);
}
word=0;
if(bits2==21) word=16;
else if(bits2==20) word=8;
for(dev=0;dev<spd_devices[1];dev+=4,reg++) {
top+=word;
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, mch_gba[reg], (reg<<11)|top);
printk_debug("GBA reg = %x, word = %x\n",mch_gba[reg],(reg<<11)|top);
}
/* The rest are filled with the high address */
for(reg_last=reg-1;reg<16;reg++) {
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, mch_gba[reg], (reg_last<<11)|top);
printk_debug("GBA reg = %x, word = %x\n",mch_gba[reg],(reg_last<<11)|top);
}
/* RDRAM Deice Pool Sizeing Register */
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RDPS, 0x0f);
/* RDRAM Device Timing */
pcibios_write_config_byte(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RDT, 0x8e);
/* Top of Memory */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_TOM, top<<8);
printk_debug("TOM = %x <<8\n",top);
/* Error Command Register */
/* Disable reporting errors for now */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_ERRCMD, 0);
/* SMI Command Register */
/* Disable reporting errors for now */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_SMICMD, 0);
/* SCI Command Register */
/* Disable reporting errors for now */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_SCICMD, 0);
/* RDRAM Device Refresh Control */
/* Hard coded the faster refrest time to make sure memory is refreshed */
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_DRAMRC, 1);
}
static void load_spd_vars(void)
{
int j;
int status;
unsigned char byte;
u16 max,min;
for(j = SMBUS_MEM_DEVICE_0; j < SMBUS_MEM_DEVICE_0 + 4; j++) {
status = 0;
if ((j == 0x1b) || 0) {
continue;
}
status = smbus_read_byte(j, 4, &byte);
if (status == 0) {
spd_row_col[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 5, &byte);
if (status == 0) {
spd_banks[j-SMBUS_MEM_DEVICE_0]=byte&0xf;
}
status = smbus_read_byte(j, 9, &byte);
if (status == 0) {
spd_misc_conf[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 12, &byte);
if (status == 0) {
spd_rcd_min[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 31, &byte);
if (status == 0) {
spd_pdnxa_max[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 32, &byte);
if (status == 0) {
spd_pdnxb_max[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 33, &byte);
if (status == 0) {
spd_napxa_max[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 34, &byte);
if (status == 0) {
spd_napxb_max[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 35, &byte);
if (status == 0) {
min=((u16)byte<<4)&0x0f00; /* shift the high 4 bits into the next byte */
max=((u16)byte<<8)&0x0f00; /* shift the low 4 bits into the next byte */
status = smbus_read_byte(j, 36, &byte);
if (status == 0) {
spd_mhz_min[j-SMBUS_MEM_DEVICE_0] = min | byte;
}
status = smbus_read_byte(j, 37, &byte);
if (status == 0) {
spd_mhz_max[j-SMBUS_MEM_DEVICE_0] = max | byte;
}
}
else {
spd_mhz_min[j-SMBUS_MEM_DEVICE_0] = 0;
spd_mhz_max[j-SMBUS_MEM_DEVICE_0] = 0;
}
status = smbus_read_byte(j, 99, &byte);
if (status == 0) {
spd_devices[j-SMBUS_MEM_DEVICE_0]=byte;
}
status = smbus_read_byte(j, 100, &byte);
if (status == 0) {
spd_data_width[j-SMBUS_MEM_DEVICE_0]=byte;
}
}
}
static void ram_zap(unsigned long start, unsigned long stop)
{
unsigned long addr;
/*
* Fill.
*/
printk_debug("DRAM zero: %08lx-%08lx\n", start, stop);
for(addr = start; addr < stop ; addr += 4) {
/* Display address being filled */
if ((addr & 0x0fffffff) == 0)
printk_spew("%08lx\r", addr);
RAM(unsigned long, addr) = 0;
};
/* Display final address */
printk_debug("%08lx\nDRAM filled\n", addr);
}
void init_memory(void)
{
int i,j;
int rdram_devices=0;
u32 ricm;
u16 word;
load_spd_vars();
display_spd_dev_row_col_bank(spd_devices, spd_row_col, spd_banks);
for(i=0;i<2;i++) {
if(spd_devices&&(spd_devices[i]==spd_devices[i+2])&&
(spd_row_col[i]==spd_row_col[i+2])&&
(spd_banks[i]==spd_banks[i+2]))
rdram_devices+=spd_devices[i];
}
if(rdram_devices==0){
printk_debug("ERROR - Memory Rimms are not matched.\n");
for(;;) i=1; /* Freeze the system error */
}
else {
rdram_chips=rdram_devices;
}
printk_debug("RDRAM Chips = %d\n",rdram_chips);
/* 1. Start the clocks */
rdram_run_command(0, 0, CMD_POWERUP_ALL_SEQUENCE);
/* 2. RAC initialization */
rdram_run_command(0, 0, CMD_MCH_INITIALIZE_RAC);
/* 3. Rdram initialize */
rdram_init(rdram_devices);
/* 4. Initialize Memory Controller */
mch_init();
/* 6.1 RDRAM Core Initialization */
for(i = 0; i < 192; i++) {
rdram_run_command(0, BCAST, CMD_RDRAM_REFRESH);
}
/* 5. Rdram Current Control */
/* You can disable the final memory initialized bit
* to see if this is working and it isn't!
* It is close though.
* FIXME manual current calibration.
*/
rdram_run_command(0, 0, CMD_MCH_RAC_CURRENT_CALIBRATION);
/* Do not do the following command. It will cause a lock up */
/* rdram_run_command(0, 0, CMD_MANUAL_CURRENT_CALIBRATION); */
for(i = 0; i < 128; i++) {
for(j=0;j<rdram_chips;j++) {
rdram_run_command(0, j, CMD_RDRAM_CURRENT_CALIBRATION);
}
}
#if 0
display_rdram_regs( rdram_chips );
#endif
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE_ENABLE);
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE);
/* 6.2 RDRAM Read Domain Initialization */
rdram_read_domain_initialization(rdram_devices);
/* 7.0 Remaining init bits (LSR, NSR, PSR) */
set_init_bits(rdram_devices);
/* Final Set the memory initialized bit */
pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, &ricm);
ricm |= RICM_DONE;
pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN,
MCH_RICM, ricm);
/* Memory Controller Hub Configuration Enable ECC */
pcibios_read_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_MCHCFG, &word);
word |= (1 << 8);
pcibios_write_config_word(I860_MCH_BUS, I860_MCH_DEVFN, MCH_MCHCFG, word);
/* Set write combine for the memory max of 2 gig */
printk_debug("set_var_mtrr\n");
set_var_mtrr(0, 0, 2*1024*1024*1024UL, MTRR_TYPE_WRCOMB);
/* Clear all memory to 0's */
total_rdram=(unsigned long)(((unsigned long)spd_size[0]<<21)*spd_devices[0])+
(((unsigned long)spd_size[1]<<21)*spd_devices[1]);
ram_zap(0,0x0a0000);
ram_zap(0x0c0000,(unsigned long)total_rdram);
}

View file

@ -2,4 +2,5 @@ object keyboard.o
object mc146818rtc.o
object isa-dma.o
object i8259.o
dir ide

1
src/pc80/ide/Config Normal file
View file

@ -0,0 +1 @@
object ide.o

447
src/pc80/ide/ide.c Normal file
View file

@ -0,0 +1,447 @@
/*
* UBL, The Universal Talkware Boot Loader
* Copyright (C) 2000 Universal Talkware Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note: Parts of this code grew out of the Openbios effort that was
* abandoned. Without the info that we were able to learn from
* OpenBios this program would have never worked. We are forever
* grateful for those who came before us.
*
* This code can be retrieved in a machine/human readable form at:
*
* http://www.talkware.net/GPL/UBL
*
* Anyone making changes to this code please send them to us so we
* can include them in the standard release.
*
*
* $Id$
*/
#include <arch/io.h>
#include <printk.h>
#include <string.h>
#include "ide.h"
static __inline__ int wait_for_notbusy(unsigned base) {
unsigned i = 0;
do {
if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) &&
((inb_p(IDE_REG_STATUS(base)) & 0x80) != 0x80))
{
return 0;
}
i++;
} while (i != 0);
return 1;
}
static __inline__ int wait_for_dataready(unsigned base) {
unsigned i = 0;
do {
if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) &&
((inb_p(IDE_REG_STATUS(base)) & 0x88) != 0x88))
{
return 0;
}
i++;
} while (i != 0);
return 1;
}
static __inline__ int write_command(
unsigned base,
ide_command_t command,
ide_cmd_param_t * params)
{
if (wait_for_notbusy(base) != 0) return 1;
outb_p(params->precomp, IDE_REG_PRECOMP(base));
outb_p(params->sector_count, IDE_REG_SECTOR_COUNT(base));
outb_p(params->sector_number, IDE_REG_SECTOR_NUMBER(base));
outb_p(params->cylinder & 0xFF, IDE_REG_CYLINDER_LSB(base));
outb_p((params->cylinder >> 8) & 0x03, IDE_REG_CYLINDER_MSB(base));
outb_p(params->drivehead, IDE_REG_DRIVEHEAD(base));
if (wait_for_notbusy(base) != 0) return 1;
outb_p(command, IDE_REG_COMMAND(base));
return 0;
}
int ide_shutdown(void)
{
outb_p(IDE_CMD_STANDBY_IMMEDIATE, IDE_REG_COMMAND(IDE_BASE1));
outb_p(IDE_CMD_STANDBY_IMMEDIATE2, IDE_REG_COMMAND(IDE_BASE1));
return 0;
}
int ide_read_data(unsigned base, void * buf, size_t size) {
register unsigned short * ptr = (unsigned short *) buf;
if (wait_for_dataready(base)) {
printk_debug("data not ready...\n");
return 1;
}
while (size > 1) {
*ptr++ = inw_p(IDE_REG_DATA(base));
size -= sizeof(unsigned short);
}
return 0;
}
int ide_write_data(unsigned base, void * buf, size_t size) {
register unsigned short * ptr = (unsigned short *) buf;
if (wait_for_dataready(base)) return 1;
while (size > 1) {
outw_p(*ptr, IDE_REG_DATA(base));
ptr++;
size -= sizeof(unsigned short);
}
return 0;
}
harddisk_info_t harddisk_info[NUM_HD];
static char buffer[512];
static int init_drive(unsigned base, int driveno) {
volatile int delay;
ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND;
unsigned char command_val;
//unsigned int idx;
//int retval;
unsigned short* drive_info;
harddisk_info[driveno].controller_port = base;
harddisk_info[driveno].num_heads = 0u;
harddisk_info[driveno].num_cylinders = 0u;
harddisk_info[driveno].num_sectors_per_track = 0u;
harddisk_info[driveno].num_sectors = 0ul;
harddisk_info[driveno].address_mode = IDE_DH_CHS;
harddisk_info[driveno].drive_exists = 0;
cmd.drivehead = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS |
IDE_DH_DRIVE(driveno);
write_command(base, IDE_CMD_GET_INFO, &cmd);
if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) {
/* Well, if that command didn't work, we probably don't have drive. */
printk_debug("Drive %d: detect FAILED\n", driveno);
return 1;
}
ide_read_data(base, buffer, IDE_SECTOR_SIZE);
/* Now suck the data out */
#if 0
harddisk_info[driveno].num_heads = *((unsigned short *) (buffer + 0x6E));
harddisk_info[driveno].num_cylinders = *((unsigned short *) (buffer + 0x6C));
harddisk_info[driveno].num_sectors_per_track =
*((unsigned short *) (buffer + 0x70));
harddisk_info[driveno].num_sectors = *((unsigned int *) (buffer + 0x72));
#else
drive_info = (unsigned short*)buffer;
harddisk_info[driveno].num_heads = drive_info[3];
harddisk_info[driveno].num_cylinders = drive_info[1];
harddisk_info[driveno].num_sectors_per_track = drive_info[6];
harddisk_info[driveno].num_sectors = *((unsigned int*)&(drive_info[60]));
#endif
harddisk_info[driveno].drive_exists = 1;
printk_debug(__FUNCTION__ " sectors_per_track=[%d], num_heads=[%d], num_cylinders=[%d]\n",
harddisk_info[driveno].num_sectors_per_track,
harddisk_info[driveno].num_heads,
harddisk_info[driveno].num_cylinders);
#define HD harddisk_info[driveno]
if(drive_info[49] != 0) {
printk_debug("IDE%d %d/%d/%d cap: %04x\n",
(int)driveno, (int)HD.num_heads, (int)HD.num_cylinders, (int)HD.num_sectors_per_track,
(int) drive_info[49]);
}
// printk_debug("drive %d detected heads=0x%X(%u) cyl=0x%X(%u) sec/trk="
// "0x%X(%u) sects=0x%X(%u)\n", (int)driveno, (int)HD.num_heads, (int)HD.num_heads,
// HD.num_cylinders, (int)HD.num_cylinders, (int)HD.num_sectors_per_track,
// HD.num_sectors_per_track, (int)HD.num_sectors, (int)HD.num_sectors);
// printk_debug" capability=[%04x]\n", (int)drive_info[49]);
if (drive_info[49] & 0x200) { /* bit 9 of capability word is lba supported bit */
harddisk_info[driveno].address_mode = IDE_DH_LBA;
} else {
harddisk_info[driveno].address_mode = IDE_DH_CHS;
}
// harddisk_info[driveno].address_mode = IDE_DH_CHS;
/* Set up the Extended control register */
if (harddisk_info[driveno].num_heads > 8) {
command_val = 0x0A;
} else {
command_val = 0x02;
}
outb_p(command_val, IDE_REG_CONTROL(base));
/* Execute the drive diagnostics command */
write_command(base, IDE_CMD_DRIVE_DIAG, &cmd);
if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) {
return 1;
}
/* Reset the bus (again) */
outb_p(cmd.drivehead, IDE_REG_DRIVEHEAD(base));
outb_p(0x04, IDE_REG_CONTROL(base));
for (delay = 0x100; delay > 0; --delay);
outb_p(command_val, IDE_REG_CONTROL(base));
/* Now do a drive recalibrate */
write_command(base, IDE_CMD_RECALIBRATE, &cmd);
if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) {
return 1;
}
(void)wait_for_notbusy(base);
/* Set device parameters */
cmd.sector_count = harddisk_info[driveno].num_sectors_per_track;
cmd.drivehead = IDE_DH_DEFAULT |
IDE_DH_HEAD(harddisk_info[driveno].num_heads) |
IDE_DH_DRIVE(driveno) |
harddisk_info[driveno].address_mode;
write_command(base, IDE_CMD_SET_PARAMS, &cmd);
/* Set multiple mode */
cmd.sector_count = 0x10; /* Single-word DMA, mode 0 */
cmd.drivehead = IDE_DH_DEFAULT |
IDE_DH_HEAD(0) |
IDE_DH_DRIVE(driveno) |
harddisk_info[driveno].address_mode;
write_command(base, IDE_CMD_SET_MULTIMODE, &cmd);
/* Make sure command is still OK */
outb_p(command_val, IDE_REG_CONTROL(base));
/* Set parameters _again_ */
cmd.sector_count = harddisk_info[driveno].num_sectors_per_track;
cmd.drivehead = IDE_DH_DEFAULT |
IDE_DH_HEAD(harddisk_info[driveno].num_heads) |
IDE_DH_DRIVE(driveno) |
harddisk_info[driveno].address_mode;
write_command(base, IDE_CMD_SET_PARAMS, &cmd);
/* Make sure command is still OK */
outb_p(command_val, IDE_REG_CONTROL(base));
#if 0
/* Exercise the drive to see if it works OK */
printk_debug("Exercising HardDisk- buffer=0x%08lX\n", (unsigned long) buffer);
outb_p(0x42, 0xeb);
while (1) {
for (idx = 0; idx < harddisk_info[driveno].num_sectors; ++idx) {
outb_p(idx & 0xFF, 0x80);
retval = ide_read_sector(driveno, buffer, idx);
if (retval != 0) {
printk_debug("readsector(driveno=%d, sector=%lu) returned %d!\n",
driveno, (unsigned long) idx, retval);
}
}
printk_debug("Exercise complete!\n");
outb(0x42, 0xeb);
}
#endif /* 0 */
return 0;
}
static int init_controller(unsigned base, int basedrive) {
volatile int delay;
/* First, check to see if the controller even exists */
outb_p(0x5, IDE_REG_SECTOR_COUNT(base));
if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0x5) {
printk_debug("Controller %d: detect FAILED (1)\n", basedrive / 2);
return -1;
}
outb_p(0xA, IDE_REG_SECTOR_COUNT(base));
if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0xA) {
printk_debug("Controller %d: detect FAILED (2)\n", basedrive / 2);
return -2;
}
/* Reset the system */
outb_p(0x4, IDE_REG_CONTROL(base));
for (delay = 0x100; delay > 0; --delay);
outb_p(0x0, IDE_REG_CONTROL(base));
/* Now initialize the individual drives */
init_drive(base, basedrive);
init_drive(base, basedrive+1);
return 0;
}
int ide_init(void) {
outb_p(0x42, 0xEB);
printk_debug ("I am now initializing the ide system\n");
if(init_controller(IDE_BASE1, 0) < 0) {
printk_debug ("Initializing the main controller failed!\n");
/* error return error */
return -1;
};
#if (NUM_HD > 3)
init_controller(IDE_BASE2, 2);
#endif
#if (NUM_HD > 5)
init_controller(IDE_BASE3, 4);
#endif
#if (NUM_HD > 7)
init_controller(IDE_BASE4, 6);
#endif
return 0;
}
/* read a sector or a partial sector */
int ide_read_sector(int drive, void * buffer, unsigned int block, int byte_offset,
int n_bytes) {
ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND;
unsigned base;
unsigned char sect_buffer[IDE_SECTOR_SIZE];
unsigned int track;
int status;
int address_mode = harddisk_info[drive].address_mode;
/*
printk_debug(__FUNCTION__ " drive[%d], buffer[%08x], block[%08x], offset[%d], n_bytes[%d]\n",
drive, buffer, block, byte_offset, n_bytes);
*/
// printk_debug(__FUNCTION__ " block(%08x) to addr(%08x)\r", block, (int)buffer);
if ((drive < 0) || (drive >= NUM_HD) ||
(harddisk_info[drive].drive_exists == 0))
{
printk_debug("unknown drive\n");
return 1;
}
base = harddisk_info[drive].controller_port;
if (harddisk_info[drive].num_heads > 8) {
outb_p(0xA, IDE_REG_CONTROL(base));
} else {
outb_p(0x2, IDE_REG_CONTROL(base));
}
cmd.sector_count = 1;
if (address_mode == IDE_DH_CHS) {
track = block / harddisk_info[drive].num_sectors_per_track;
cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track);
cmd.cylinder = track / harddisk_info[drive].num_heads;
cmd.drivehead = IDE_DH_DEFAULT |
IDE_DH_HEAD(track % harddisk_info[drive].num_heads) |
IDE_DH_DRIVE(drive) |
IDE_DH_CHS;
/*
printk_debug(__FUNCTION__ " CHS: track=[%d], sector_number=[%d], cylinder=[%d]\n",
track, cmd.sector_number, cmd.cylinder);
*/
} else {
#if 1
cmd.sector_number = block & 0xff; /* lower byte of block (lba) */
cmd.cylinder = (block >> 8) & 0xffff; /* middle 2 bytes of block (lba) */
cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */
((block >> 24) & 0x0f) | /* lower nibble of byte 3 of block */
IDE_DH_DRIVE(drive) |
IDE_DH_LBA;
#else
cmd.sector_number = (block >> 24) & 0xff; /* byte 0 of block (lba) */
cmd.cylinder = (block >> 8) & 0xffff; /* bytes 1 & 2 of block (lba) */
cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */
((block >> 4) & 0x0f) | /* upper nibble of byte 3 of block */
IDE_DH_DRIVE(drive) |
IDE_DH_LBA;
#endif
/*
printk_debug(__FUNCTION__ " LBA: drivehead[%0x], cylinder[%04x], sector[%0x], block[%8x]\n",
cmd.drivehead, cmd.cylinder, cmd.sector_number, block & 0x0fffffff);
*/
}
write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd);
if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) {
printk_debug("ide not ready...\n");
return 1;
}
if (n_bytes != IDE_SECTOR_SIZE) {
status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE);
if (status == 0) {
memcpy(buffer, sect_buffer+byte_offset, n_bytes);
}
} else {
status = ide_read_data(base, buffer, IDE_SECTOR_SIZE);
}
// printk_debug(__FUNCTION__ " status = [%d]\n", status);
return status;
}
#if 0
/* read a sector or a partial sector */
int ide_read_sector(int drive, void * buffer, unsigned int block, int byte_offset,
int n_bytes) {
ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND;
unsigned base;
unsigned char sect_buffer[IDE_SECTOR_SIZE];
unsigned int track;
int status;
if ((drive < 0) || (drive >= NUM_HD) ||
(harddisk_info[drive].drive_exists == 0))
{
return 1;
}
base = harddisk_info[drive].controller_port;
if (harddisk_info[drive].num_heads > 8) {
outb_p(0xA, IDE_REG_CONTROL(base));
} else {
outb_p(0x2, IDE_REG_CONTROL(base));
}
track = block / harddisk_info[drive].num_sectors_per_track;
cmd.sector_count = 1;
cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track);
cmd.cylinder = track % harddisk_info[drive].num_heads;
cmd.drivehead = IDE_DH_DEFAULT |
IDE_DH_HEAD(track / harddisk_info[drive].num_heads) |
IDE_DH_DRIVE(drive) |
IDE_DH_CHS;
// printk_debug(__FUNCTION__ " track=[%d], sector_number=[%d], cylinder=[%d]\n",
// track, cmd.sector_number, cmd.cylinder);
write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd);
if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) {
return 1;
}
if (n_bytes != IDE_SECTOR_SIZE) {
status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE);
if (status == 0) {
memcpy(buffer, sect_buffer+byte_offset, n_bytes);
}
} else {
status = ide_read_data(base, buffer, IDE_SECTOR_SIZE);
}
// printk_debug(__FUNCTION__ " status = [%d]\n", status);
return status;
}
#endif

View file

@ -1,7 +1,9 @@
object fill_inbuf.o
object rom_fill_inbuf.o
object docmil_fill_inbuf.o
#object docplus_fill_inbuf.o
object tsunami_tigbus_rom_fill_inbuf.o
object serial_fill_inbuf.o
object tftp_fill_inbuf.o
driver rom_fill_inbuf.o USE_GENERIC_ROM
driver docmil_fill_inbuf.o
#driver docplus_fill_inbuf.o
driver tsunami_tigbus_rom_fill_inbuf.o USE_TSUNAMI_TIGBUS_ROM
driver serial_fill_inbuf.o USE_SERIAL_FILL_INBUF
driver tftp_fill_inbuf.o USE_TFTP
driver floppy_fill_inbuf.o BOOT_FLOPPY
driver ide_fill_inbuf.o BOOT_IDE
#object read_bytes.o

View file

@ -20,6 +20,10 @@
#define DOC_MIL_BASE 0xffffe000
#endif
static unsigned char *inbuf; /* input buffer */
static unsigned int insize; /* valid bytes in inbuf */
static unsigned int inptr; /* index of next byte to be processed in inbuf */
static unsigned char *nvram;
static int block_count;
static int firstfill = 1;
@ -53,7 +57,7 @@ reset_doc()
}
#endif
int
static int
fill_inbuf(void)
{
#ifdef CHECK_DOC_MIL
@ -373,7 +377,7 @@ static int DoCMil_is_alias(volatile char *docptr1, volatile char *docptr2)
}
#if 0
int WriteBlockECC(volatile char *docptr, unsigned int block, const char *buf)
static int WriteBlockECC(volatile char *docptr, unsigned int block, const char *buf)
{
unsigned char eccbuf[6];
volatile char dummy;
@ -458,7 +462,7 @@ int WriteBlockECC(volatile char *docptr, unsigned int block, const char *buf)
}
#endif
int ReadBlockECC( volatile unsigned char *docptr, unsigned int block, char *buf)
static int ReadBlockECC( volatile unsigned char *docptr, unsigned int block, char *buf)
{
int i, ret;
volatile char dummy;
@ -591,4 +595,46 @@ memcpy_from_doc_mil(void *dest, const void *src, size_t n)
}
}
/* FIXME this is a very lazy ugly port of the new interface to the doc millenium
* find a good way to implement this...
*/
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
static int init_bytes(void)
{
return;
}
static void fini_bytes(void)
{
return;
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
byte_offset_t bytes = 0;
unsigned char *dest = vdest;
while(bytes < count) {
*(dest++) = get_byte();
}
return count;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
byte_offset_t bytes = 0;
while(bytes < count) {
unsigned char byte;
byte = get_byte();
}
return count;
}
static struct stream doc_mil_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
}
#endif /* USE_DOC_MIL */

View file

@ -0,0 +1,44 @@
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/read_bytes.h>
#include <string.h>
#include <floppy_subr.h>
static unsigned long offset;
static int init_bytes(void)
{
offset = 0;
return floppy_init();
}
static void fini_bytes(void)
{
floppy_fini();
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
byte_offset_t len;
len = floppy_read(vdest, offset, count);
if (len > 0) {
offset += len;
}
return len;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
offset += count;
return count;
}
static struct stream floppy_bytes __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

84
src/rom/ide_fill_inbuf.c Normal file
View file

@ -0,0 +1,84 @@
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/read_bytes.h>
#include <delay.h>
#include <string.h>
#include <floppy_subr.h>
/* read a sector or a partial sector */
extern int ide_read_sector(int drive, void * buffer, unsigned int block, int byte_offset,
int n_bytes);
extern int ide_init(void);
static unsigned long offset;
static int init_bytes(void)
{
int i;
printk_debug ("Trying polled ide\n");
printk_debug ("Waiting for ide disks to spin up\n");
printk_debug ("This is a hard coded delay and longer than necessary.\n");
for(i = 0; i < 25; i++) {
printk_debug(".");
delay(1);
}
printk_debug("\n");
offset = 0;
return ide_init();
}
static void fini_bytes(void)
{
return;
}
static byte_offset_t ide_read(void *vdest, byte_offset_t offset, byte_offset_t count)
{
byte_offset_t bytes = 0;
unsigned char *dest = vdest;
while(bytes < count) {
unsigned int block, byte_offset, len;
int result;
block = offset / 512;
byte_offset = offset %512;
len = 512 - byte_offset;
if (len > (count - bytes)) {
len = (count - bytes);
}
result = ide_read_sector(0, dest, block , byte_offset, len);
if (result != 0) {
return bytes;
}
offset += len;
bytes += len;
dest += len;
}
return bytes;
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
byte_offset_t len;
len = ide_read(vdest, offset, count);
if (len > 0) {
offset += len;
}
return len;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
offset += count;
return count;
}
static struct stream ide_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -1,10 +1,8 @@
#ifdef USE_GENERIC_ROM
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <string.h>
@ -16,102 +14,85 @@
#define ZKERNEL_MASK 0x0000ffff
#endif
/* The inbuf copy option has been killed... */
static unsigned char *zkernel_start = (unsigned char *)ZKERNEL_START;
static unsigned long zkernel_mask = ZKERNEL_MASK;
static unsigned char *nvram;
static int block_count;
static int firstfill = 1;
#if defined(INBUF_COPY)
static unsigned char *ram;
#endif
static int block_offset;
#define K64 (64 * 1024)
int fill_inbuf(void)
static int init_bytes(void)
{
extern unsigned char *inbuf;
extern unsigned int insize;
extern unsigned int inptr;
block_count = 0;
block_offset = 0;
nvram = zkernel_start;
if (firstfill) {
block_count = 0;
firstfill = 0;
#ifdef INBUF_COPY
ram = malloc(K64);
#endif
}
printk_debug("%6d:%s() - zkernel_start:0x%08x "
"zkernel_mask:0x%08x\n",
__LINE__, __FUNCTION__,
zkernel_start, zkernel_mask);
if (block_count > 31) {
printk_emerg( "%6d:%s() - overflowed source buffer\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 0;
return (0);
}
if (!block_count) {
nvram = zkernel_start;
#ifdef INBUF_COPY
if (!ram) {
printk_emerg("%6d:%s() - "
"ram malloc failed\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 0;
return (0);
}
printk_debug("%6d:%s() - ram buffer:0x%08x\n",
__LINE__, __FUNCTION__, ram);
#endif
printk_debug("%6d:%s() - zkernel_start:0x%08x "
"zkernel_mask:0x%08x\n",
__LINE__, __FUNCTION__,
zkernel_start, zkernel_mask);
} else {
nvram += K64;
while (!(zkernel_mask & (1 << block_count))) {
printk_debug("%6d:%s() - skipping block %d\n",
__LINE__, __FUNCTION__, block_count);
block_count++;
nvram += K64;
if (block_count > 31) {
printk_emerg("%6d:%s() - "
"overflowed source buffer\n",
__LINE__, __FUNCTION__);
inbuf = zkernel_start;
inptr = 0;
insize = 1;
return (0);
}
}
}
#ifdef INBUF_COPY
memcpy(ram, nvram, K64);
#endif
printk_debug("%6d:%s() - nvram:0x%p block_count:%d\n",
__LINE__, __FUNCTION__, nvram, block_count);
#ifdef INBUF_COPY
inbuf = ram;
#else
inbuf = nvram;
#endif
insize = K64;
inptr = 1;
post_code(0xd0 + block_count);
block_count++;
return inbuf[0];
return 0;
}
#endif /* USE_GENERIC_ROM */
static void fini_bytes(void)
{
return;
}
static byte_offset_t rom_read_bytes(int cp, void *vdest, byte_offset_t count)
{
unsigned char *dest = vdest;
byte_offset_t bytes = 0;
while (bytes < count) {
int length;
if (block_offset == K64) {
block_offset = 0;
block_count++;
nvram+= K64;
}
if (!(zkernel_mask & (1 << block_count))) {
printk_debug("%6d:%s() - skipping block %d\n",
__LINE__, __FUNCTION__, block_count);
continue;
}
if (block_count > 31) {
printk_emerg( "%6d:%s() - overflowed source buffer\n",
__LINE__, __FUNCTION__);
return bytes;
}
length = K64 - block_offset;
if (length > count) {
length = count;
}
if (cp) {
memcpy(dest, nvram + block_offset, length);
}
dest += length;
block_offset += length;
bytes += length;
}
return bytes;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
return rom_read_bytes(0, 0, count);
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
return rom_read_bytes(1, vdest, count);
}
static struct stream rom_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -1,32 +1,36 @@
#ifdef USE_SERIAL_FILL_INBUF
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <string.h>
#include <serial_subr.h>
static int firstfill = 1;
static unsigned char *ram;
#define K64 (64*1024)
int fill_inbuf(void)
static int init_bytes(void)
{
int rc;
if (firstfill) {
firstfill = 0;
ram = malloc(K64);
return 0;
}
static void fini_bytes(void)
{
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
return ttys0_rx_bytes(vdest, count);
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
int64_t i;
for(i = 0; i < count; i++) {
unsigned char byte;
byte = ttys0_rx_byte();
}
inbuf = ram;
insize = ttys0_rx_bytes(inbuf, K64);
inptr = 1;
return inbuf[0];
}
#endif /* USE_SERIAL_FILL_INBUF */
static struct stream serial_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -1,54 +1,79 @@
#ifdef USE_TFTP
#include <cpu/p5/io.h>
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#ifndef DOC_KERNEL_START
#define DOC_KERNEL_START 65536
#endif
static int block_bytes;
static int block_offset;
static unsigned char *buffer;
static int keof;
static unsigned char *nvram;
static int block_count;
static int firstfill = 1;
extern int tftp_init(const char *name);
static void memcpy_from_doc_mil(void *dest, const void *src, size_t n);
static unsigned char *doc_mil = (unsigned char *) 0xffffe000;
#ifdef CHECK_DOC_MIL
static unsigned char *checkbuf;
#endif /* CHECK_DOC_MIL */
static unsigned char *ram;
#define K64 (64 * 1024)
int fill_inbuf(void)
static int init_bytes(void)
{
extern unsigned char *inbuf;
extern unsigned int insize;
extern unsigned int inptr;
int rc;
static keof;
if(keof)
return(-1);
if(firstfill) {
tftp_init("vmlinux");
block_count = 0;
firstfill = 0;
inbuf = ram = malloc(512);
keof=0;
tftp_init("vmlinux");
block_bytes = 0;
block_offset = 0;
firstfill = 0;
buffer = malloc(512);
if (buffer == 0) {
return -1;
}
rc = tftp_fetchone(ram);
insize = rc;
inptr = 1;
return inbuf[0];
keof=0;
}
#endif // USE_TFTP
static void fini_bytes(void)
{
free(buffer);
buffer = 0;
}
static byte_offset_t tftp_read_bytes(int cp, void *vdest, byte_offset_t count)
{
byte_offset_t bytes = 0;
unsigned char *dest = vdest;
if (keof)
return -1;
do {
int length;
if (block_bytes - block_offset == 0) {
block_offset = 0;
block_bytes = tftp_fetchone(buffer);
}
if (block_bytes <= 0) {
keof = 1;
return -1;
}
length = block_bytes - block_offset;
if (length > count) {
length = count;
}
if (cp) {
memcpy(dest, buffer, + block_offset, length);
}
block_offset += length;
dest += length;
} while (bytes < count);
return bytes;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
return tftp_read_bytes(0, 0, count);
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
return tftp_read_bytes(1, vdest, count);
}
static struct stream tftp_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -1,10 +1,8 @@
#ifdef USE_TSUNAMI_TIGBUS_ROM
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/fill_inbuf.h>
#include <rom/read_bytes.h>
#include <arch/io.h>
#include <northbridge/alpha/tsunami/core_tsunami.h>
@ -13,12 +11,7 @@
#define TIG_KERNEL_START 0x20000
#endif
static unsigned long nvram;
static int block_count;
static int firstfill = 1;
static unsigned char *ram;
#define K64 (64 * 1024)
static unsigned long offset;
#define MAX_TIG_FLASH_SIZE (16*1024*1024)
static void tsunami_flash_copy_from(void *addr, unsigned long offset, long len)
@ -34,65 +27,49 @@ static void tsunami_flash_copy_from(void *addr, unsigned long offset, long len)
}
}
int fill_inbuf(void)
static int init_bytes(void)
{
extern unsigned char *inbuf;
extern unsigned int insize;
extern unsigned int inptr;
if (firstfill) {
block_count = 0;
firstfill = 0;
ram = malloc(K64);
if (!ram) {
printk_emerg("%6d:%s() - "
"ram malloc failed\n",
__LINE__, __FUNCTION__);
return 0;
}
offset = 0;
printk_debug("%6d:%s() - TIG_KERNEL_START:0x%08x\n",
__LINE__, __FUNCTION__,
TIG_KERNEL_START);
}
static void fini_bytes(void)
{
return;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
unsigned long new_offset;
byte_offset_t len;
new_offset = offset + count;
if (new_offset > MAX_TIG_FLASH_SIZE) {
new_offset = MAX_TIG_FLASH_SIZE;
}
if (block_count > 31) {
printk_emerg("%6d:%s() - overflowed source buffer\n",
__LINE__, __FUNCTION__);
insize = 0;
return (0);
}
if (!block_count) {
nvram = TIG_KERNEL_START;
printk_debug("%6d:%s() - ram buffer:0x%08x\n",
__LINE__, __FUNCTION__, ram);
printk_debug("%6d:%s() - TIG_KERNEL_START:0x%08x\n",
__LINE__, __FUNCTION__,
TIG_KERNEL_START);
}
tsunami_flash_copy_from(ram, nvram, K64);
printk_debug("\n%6d:%s() - nvram:0x%lx block_count:%d\n",
__LINE__, __FUNCTION__, nvram, block_count);
#if 0
{
int i;
for(i = 0; i < K64; i+= 16) {
printk_debug("%05x: %02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
(block_count << 16)+i,
ram[i+0], ram[i+1], ram[i+2], ram[i+3],
ram[i+4], ram[i+5], ram[i+6], ram[i+7],
ram[i+8], ram[i+9], ram[i+10], ram[i+11],
ram[i+12], ram[i+13], ram[i+14],ram[i+15]);
}
}
#endif
nvram += K64;
inbuf = ram;
insize = K64;
inptr = 1;
post_code(0xd0 + block_count);
block_count++;
return inbuf[0];
len = new_offset - offset;
offset = new_offset;
return len;
}
#endif /* USE_TSUNAMI_TIGBUS_ROM */
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
long length;
length = MAX_TIG_FLASH_SIZE - offset;
if (count < 0)
count = 0;
if (count < length) {
length = count;
}
tsunami_flash_copy_from(vdest, offset, length);
offset += length;
return length;
}
static struct stream tsunami_tigbus_rom_stream __stream = {
.init = init_bytes,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -7,7 +7,6 @@
void ich2_power_after_power_fail(int on)
{
struct pci_dev *dev;
unsigned char byte;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_1F0, 0);
if (!dev) {
return;

View file

@ -15,7 +15,7 @@ void ich2_rtc_init(void)
rtc_failed = byte & RTC_FAILED;
if (rtc_failed) {
byte &= ~(1 << 1); /* preserve the power fail state */
pcibios_write_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, &byte);
pcibios_write_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, byte);
}
pcibios_read_config_dword(RTC_BUS, RTC_DEVFN, GEN_STS, &dword);
rtc_failed |= dword & (1 << 2);

View file

@ -41,17 +41,17 @@ def add_main_rule_dependency(new_dependency):
# this is a tuple, object name, source it depends on,
# and an optional rule (can be empty) for actually building
# the object
def addobject(object, sourcepath, rule, condition):
objectrules.append([object, topify(sourcepath), rule, condition])
def addobject(object, sourcepath, rule, condition, variable):
objectrules.append([object, topify(sourcepath), rule, condition, variable])
# OK, let's face it, make sucks.
# if you have a rule like this:
# a.o: /some/long/path/a.c
# make won't apply the .c.o rule. Toy!
def addobject_defaultrule(object, sourcepath, condition):
def addobject_defaultrule(object, sourcepath, condition, variable):
defaultrule = "\t $(CC) -c $(CFLAGS) -o $@ $<"
addobject(object, sourcepath, defaultrule, condition)
addobject(object, sourcepath, defaultrule, condition, variable)
# for all these functions, you need:
# the dir that the Config file is in
@ -136,7 +136,7 @@ def keyboard(dir, keyboard_name):
if (debug):
print "KEYBOARD"
keyboard_dir = os.path.join(treetop, 'src', keyboard_name)
addobject_defaultrule('keyboard.o', keyboard_dir,'')
addobject_defaultrule('keyboard.o', keyboard_dir,'','OBJECTS')
def cpu(dir, cpu_name):
common_command_action(dir, 'cpu', cpu_name)
@ -165,7 +165,7 @@ def superio(dir, superio_name):
# note that superio is w.r.t. treetop
buildfullpath('superio', superio_name)
dir = os.path.join(treetop, 'src', 'superio', superio_name)
addobject_defaultrule('superio.o', dir,'')
addobject_defaultrule('superio.o', dir,'','OBJECTS')
# commands are of the form:
# superio_name [name=val]*
@ -188,8 +188,8 @@ def nsuperio(dir, superio_commands):
dir = os.path.join(treetop, 'src', 'superio', superio_name)
object="superio_%s.o" % superio_decl_name
superio_source = dir + "/superio.c"
addobject_defaultrule(object, superio_source,'')
addobject_defaultrule('nsuperio.o', "", '')
addobject_defaultrule(object, superio_source,'','OBJECTS')
addobject_defaultrule('nsuperio.o', "", '','OBJECTS')
rest = m.group(2)
superio_cmds = '';
m = command_re.match(rest)
@ -251,7 +251,15 @@ def object(dir, command):
m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command)
obj_name = m.group(1)
condition = m.group(3)
addobject_defaultrule(obj_name, dir, condition)
addobject_defaultrule(obj_name, dir, condition,'OBJECTS')
def driver(dir, command):
wspc = string.whitespace
m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command)
obj_name = m.group(1)
condition = m.group(3)
addobject_defaultrule(obj_name, dir, condition, 'DRIVERS')
# for eventual user-defined rules.
# pattern is name : deps ; rule
@ -390,6 +398,7 @@ command_vals = {
'pcibridge' : [], # vendor, bridgename
'superio' : [], # vendor, superio name
'object' : {}, # path/filename.[cS]
'driver' : {}, # path/filename.[cS]
'mainboardinit' : [], # set of files to include for mainboard init
'config_files' : [], # set of files we built the makefile from
'ldscripts' : [], # set of files we build the linker script from
@ -408,6 +417,7 @@ command_actions = {
'superio' : superio,
'nsuperio' : nsuperio,
'object' : object,
'driver' : driver,
'linux' : linux,
'payload' : payload,
'raminit' : raminit,
@ -595,13 +605,15 @@ def writemakefile(path):
# print out all the object dependencies
# There is ALWAYS a crt0.o
file.write("OBJECTS-1 := crt0.o\n")
file.write("DRIVERS-1 :=\n")
for i in range(len(objectrules)):
obj_name = objectrules[i][0]
obj_cond = objectrules[i][3]
obj_var = objectrules[i][4]
if not obj_cond :
file.write("OBJECTS-1 += %s\n" % (obj_name))
file.write("%s-1 += %s\n" % (obj_var, obj_name))
else:
file.write("OBJECTS-$(%s) += %s\n" % (obj_cond, obj_name))
file.write("%s-$(%s) += %s\n" % (obj_var, obj_cond, obj_name))
# print out all ldscript.ld dependencies
file.write("LDSUBSCRIPTS-1 := \n" )