EPIA-M fixup

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2090 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Ronald G. Minnich 2005-11-22 00:07:02 +00:00
parent 86cbd33837
commit 43225bc804
27 changed files with 2889 additions and 556 deletions

593
HOWTO/EPIA-M-howto Normal file
View File

@ -0,0 +1,593 @@
This HOWTO contains instructions for using LinuxBIOSv2 on the VIA EPIA-M and MII
mini-itx based motherboards.
Version 1.0 initial write for LinuxBIOSv2 by Nick Barker
Using materials and inspiration from
- EPIA HOWTO for freebios/linuxbios by Mark Wilkinson
- Based on the K7SEM HOWTO by Brenden Bixler,
- which is based on the Sis 630 HOWTO by Ron Minnich.
- Getting Started with freebios2 - a mail posting by Jay Miller
Unfortunately, there is a step in this HOWTO that could be hazardous. The
hazards include (but are not limited to)
1) destroying your motherboard
2) hurting yourself
3) killing yourself
Because of these hazards, you must take full responsibility if you
decide to install LinuxBIOSv2 following these procedures. Neither the
author of this HOWTO or any organisation or individual associated with
the LinuxBIOSv2 project can be held responsible for any adverse consequences
of your attempt to follow these procedures.
WARNING: We assume you've built kernels, know how to open up your PC,
and how to yank the flash part out while power is on and put in a
different part. There is NO WARRANTY, express or implied, with this
software. In fact, if you don't know what you're doing, and you get
careless, you're going to end up with a nice paperweight instead of a
motherboard, an emergency room bill, or a funeral service.
YOU HAVE BEEN WARNED.
Additional information available at: http://www.linuxbios.org/
Linux distribution: Most modern distributions are supported.
Other software notes: You MUST have 'as' version 2.9.5 or later.
You MUST have 'gcc' version other than 2.96.
Pre-requisites
--------------
Before you start there are a few things which you need to arrange:
Since you are going to be re-programming the flash rom on the mainboard, and
it is likely that you first few attempts / images will not be right, then
you need a way of restoring a known working bios onto a board which is otherwise
dead.
Recommended: you might want to get a Bios Saviour (RD1-PL) - this is
a handy little piggy-back flash chip that saves you destroying the original
flash image. This howto assumes that you have this device, though other methods
and devices exist for programming flash roms.
LinuxBIOSv2 sends debugging output through the first serial port. You might want
to arrange a null modem serial cable for connecting this serial port to a
second computer running a terminal emulation program. I use 'microcom' which
is simple and allows all output to be captured into a file for later analysis.
The port is set up to use 115200 baud, 8bit, No parity, 1 stop bit.
Under LinuxBIOSv2 you have a choice of 'payloads'. The payload is the program
which LinuxBIOSv2 hands over to once it has finished initialising everything
on the mainboard at boot time. The payload is included in the flash rom along
with LinuxBIOSv2, and usually its function is to locate and load the operating
system. The 2 most common payloads are FILO, for booting Linux off an IDE
disk, and Etherboot for booting a diskless workstation accross a network.
This howto assumes the use of FILO.
A vga bios image. LinuxBIOS2v2 uses the vga bios of the original Via BIOS to
initialise the vga. It is not directly downloadable, but you can capture it from
a system running with the original bios, so you might as well capture it now:
dd if=/dev/mem of=/video.bios.bin \
bs=1 count=65536 skip=790528
Getting Going
-------------
The steps for loading LinuxBIOSv2 are simple:
1) Get Linux installed on your machine.
2) Download and install LinuxBIOSv2 sources.
3) Understand how to flash your rom.
4) Download, Configure and build the FILO payload
5) Configure and build LinuxBIOSv2.
6) Burn the LinuxBIOSv2 image to the flash.
7) Reset the machine -- did it work?
Options Once it has booted
i) Speeding up the boot
ii) Enhancing ACPI support
iii) On EPIA-MII, booting the computer from on-board compact flash
Step 1)
Get Linux installed on your LinuxBIOSv2 machine.
Don't forget to note which partition is / (/dev/hda3 etc.)
Step 2)
Grab the LinuxBIOSv2 source.
cd to the directory you want the source tree to be.
Note: this will create a sub directory called LinuxBIOSv2 which contains
the LinuxBIOSv2 source code
Download the latest code for LinuxBIOSv2 from the downloads page at
http://www.linuxbios.org
having expanded the tarball, cd into the LinuxBIOSv2 directory and browse around.
The top level directory includes:
'src' - where all of the source files for LinuxBIOSv2 are located.
'targets' - where all of the platform specific configuration files
for each platform supported by LinuxBIOSv2 are kept, and
where the build files and build process occur.
'util' - where various utilities required for the build process
and debugging are kept.
Hereafter, this howto refers to directory locations relative to these directories,
unless an absolute pathlist is given.
Step 3)
Whilst getting LinuxBIOSv2 going on your EPIA-M, you are almost
certainly going to be re-programming the flash rom several times, and
there is a very high probability that at one of these stages you will
get a flash rom that fails to boot your mainboard into Linux.
Before we proceed any further, it is absolutley vital that you have
worked out how to program the flash chip, and how you are going to
get back to your original bios when things go wrong. Otherwise you
will end up with a very expensive paper weight as described earlier.
You can use a professional Data I/O burner, or you can be foolhardy
and simply re-program the flash part of a running machine. However
whilst getting going a BIOS SAVIOUR RD1-PL is a very inexpensive
but effective device for ensuring that you always have a working
BIOS to hand.
The bios saviour is a little device which plugs into the flash rom
socket of the motherboard, and the original flash rom then plugs into
the bios saviour. The bios saviour includes a second flash rom chip,
and either of these chips can be selected as the active chip by a
simple supplied electrical switch mounted on flying leads. Make
sure that this switch is clearly visible, so that you know which
chip you are booting from, and which chip you are about to re-program.
Decide which chip you are going to use for LinuxBIOSv2, and which chip
you are going to keep the original working bios in, and mark them
clearly on this switch.
In the 'util/flash_and_burn' directory is the source for the 'flash_rom'
utility, which is great for re-programming the flash chips on the
EPIA-M / MII. Once you have built this utility:
Make sure that it can detect both flash chips on the bios saviour:
with switch set to chip 1 run 'flash_rom'
flash rom should search through a list of known flash rom
device types until it finds the type of the original chip
from your EPIA-M, and report what it has found.
with the switch set to chip 2, run 'flash_rom' again and confirm
that it can 'see' the second flash chip.
If your are lucky, the actual part number of the 2 chips may
be different, which you can use just prior to re-programming
a chip to make sure you are programming the right chip.
Make sure that you can read / write and verify a flash chip:
with switch set to 1 (original BIOS) run
'flash_rom -r original.rom'
this should read the contents of the original bios into the
file original.rom
confirm that the newly read file matches the original bios
'flash_rom -v original.rom'
set the switch to 2
confirm if you can that flash_rom 'sees' the second chip
'flash_rom' - and look for the detected device type
write the known good bios to the second chip with
'flash_rom -w original.bios'
verify that it has written correctly
'flash_rom -v original.rom'
with switch left at position 2, reboot the machine and make
sure that it comes up corectly. If it does then you now have
a working flash programming environment. If it does not, then
set the switch back to 1, reboot the machine, and investigate
further.
Step 4)
Download FILO from http://felixx.tsn.or.jp/~ts1/filo, and expand
In the FILO source directory, type 'make'
The first invocation of make builds the default Config file, which
should be edited to meet your needs. In particular look at the line:
"AUTOBOOT_FILE ...."
and make sure that it looks sensible for your setup. The line
AUTOBOOT_FILE "hda1:/vmlinuz root=/dev/hda2 console=ttyS0,115200"
reads as:
- find a linux os image on device hda partion 1 called vmlinuz,
- load this image
- execute the image passing kernel command line parameters of:
"root=/dev/hda2 console=ttyS0,115200"
after editing Config, type 'make' again, and this will build the file
'filo.elf' which is the payload we will be using.
Copy this file to somewhere which the LinuxBIOSv2 makefile can easily
find it. I just tend to keep it in the root directory though I'm sure
others will condem me for that practise:
'cp filo.elf /'
Make sure that you have compiled a kernel bzImage, and copied it to
the file location you identified in the FILO Config file.
Step 5)
The next step is to create the build environment for the epia-m. This
step creates the appropriate makefiles and build directories for the
epia-m.
'cd targets'
'./buildtarget via/epia-m'
This step will create a subdirectory in the targets/via/epia-m
directory called epia-m, which is the build directory for LinuxBIOSv2.
The main configuration file for the epia-m is in
'targets/via/epia-m/Config.lb'
If you need to make any changes to the configuration, for example you wish to
locate filo.elf in a place other than '/filo.elf', or during the more advanced
steps of this HOWTO, then these changes are made to this file.
You need to re-run the './buildtartegt via/epia-m' after any such change.
The directory 'targets/via/epia-m' contains other sample Config.lb files, any
of which can be copied through to Config.lb in order to become the current
configuration.
Once you have your Config.lb set up to your needs, and the build environment
created with './buildtarget', it is time to build a rom image.
Change directory into the build directory 'targets/via/epia-m/epia-m'
The configuration as set up by the buildtarget process will create a LinuxBIOS
which is exactly 196608 bytes long, which is exactly 64K bytes short of what
needs to go into the 256K flash rom. The other 64K is for your vga bios
which is simply merged with the linuxbios image. The easiest way to make this
happen is to edit the Makefile and change the line
cat fallback/linuxbios.rom > linuxbios.rom
to
cat /video.bios.bin fallback/linuxbios.rom >linuxbios.rom
Note: the above order of merging the files together is critical
You will need to remember to make this change every time after you have run
the buildtarget program.
Type 'make', and wait for the build process to complete.
If all went well, then you should find a file 'linuxbios.rom' in your
current directory. Check that it is 262144 bytes long - i.e. exactly the right
size for the flash rom chip in your EPIA-M / MII.
Step 6)
NOTE: BE ADVISED THAT THIS STEP CAN KILL YOUR MOTHERBOARD !
IF YOU DO NOT HAVE A MEANS OF RECOVERING FROM FLASHING YOUR BIOS,
YOU MAY/WILL BE LEFT WITH A DEAD MACHINE.
Assuming that you are using a Bios Saviour, make sure that the switch is set
to the position for your LinuxBIOSv2 image.
Type 'flash_rom' to make sure it can see the flash chip, and verify its type if
possible.
Only once you are happy that you are about to re-programme the desired chip, type
'flash_rom -w linuxbios.rom', and wait the few seconds it takes to program it.
Once it has finished, verify that the chip was re-rogrammed correctly - type
'flash_rom -v linuxbios.rom'
Step 7)
Power cycle the machine. LinuxBIOSv2 should come up in a few seconds.
With a connection to the serial port set at 115200, you should see LinuxBIOSv2
come up, launch FILO, and if you have a timeout set in FILO, then it may be
waiting for you to confirm its boot command line.
As long as you have this command line set up correctly, and an os image in the
right place, then FILO should proceed to boot into your Linux os.
If you do, CONGRATULATIONS ! It WORKED ! Pat yourself on the back,
why not try the optional steps now ?
If you don't, time to start capturing the output of the serial port
and talking to the linuxbios mailing list.
Optional steps - for use only if step 7 was successfull.
OK so now we have a BIOS which boots your computer fully into the operating system, and
depending upon your needs that may be all that you want. However LinuxBIOSv2 has a few more
tricks up its sleeve should you find yourself hungry for more.
Speeding up the boot
--------------------
Linuxbios sends its debugging output to the first serial port and, depending upon the amount of debug
output selected, can be the limiting factor in the speed with which it boots your computer - regardless
of whether you have anything attached to the serial port.
Linuxbios uses the notion of debug levels to control what is sent to the serial port. These levels
range from 0 to 9 with 0 being the least verbose and 9 being the most verbose.
These levels are defined in the Config.lb file described earlier. To reduce the output set:
option MAXIMUM_CONSOLE_LOGLEVEL=8
option DEFAULT_CONSOLE_LOGLEVEL=8
to lower values.
Next you will have to run 'buildtarget' again to propagate the effects of the config change.
Then edit your Makefile again to include your video bios in the final merging.
Then run 'make clean' followed by 'make'.
Advanced ACPI
-------------
LinuxBIOSv2 now supports ACPI on the epia-m and epia-m II. In particular the interrupt
processing in Linux can be done through ACPI, and crude power management support
is provided. This includes software power off, and power management events from the
power button.
It is possible to enhance this behaviour to provide the full capabilities of the
original BIOS, which includes different sleep levels and wake from these levels
upon certain events. This is achieved by using a 'grabbed' copy of the ACPI
Differentiated System Descriptor Table or DSDT from the original BIOS.
For copyright reasons this table cannot be included with the source distribution
of LinuxBIOSv2.
You MUST have 'iasl' - Intel's ACPI Asl compiler for Unix/Linux -
http://developer.intel.com/technology/iapc/acpi/downloads.htm.
To replace the LinuxBIOSv2 DSDT with the grabbed one from the original BIOS:
- Start the computer using the original BIOS, and make sure that you
have ACPI set up in the kernel that you are running
- Grab the DSDT table - 'cat /proc/acpi/dsdt >dsdt.aml'
- Convert to asl code - 'iasl -d dsdt.aml' (creates dsdt.dsl)
- Convert it to a C hex table - 'iasl -tc dsdt.dsl' (creates dsdt.hex)
- Replace the file 'src/mainboard/via/epia-m/dsdt.c with dsdt.hex
Now re-build LinuxBIOSv2, re-program the flash and power cycle.
If you wish to return to the LinuxBIOSv2 DSDT, then the original file dsdt.asl can be converted
into a C hex file using 'iasl -tc dsdt.asl'
Boot from Onboard Compact Flash (MII only)
------------------------------------------
LinuxBIOSv2 now supports the onboard compact flash on the MII as an IDE drive,
and it is possible to boot directly from this drive using the following steps.
The first step is to get Filo or whatever payload you are using to recognise
and use this device.
In order that the pcmcia subsystem of the Linux kernel can correctly configure
the device later on in the boot process the CF is set up with its I/O
registers in a contiguous block of 16 bytes at 0x1e0 through 0x1ef. Unfortunately
this is not a standard IDE address which is why we need to 'fix' filo to use it.
(Actually it is half of the address range used by IDE4, and so we need to
be careful to tell the kernel not to probe that address - more on that later).
The first step is to change the filo Config file.
1) Comment out SUPPORT_PCI=1. This line instructs filo to search for PCI based IDE
adapters only, and the CF is not attached to a PCI based IDE controller.
2) Add the following two lines somewhere in the Config file:
IDE2_CMD = 0x1e0
IDE2_CNTRL =0x1ec
The second step is to modify the file drivers/ide.c in the filo source directory.
Find the function 'find_ide_controller_compat' and change it to look like
static int find_ide_controller_compat(struct controller *ctrl, int index)
{
if (index >= IDE_MAX_CONTROLLERS)
return -1;
#ifdef IDE2_CMD
if(index == 2){
ctrl->cmd_base = IDE2_CMD;
ctrl->ctrl_base = IDE2_CNTRL;
return 0;
}
#endif
ctrl->cmd_base = ide_base[index];
ctrl->ctrl_base = ide_base[index] + IDE_REG_EXTENDED_OFFSET;
return 0;
}
Filo will now recognise the CF as the first device on the third IDE controller
(i.e. ide2), and can be referred to as 'hde'
The next step is to create an initrd file for your Linux kernel. What? Why?
The CF socket on your MII is hardwired to the PCMCIA controller and for all intents
and purposes it is a PCMCIA device. This means that once Linux boots it will be under
the control of the pcmcia manager. Now according to the pcmcia-utils documentation,
the pcmcia manager is intended to control and configure devices on an already
running system. Yet if we need the CF to be the root device, it needs to be mounted
very early on in the boot sequence, before the stage where pcmcia devices would normally
be configured. The answer is to use an initrd file to get the pcmcia manager running early
for the CF. If you are unfamiliar with initrd then 'man initrd' will give you more background.
The easiest way to create an initrd is to use the script 'mkcfinitrd' which is at the bottom
of this howto. This is a tailored version of the 'pcinitrd' script from the pcmcia-utils package.
Make sure that 'ash' is available on your system as this is the tiny shell programme used during
the initrd phase of booting.
It is worth mounting the initrd generated, and looking over it to make sure that
it contains all of the modules necessary to load and initialise the CF. It does not
need drivers for whatever you use in the pcmcia socket, as that can be initialised
later on in the boot process as before.
Finally gzip the file created, and move it alongside your kernel.
Next adjust your FILO command line to pick things up from the CF. My linux command
line in filo looks like:
AUTOBOOT_FILE = "hde:/vmlinuz initrd=hde:/initrd.gz root=/dev/hde console=tty0 ide4=noprobe"
The ide4=noprobe option is required to stop the kernel from probing the address used
by the CF. As this address is half that used as the standard address for a fifth (i.e. ide4)
controller, the kernel hangs whilst trying to initialise this device if this option
is not given.
Finally make sure that you have copied the necessary files onto your CF, and re-boot
your computer.
******************* mkcfinitrd script **************************************
#!/bin/sh
#
# Utility for constructing CF initrd for Epia-MII CF Boot
#
# Copyright (C) 2005 Nick Barker -- nick.barker9@btinternet.com
#
# Based on pcinitrd
# Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
SIZE=2400
MODULES="pcmcia/pcmcia_core.o pcmcia/ds.o pcmcia/yenta_socket.o"
BLK="kernel/drivers/ide/legacy/ide-cs.o"
KERNEL=`uname -r`
MODDIR=/lib/modules/$KERNEL
BIN="bin/mount bin/umount sbin/insmod sbin/cardmgr"
LIB=`ls /lib/libc.so.? | sort | tail -1`
ETC="/etc/ld.so.cache /etc/pcmcia/config /etc/pcmcia/config.opts"
DEV="/dev/console /dev/null /dev/ram /dev/tty1 /dev/tty2 /dev/tty3 /dev/tty4"
MNT=/tmp/initrd.mnt
# name of the initrd file to make
TARGET=/tmp/initrd
fail()
{
umount $MNT
rmdir $MNT
exit 1
}
trap fail SIGTERM SIGINT
strip_cp()
{
if [ -d $3 ] ; then
DEST=$3/`basename $2`
else
DEST=$3
fi
strip $1 --verbose -o $DEST $2 | sed -e 's/([^ ]*)//g' || fail
}
mkdir --verbose $MNT || exit 1
echo "Creating filesystem on $TARGET"
if [ -b $TARGET ] ; then
rm $TARGET || fail
fi
dd if=$ROOT/dev/zero of=$TARGET bs=1k count=$SIZE
echo "y" | mke2fs $TARGET $SIZE >/dev/null || fail
mount --verbose -t ext2 -o loop $TARGET $MNT || fail
rm -rf $MNT/lost+found
echo "Creating Directories on $TARGET"
for DIR in bin dev etc lib proc tmp mnt ; do
mkdir --verbose $MNT/$DIR || fail
done
for DIR in block misc fs net pcmcia ; do
mkdir --verbose $MNT/lib/$DIR || fail
done
echo "Copying Files to $TARGET"
for F in $DEV ; do
cp -a --verbose /$F $MNT/dev || fail
done
if [ -e /dev/systty ] ; then
cp -a --verbose /dev/systty $MNT/dev || fail
fi
for F in $BIN ; do
strip_cp --strip-all /$F $MNT/bin
done
strip_cp --strip-all /bin/ash $MNT/bin/sh
for F in $LIB ; do
strip_cp --strip-debug /$F $MNT/lib
done
cp --verbose /lib/ld-linux.so.? $MNT/lib || fail
for F in $ETC ; do
cp --verbose /$F $MNT/etc || fail
done
for F in scsi network ftl ide memory serial ; do
touch $MNT/etc/$F ; chmod +x $MNT/etc/$F
done
for MOD in $MODULES ; do
strip_cp --strip-debug $MODDIR/$MOD $MNT/lib/$MOD
done
strip_cp --strip-debug $MODDIR/$BLK $MNT/lib/block/ide-cs.o
echo "Creating linuxrc startup script"
cat > $MNT/linuxrc <<- 'EOF'
#!/bin/sh
mount -t proc /proc /proc
echo ""
echo "==== initrd: starting PCMCIA services ===="
echo ""
PC=/lib/pcmcia
insmod $PC/pcmcia_core.o
insmod $PC/yenta_socket.o
insmod $PC/ds.o
insmod /lib/block/ide-cs.o
if [ "$DEBUG" != "" ] ; then V=-v ; fi
cardmgr $V -q -o -c /etc -m /lib -s /tmp/stab -p /tmp/pid
umount /proc
echo ""
if [ "$DEBUG" != "" ] ; then
/bin/sh < /dev/console
fi
EOF
chmod +x $MNT/linuxrc
df -P $MNT | awk '/tmp/ { printf "%dK/%dK used\n",$3,$2 }'
umount $VERBOSE $MNT
rmdir $MNT
echo "Finished $TARGET"
echo "Now gzip $TARGET to create final initrd.gz"
exit 0
*************************** end mkcfinitrd ***********************************

View File

@ -234,11 +234,13 @@ void cpu_initialize(void)
// Check that we haven't been passed bad information as the result of a race
// (i.e. BSP timed out while waiting for us to load secondary_stack)
#if CONFIG_SMP || CONFIG_IOPIC
if (cpu->path.u.apic.apic_id != lapicid()) {
printk_err("CPU #%d Initialization FAILED: APIC ID mismatch (%u != %u)\n",
info->index, cpu->path.u.apic.apic_id, lapicid());
// return without setting initialized flag
} else {
#endif
/* Find what type of cpu we are dealing with */
identify_cpu(cpu);
printk_debug("CPU: vendor %s device %x\n",
@ -255,8 +257,10 @@ void cpu_initialize(void)
}
printk_info("CPU #%d Initialized\n", info->index);
}
#if CONFIG_SMP || CONFIG_IOPIC
}
#endif
return;
}

View File

@ -15,6 +15,7 @@ static void model_centaur_init(device_t dev)
{
/* Turn on caching if we haven't already */
x86_enable_cache();
x86_setup_mtrrs(36);
x86_mtrr_check();
/* Enable the local cpu apics */
@ -28,6 +29,13 @@ static struct device_operations cpu_dev_ops = {
#warning "FIXME - need correct cpu id here for VIA C3"
static struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_CENTAUR, 0x0670 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0671 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0672 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0673 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0674 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0675 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0676 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0677 }, // VIA C3 Samual 2
{ X86_VENDOR_CENTAUR, 0x0678 }, // VIA C3 Ezra
{ X86_VENDOR_CENTAUR, 0x0680 }, // VIA C3 Ezra-T
{ X86_VENDOR_CENTAUR, 0x0698 }, // VIA C3 Nehemiah

View File

@ -74,6 +74,13 @@ void cardbus_read_resources(device_t dev)
resource_t moving_base, moving_limit, moving;
unsigned long type;
uint16_t ctl;
unsigned long index;
/* See if needs a card control registers base address */
pci_get_resource(dev, PCI_BASE_ADDRESS_0);
compact_resources(dev);
/* See which bridge I/O resources are implemented */
moving_base = pci_moving_config32(dev, PCI_CB_IO_BASE_0);

View File

@ -6,6 +6,7 @@ void cardbus_read_resources(device_t dev);
unsigned int cardbus_scan_bus(struct bus *bus,
unsigned min_devfn, unsigned max_devfn, unsigned int max);
unsigned int cardbus_scan_bridge(device_t dev, unsigned int max);
void cardbus_enable_resources(device_t dev);
extern struct device_operations default_cardbus_ops_bus;

View File

@ -45,6 +45,7 @@ arch i386 end
driver mainboard.o
if HAVE_PIRQ_TABLE object irq_tables.o end
#object reset.o
object vgabios.o
if HAVE_ACPI_TABLES
object fadt.o
@ -133,11 +134,6 @@ config chip.h
chip northbridge/via/vt8623
device pci_domain 0 on
chip southbridge/via/vt8235
register "enable_usb" = "0"
register "enable_native_ide" = "0"
register "enable_com_ports" = "1"
register "enable_keyboard" = "0"
register "enable_nvram" = "1"
device pci 10.0 on end # USB 1.1
device pci 10.1 on end # USB 1.1
@ -151,7 +147,7 @@ chip northbridge/via/vt8623
irq 0x70 = 6
drq 0x74 = 2
end
device pnp 2e.1 off # Parallel Port
device pnp 2e.1 on # Parallel Port
io 0x60 = 0x378
irq 0x70 = 7
drq 0x74 = 3
@ -178,10 +174,16 @@ chip northbridge/via/vt8623
device pci 12.0 on end # Ethernet
end
# This is on the EPIA MII, not the M.
# chip southbridge/ricoh/rl5c476
# end
chip southbridge/ricoh/rl5c476
register "enable_cf" = "1"
device pci 0a.0 on end
device pci 0a.1 on end
end
end
device apic_cluster 0 on
chip cpu/via/model_centaur
device apic 0 on end
end
end
end

View File

@ -36,6 +36,8 @@ uses DEFAULT_CONSOLE_LOGLEVEL
uses MAXIMUM_CONSOLE_LOGLEVEL
uses CONFIG_CONSOLE_SERIAL8250
uses CONFIG_UDELAY_TSC
uses CONFIG_PCI_ROM_RUN
uses CONFIG_CONSOLE_VGA
## ROM_SIZE is the size of boot ROM that this board will use.
default ROM_SIZE = 256*1024
@ -43,6 +45,8 @@ default ROM_SIZE = 256*1024
###
### Build options
###
default CONFIG_PCI_ROM_RUN=0
default CONFIG_CONSOLE_VGA=0
##
## Build code for the fallback boot
@ -70,6 +74,13 @@ default HAVE_HARD_RESET=1
default HAVE_PIRQ_TABLE=1
default IRQ_SLOT_COUNT=5
##
## Build code to load acpi tables
##
default HAVE_ACPI_TABLES=1
##
## Build code to export a CMOS option table
##

View File

@ -68,7 +68,7 @@ static void enable_mainboard_devices(void)
die("Southbridge not found!!!\n");
}
pci_write_config8(dev, 0x50, 0x80);
pci_write_config8(dev, 0x51, 0x1F);
pci_write_config8(dev, 0x51, 0x1f);
#if 0
// This early setup switches IDE into compatibility mode before PCI gets
// // a chance to assign I/Os
@ -141,14 +141,8 @@ static void main(unsigned long bist)
print_debug(" Enabling shadow ram\r\n");
enable_shadow_ram();
/*
memreset_setup();
this is way more generic than we need.
sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
*/
sdram_set_registers((const struct mem_controller *) 0);
sdram_set_spd_registers((const struct mem_controller *) 0);
sdram_enable(0, (const struct mem_controller *) 0);
ddr_ram_setup((const struct mem_controller *)0);
/* Check all of memory */
#if 0

View File

@ -0,0 +1,256 @@
/*
* Minimalist ACPI DSDT table for EPIA-M / MII
* (C) Copyright 2004 Nick Barker <Nick.Barker9@btinternet.com>
*
*
*/
DefinitionBlock ("DSDT.aml", "DSDT", 1, "LXBIOS", "LXB-DSDT", 1)
{
/*
* Define the main processor
*/
Scope (\_PR)
{
Processor (\_PR.CPU0, 0x00, 0x00000410, 0x06) {}
}
/* For now only define 2 power states:
* - S0 which is fully on
* - S5 which is soft off
* any others would involve declaring the wake up methods
*/
Name (\_S0, Package () {0x00, 0x00, 0x00, 0x00 })
Name (\_S5, Package () {0x02, 0x02, 0x00, 0x00 })
/* Root of the bus hierarchy */
Scope (\_SB)
{
/* Define how interrupt Link A is plumbed in */
Device (LNKA)
{
Name (_HID, EisaId ("PNP0C0F"))
Name (_UID, 0x01)
/* Status - always return ready */
Method (_STA, 0, NotSerialized)
{
Return (0x0B)
}
/* Current Resources - return irq set up in BIOS */
Method (_CRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5}
})
Return (BUFF)
}
/* Possible Resources - return the range of irqs
* we are using for PCI - only here to keep Linux ACPI
* happy
*/
Method (_PRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5,9,10}
})
Return (BUFF)
}
/* Set Resources - dummy function to keep Linux ACPI happy
* Linux is more than happy not to tinker with irq
* assignments as long as the CRS and STA functions
* return good values
*/
Method (_SRS, 1, NotSerialized ) {}
/* Disable - dummy function to keep Linux ACPI happy */
Method (_DIS, 0, NotSerialized ) {}
} // End of LNKA
/* Define how interrupt Link B is plumbed in */
Device (LNKB)
{
Name (_HID, EisaId ("PNP0C0F"))
Name (_UID, 0x02)
/* Status - always return ready */
Method (_STA, 0, NotSerialized)
{
Return (0x0B)
}
/* Current Resources - return irq set up in BIOS */
Method (_CRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {9}
})
Return (BUFF)
}
/* Possible Resources - return the range of irqs
* we are using for PCI - only here to keep Linux ACPI
* happy
*/
Method (_PRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5,9,10}
})
Return (BUFF)
}
/* Set Resources - dummy function to keep Linux ACPI happy
* Linux is more than happy not to tinker with irq
* assignments as long as the CRS and STA functions
* return good values
*/
Method (_SRS, 1, NotSerialized ) {}
/* Disable - dummy function to keep Linux ACPI happy */
Method (_DIS, 0, NotSerialized ) {}
} // End of LNKB
/* Define how interrupt Link C is plumbed in */
Device (LNKC)
{
Name (_HID, EisaId ("PNP0C0F"))
Name (_UID, 0x03)
/* Status - always return ready */
Method (_STA, 0, NotSerialized)
{
Return (0x0B)
}
/* Current Resources - return irq set up in BIOS */
Method (_CRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {9}
})
Return (BUFF)
}
/* Possible Resources - return the range of irqs
* we are using for PCI - only here to keep Linux ACPI
* happy
*/
Method (_PRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5,9,10}
})
Return (BUFF)
}
/* Set Resources - dummy function to keep Linux ACPI happy
* Linux is more than happy not to tinker with irq
* assignments as long as the CRS and STA functions
* return good values
*/
Method (_SRS, 1, NotSerialized ) {}
/* Disable - dummy function to keep Linux ACPI happy */
Method (_DIS, 0, NotSerialized ) {}
} // End of LNKC
/* Define how interrupt Link D is plumbed in */
Device (LNKD)
{
Name (_HID, EisaId ("PNP0C0F"))
Name (_UID, 0x04)
/* Status - always return ready */
Method (_STA, 0, NotSerialized)
{
Return (0x0B)
}
/* Current Resources - return irq set up in BIOS */
Method (_CRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5}
})
Return (BUFF)
}
/* Possible Resources - return the range of irqs
* we are using for PCI - only here to keep Linux ACPI
* happy
*/
Method (_PRS, 0, NotSerialized)
{
Name (BUFF, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared) {5,9,10}
})
Return (BUFF)
}
/* Set Resources - dummy function to keep Linux ACPI happy
* Linux is more than happy not to tinker with irq
* assignments as long as the CRS and STA functions
* return good values
*/
Method (_SRS, 1, NotSerialized ) {}
/* Disable - dummy function to keep Linux ACPI happy */
Method (_DIS, 0, NotSerialized ) {}
} // End of LNKD
/* top PCI device */
Device (PCI0)
{
Name (_HID, EisaId ("PNP0A03"))
Name (_ADR, 0x00)
Name (_UID, 0x00)
Name (_BBN, 0x00)
/* PCI Routing Table */
Name (_PRT, Package () {
Package () {0x000AFFFF, 0x00, LNKD, 0x00}, // Cardbus Link D
Package () {0x000AFFFF, 0x01, LNKA, 0x00}, // Cardbus Link A
Package () {0x000AFFFF, 0x02, LNKB, 0x00}, // Cardbus Link B
Package () {0x000AFFFF, 0x03, LNKC, 0x00}, // Cardbus Link C
Package () {0x000DFFFF, 0x00, LNKB, 0x00}, // Firewire Link B
Package () {0x000DFFFF, 0x01, LNKC, 0x00}, // Firewire Link C
Package () {0x000DFFFF, 0x02, LNKD, 0x00}, // Firewire Linc D
Package () {0x000DFFFF, 0x03, LNKA, 0x00}, // Firewire Link A
Package () {0x0010FFFF, 0x00, LNKA, 0x00}, // USB Link A
Package () {0x0010FFFF, 0x01, LNKB, 0x00}, // USB Link B
Package () {0x0010FFFF, 0x02, LNKC, 0x00}, // USB Link C
Package () {0x0010FFFF, 0x03, LNKD, 0x00}, // USB Link D
Package () {0x0011FFFF, 0x00, LNKA, 0x00}, // vt8623 Link A
Package () {0x0011FFFF, 0x01, LNKB, 0x00}, // vt8623 Link B
Package () {0x0011FFFF, 0x02, LNKC, 0x00}, // vt8623 Link C
Package () {0x0011FFFF, 0x03, LNKD, 0x00}, // vt8623 Link D
Package () {0x0012FFFF, 0x00, LNKA, 0x00}, // LAN Link A
Package () {0x0012FFFF, 0x01, LNKB, 0x00}, // LAN Link B
Package () {0x0012FFFF, 0x02, LNKC, 0x00}, // LAN Link C
Package () {0x0012FFFF, 0x03, LNKD, 0x00}, // LAN Link D
Package () {0x0013FFFF, 0x00, LNKA, 0x00}, // Riser slot LinkA
Package () {0x0013FFFF, 0x01, LNKB, 0x00}, // Riser slot LinkB
Package () {0x0013FFFF, 0x02, LNKC, 0x00}, // Riser slot LinkC
Package () {0x0013FFFF, 0x03, LNKD, 0x00}, // Riser slot LinkD
Package () {0x0014FFFF, 0x00, LNKB, 0x00}, // Slot 1, Link B
Package () {0x0014FFFF, 0x01, LNKC, 0x00}, // Slot 1, Link C
Package () {0x0014FFFF, 0x02, LNKD, 0x00}, // Slot 1, Link D
Package () {0x0014FFFF, 0x03, LNKA, 0x00}, // Slot 1, Link A
Package () {0x0001FFFF, 0x00, LNKA, 0x00}, // VGA Link A
Package () {0x0001FFFF, 0x01, LNKB, 0x00}, // VGA Link B
Package () {0x0001FFFF, 0x02, LNKC, 0x00}, // VGA Link C
Package () {0x0001FFFF, 0x03, LNKD, 0x00} // VGA Link D
})
} // End of PCI0
} // End of _SB
} // End of Definition Block

View File

@ -0,0 +1,142 @@
/*
*
* Intel ACPI Component Architecture
* ASL Optimizing Compiler / AML Disassembler version 20040715 [Aug 16 2004]
* Copyright (C) 2000 - 2004 Intel Corporation
* Supports ACPI Specification Revision 2.0c
*
* Compilation of "dsdt.asl" - Thu Oct 27 09:25:57 2005
*
* C source code output
*
*/
unsigned char AmlCode[] =
{
0x44,0x53,0x44,0x54,0xF0,0x03,0x00,0x00, /* 00000000 "DSDT...." */
0x01,0x11,0x4C,0x58,0x42,0x49,0x4F,0x53, /* 00000008 "..LXBIOS" */
0x4C,0x58,0x42,0x2D,0x44,0x53,0x44,0x54, /* 00000010 "LXB-DSDT" */
0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
0x15,0x07,0x04,0x20,0x10,0x12,0x5F,0x50, /* 00000020 "... .._P" */
0x52,0x5F,0x5B,0x83,0x0B,0x43,0x50,0x55, /* 00000028 "R_[..CPU" */
0x30,0x00,0x10,0x04,0x00,0x00,0x06,0x08, /* 00000030 "0......." */
0x5F,0x53,0x30,0x5F,0x12,0x06,0x04,0x00, /* 00000038 "_S0_...." */
0x00,0x00,0x00,0x08,0x5F,0x53,0x35,0x5F, /* 00000040 "...._S5_" */
0x12,0x08,0x04,0x0A,0x02,0x0A,0x02,0x00, /* 00000048 "........" */
0x00,0x10,0x4E,0x39,0x5F,0x53,0x42,0x5F, /* 00000050 "..N9_SB_" */
0x5B,0x82,0x44,0x06,0x4C,0x4E,0x4B,0x41, /* 00000058 "[.D.LNKA" */
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000060 "._HID.A." */
0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x01, /* 00000068 "..._UID." */
0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4, /* 00000070 ".._STA.." */
0x0A,0x0B,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 00000078 "...._CRS" */
0x00,0x08,0x42,0x55,0x46,0x46,0x11,0x09, /* 00000080 "..BUFF.." */
0x0A,0x06,0x23,0x20,0x00,0x18,0x79,0x00, /* 00000088 "..# ..y." */
0xA4,0x42,0x55,0x46,0x46,0x14,0x1A,0x5F, /* 00000090 ".BUFF.._" */
0x50,0x52,0x53,0x00,0x08,0x42,0x55,0x46, /* 00000098 "PRS..BUF" */
0x46,0x11,0x09,0x0A,0x06,0x23,0x20,0x06, /* 000000A0 "F....# ." */
0x18,0x79,0x00,0xA4,0x42,0x55,0x46,0x46, /* 000000A8 ".y..BUFF" */
0x14,0x06,0x5F,0x53,0x52,0x53,0x01,0x14, /* 000000B0 ".._SRS.." */
0x06,0x5F,0x44,0x49,0x53,0x00,0x5B,0x82, /* 000000B8 "._DIS.[." */
0x45,0x06,0x4C,0x4E,0x4B,0x42,0x08,0x5F, /* 000000C0 "E.LNKB._" */
0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 000000C8 "HID.A..." */
0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 000000D0 "._UID..." */
0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 000000D8 "._STA..." */
0x0B,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 000000E0 "..._CRS." */
0x08,0x42,0x55,0x46,0x46,0x11,0x09,0x0A, /* 000000E8 ".BUFF..." */
0x06,0x23,0x00,0x02,0x18,0x79,0x00,0xA4, /* 000000F0 ".#...y.." */
0x42,0x55,0x46,0x46,0x14,0x1A,0x5F,0x50, /* 000000F8 "BUFF.._P" */
0x52,0x53,0x00,0x08,0x42,0x55,0x46,0x46, /* 00000100 "RS..BUFF" */
0x11,0x09,0x0A,0x06,0x23,0x20,0x06,0x18, /* 00000108 "....# .." */
0x79,0x00,0xA4,0x42,0x55,0x46,0x46,0x14, /* 00000110 "y..BUFF." */
0x06,0x5F,0x53,0x52,0x53,0x01,0x14,0x06, /* 00000118 "._SRS..." */
0x5F,0x44,0x49,0x53,0x00,0x5B,0x82,0x45, /* 00000120 "_DIS.[.E" */
0x06,0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48, /* 00000128 ".LNKC._H" */
0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000130 "ID.A...." */
0x5F,0x55,0x49,0x44,0x0A,0x03,0x14,0x09, /* 00000138 "_UID...." */
0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0B, /* 00000140 "_STA...." */
0x14,0x1A,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000148 ".._CRS.." */
0x42,0x55,0x46,0x46,0x11,0x09,0x0A,0x06, /* 00000150 "BUFF...." */
0x23,0x00,0x02,0x18,0x79,0x00,0xA4,0x42, /* 00000158 "#...y..B" */
0x55,0x46,0x46,0x14,0x1A,0x5F,0x50,0x52, /* 00000160 "UFF.._PR" */
0x53,0x00,0x08,0x42,0x55,0x46,0x46,0x11, /* 00000168 "S..BUFF." */
0x09,0x0A,0x06,0x23,0x20,0x06,0x18,0x79, /* 00000170 "...# ..y" */
0x00,0xA4,0x42,0x55,0x46,0x46,0x14,0x06, /* 00000178 "..BUFF.." */
0x5F,0x53,0x52,0x53,0x01,0x14,0x06,0x5F, /* 00000180 "_SRS..._" */
0x44,0x49,0x53,0x00,0x5B,0x82,0x45,0x06, /* 00000188 "DIS.[.E." */
0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48,0x49, /* 00000190 "LNKD._HI" */
0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F, /* 00000198 "D.A...._" */
0x55,0x49,0x44,0x0A,0x04,0x14,0x09,0x5F, /* 000001A0 "UID...._" */
0x53,0x54,0x41,0x00,0xA4,0x0A,0x0B,0x14, /* 000001A8 "STA....." */
0x1A,0x5F,0x43,0x52,0x53,0x00,0x08,0x42, /* 000001B0 "._CRS..B" */
0x55,0x46,0x46,0x11,0x09,0x0A,0x06,0x23, /* 000001B8 "UFF....#" */
0x20,0x00,0x18,0x79,0x00,0xA4,0x42,0x55, /* 000001C0 " ..y..BU" */
0x46,0x46,0x14,0x1A,0x5F,0x50,0x52,0x53, /* 000001C8 "FF.._PRS" */
0x00,0x08,0x42,0x55,0x46,0x46,0x11,0x09, /* 000001D0 "..BUFF.." */
0x0A,0x06,0x23,0x20,0x06,0x18,0x79,0x00, /* 000001D8 "..# ..y." */
0xA4,0x42,0x55,0x46,0x46,0x14,0x06,0x5F, /* 000001E0 ".BUFF.._" */
0x53,0x52,0x53,0x01,0x14,0x06,0x5F,0x44, /* 000001E8 "SRS..._D" */
0x49,0x53,0x00,0x5B,0x82,0x4B,0x1F,0x50, /* 000001F0 "IS.[.K.P" */
0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000001F8 "CI0._HID" */
0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41, /* 00000200 ".A...._A" */
0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44, /* 00000208 "DR.._UID" */
0x00,0x08,0x5F,0x42,0x42,0x4E,0x00,0x08, /* 00000210 ".._BBN.." */
0x5F,0x50,0x52,0x54,0x12,0x43,0x1D,0x20, /* 00000218 "_PRT.C. " */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 00000220 "........" */
0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000228 ".LNKD..." */
0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x4C, /* 00000230 ".......L" */
0x4E,0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C, /* 00000238 "NKA....." */
0xFF,0xFF,0x0A,0x00,0x0A,0x02,0x4C,0x4E, /* 00000240 "......LN" */
0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000248 "KB......" */
0xFF,0x0A,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000250 ".....LNK" */
0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000258 "C......." */
0x0D,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000260 "...LNKB." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000268 "........" */
0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000270 ".LNKC..." */
0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02, /* 00000278 "........" */
0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 00000280 "LNKD...." */
0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C, /* 00000288 ".......L" */
0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 00000290 "NKA....." */
0xFF,0xFF,0x10,0x00,0x00,0x4C,0x4E,0x4B, /* 00000298 ".....LNK" */
0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000002A0 "A......." */
0x10,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000002A8 "...LNKB." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x10,0x00, /* 000002B0 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000002B8 "..LNKC.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x10,0x00,0x0A, /* 000002C0 "........" */
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 000002C8 ".LNKD..." */
0x04,0x0C,0xFF,0xFF,0x11,0x00,0x00,0x4C, /* 000002D0 ".......L" */
0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000002D8 "NKA....." */
0xFF,0xFF,0x11,0x00,0x01,0x4C,0x4E,0x4B, /* 000002E0 ".....LNK" */
0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000002E8 "B......." */
0x11,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x43, /* 000002F0 "....LNKC" */
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x11, /* 000002F8 "........" */
0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44,0x00, /* 00000300 "...LNKD." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x12,0x00, /* 00000308 "........" */
0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000310 ".LNKA..." */
0x04,0x0C,0xFF,0xFF,0x12,0x00,0x01,0x4C, /* 00000318 ".......L" */
0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000320 "NKB....." */
0xFF,0xFF,0x12,0x00,0x0A,0x02,0x4C,0x4E, /* 00000328 "......LN" */
0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000330 "KC......" */
0xFF,0x12,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000338 ".....LNK" */
0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000340 "D......." */
0x13,0x00,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 00000348 "...LNKA." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x13,0x00, /* 00000350 "........" */
0x01,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E, /* 00000358 ".LNKB..." */
0x04,0x0C,0xFF,0xFF,0x13,0x00,0x0A,0x02, /* 00000360 "........" */
0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 00000368 "LNKC...." */
0x0C,0xFF,0xFF,0x13,0x00,0x0A,0x03,0x4C, /* 00000370 ".......L" */
0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000378 "NKD....." */
0xFF,0xFF,0x14,0x00,0x00,0x4C,0x4E,0x4B, /* 00000380 ".....LNK" */
0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000388 "B......." */
0x14,0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00, /* 00000390 "...LNKC." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x14,0x00, /* 00000398 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000003A0 "..LNKD.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x14,0x00,0x0A, /* 000003A8 "........" */
0x03,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 000003B0 ".LNKA..." */
0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C, /* 000003B8 ".......L" */
0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000003C0 "NKA....." */
0xFF,0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B, /* 000003C8 ".....LNK" */
0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000003D0 "B......." */
0x01,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x43, /* 000003D8 "....LNKC" */
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01, /* 000003E0 "........" */
0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44,0x00, /* 000003E8 "...LNKD." */
};

View File

@ -15,8 +15,8 @@
*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

View File

@ -8,6 +8,7 @@
static unsigned long main(unsigned long bist)
{
#if 0
/* This is the primary cpu how should I boot? */
if (do_normal_boot()) {
goto normal_image;
@ -28,5 +29,6 @@ static unsigned long main(unsigned long bist)
: /* clobbers */
);
fallback_image:
#endif
return bist;
}

View File

@ -25,7 +25,7 @@ static void vga_fixup(void) {
}
static void write_protect_vgabios(void)
void write_protect_vgabios(void)
{
device_t dev;

View File

@ -0,0 +1,861 @@
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#undef __KERNEL__
#include <arch/io.h>
//#include <printk.h>
#include <string.h>
#include "vgachip.h"
/* vgabios.c. Derived from: */
/*------------------------------------------------------------ -*- C -*-
* 2 Kernel Monte a.k.a. Linux loading Linux on x86
*
* Erik Arjan Hendriks <hendriks@lanl.gov>
*
* This version is a derivative of the original two kernel monte
* which is (C) 2000 Scyld.
*
* Copyright (C) 2000 Scyld Computing Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Portions related to the alpha architecture are:
*
* Copyright(C) 2001 University of California. LA-CC Number 01-67.
* 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. If the 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by
* reference to http://www.gnu.org/licenses/gpl.html.
*
* This software is provided by the author(s) "as is" and any express
* or implied warranties, including, but not limited to, the implied
* warranties of merchantability and fitness for a particular purpose
* are disclaimed. In no event shall the author(s) be liable for any
* direct, indirect, incidental, special, exemplary, or consequential
* damages (including, but not limited to, procurement of substitute
* goods or services; loss of use, data, or profits; or business
* interruption) however caused and on any theory of liability,
* whether in contract, strict liability, or tort (including
* negligence or otherwise) arising in any way out of the use of this
* software, even if advised of the possibility of such damage.
*
* $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
*--------------------------------------------------------------------*/
/* Modified to be a self sufficient plug in so that it can be used
without reliance on other parts of core Linuxbios
(C) 2005 Nick.Barker9@btinternet.com
Used initially for epia-m where there are problems getting the bios
emulator to successfully run this bios.
*/
/* Declare a temporary global descriptor table - necessary because the
Core part of the bios no longer sets up any 16 bit segments */
__asm__ (
/* pointer to original gdt */
"gdtarg: \n\t"
".word gdt_limit \n\t"
".long gdt \n\t"
/* compute the table limit */
"__mygdt_limit = __mygdt_end - __mygdt - 1 \n\t"
"__mygdtaddr: \n\t"
".word __mygdt_limit \n\t"
".long __mygdt \n\t"
"__mygdt: \n\t"
/* selgdt 0, unused */
".word 0x0000, 0x0000 \n\t"
".byte 0x00, 0x00, 0x00, 0x00 \n\t"
/* selgdt 8, unused */
".word 0x0000, 0x0000 \n\t"
".byte 0x00, 0x00, 0x00, 0x00 \n\t"
/* selgdt 0x10, flat code segment */
".word 0xffff, 0x0000 \n\t"
".byte 0x00, 0x9b, 0xcf, 0x00 \n\t"
/* selgdt 0x18, flat data segment */
".word 0xffff, 0x0000 \n\t"
".byte 0x00, 0x93, 0xcf, 0x00 \n\t"
/* selgdt 0x20, unused */
".word 0x0000, 0x0000 \n\t"
".byte 0x00, 0x00, 0x00, 0x00 \n\t"
/*selgdt 0x28 16-bit 64k code at 0x00000000 */
".word 0xffff, 0x0000 \n\t"
".byte 0, 0x9a, 0, 0 \n\t"
/* selgdt 0x30 16-bit 64k data at 0x00000000 */
".word 0xffff, 0x0000 \n\t"
".byte 0, 0x92, 0, 0 \n\t"
"__mygdt_end: \n\t"
);
/* Declare a pointer to where our idt is going to be i.e. at mem zero */
__asm__ (
"__myidt: \n"
" .word 1023 \n"
" .long 0 \n"
" .word 0 \n"
);
/* The address arguments to this function are PHYSICAL ADDRESSES */
static void real_mode_switch_call_vga(unsigned long devfn)
{
__asm__ __volatile__ (
// paranoia -- does ecx get saved? not sure. This is
// the easiest safe thing to do.
" pushal\n"
/* save the stack */
" mov %esp, __stack\n"
" jmp 1f\n"
"__stack: .long 0\n"
"1:\n"
/* get devfn into %ecx */
" movl %esp, %ebp\n"
" movl 8(%ebp), %ecx\n"
/* load 'our' gdt */
" lgdt %cs:__mygdtaddr \n\t"
/* This configures CS properly for real mode. */
" ljmp $0x28, $__rms_16bit\n"
"__rms_16bit: \n"
".code16 \n"
/* 16 bit code from here on... */
/* Load the segment registers w/ properly configured segment
* descriptors. They will retain these configurations (limits,
* writability, etc.) once protected mode is turned off. */
" mov $0x30, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
/* Turn off protection (bit 0 in CR0) */
" movl %cr0, %eax \n"
" andl $0xFFFFFFFE, %eax \n"
" movl %eax, %cr0 \n"
/* Now really going into real mode */
" ljmp $0, $__rms_real \n"
"__rms_real: \n"
// put the stack at the end of page zero.
// that way we can easily share it between real and protected,
// since the 16-bit ESP at segment 0 will work for any case.
/* Setup a stack */
" mov $0x0, %ax \n"
" mov %ax, %ss \n"
" movl $0x1000, %eax \n"
" movl %eax, %esp \n"
/* Load our 16 it idt */
" xor %ax, %ax \n"
" mov %ax, %ds \n"
" lidt __myidt \n"
/* Dump zeros in the other segregs */
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov $0x40, %ax \n"
" mov %ax, %ds \n"
" mov %cx, %ax \n"
/* go run the code */
" .byte 0x9a, 0x03, 0, 0, 0xc0 \n"
/* if we got here, just about done.
* Need to get back to protected mode */
"movl %cr0, %eax\n"
"orl $0x0000001, %eax\n" /* PE = 1 */
"movl %eax, %cr0\n"
/* Now that we are in protected mode jump to a 32 bit code segment. */
"data32 ljmp $0x10, $vgarestart\n"
"vgarestart:\n"
".code32\n"
" movw $0x18, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
/* restore proper gdt and idt */
" lgdt %cs:gdtarg \n"
" lidt idtarg \n"
".globl vga_exit\n"
"vga_exit:\n"
" mov __stack, %esp\n"
" popal\n"
);
}
__asm__ (".text\n""real_mode_switch_end:\n");
extern char real_mode_switch_end[];
/* call vga bios int 10 function 0x4f14 to enable main console
epia-m does not always autosence the main console so forcing it on is good !! */
void vga_enable_console()
{
__asm__ __volatile__ (
// paranoia -- does ecx get saved? not sure. This is
// the easiest safe thing to do.
" pushal\n"
/* save the stack */
" mov %esp, __stack\n"
/* load 'our' gdt */
" lgdt %cs:__mygdtaddr \n\t"
/* This configures CS properly for real mode. */
" ljmp $0x28, $__vga_ec_16bit\n"
"__vga_ec_16bit: \n"
".code16 \n"
/* 16 bit code from here on... */
/* Load the segment registers w/ properly configured segment
* descriptors. They will retain these configurations (limits,
* writability, etc.) once protected mode is turned off. */
" mov $0x30, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
/* Turn off protection (bit 0 in CR0) */
" movl %cr0, %eax \n"
" andl $0xFFFFFFFE, %eax \n"
" movl %eax, %cr0 \n"
/* Now really going into real mode */
" ljmp $0, $__vga_ec_real \n"
"__vga_ec_real: \n"
// put the stack at the end of page zero.
// that way we can easily share it between real and protected,
// since the 16-bit ESP at segment 0 will work for any case.
/* Setup a stack */
" mov $0x0, %ax \n"
" mov %ax, %ss \n"
" movl $0x1000, %eax \n"
" movl %eax, %esp \n"
/* debugging for RGM */
" mov $0x11, %al \n"
" outb %al, $0x80\n"
/* Load our 16 it idt */
" xor %ax, %ax \n"
" mov %ax, %ds \n"
" lidt __myidt \n"
/* Dump zeros in the other segregs */
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
/* ask bios to enable main console */
/* set up for int 10 call - values found from X server bios call routines */
" movw $0x4f14,%ax \n"
" movw $0x8003,%bx \n"
" movw $1, %cx \n"
" movw $0, %dx \n"
" movw $0, %di \n"
" .byte 0xcd, 0x10 \n"
" movb $0x55, %al\noutb %al, $0x80\n"
/* if we got here, just about done.
* Need to get back to protected mode */
"movl %cr0, %eax\n"
"orl $0x0000001, %eax\n" /* PE = 1 */
"movl %eax, %cr0\n"
/* Now that we are in protected mode jump to a 32 bit code segment. */
"data32 ljmp $0x10, $vga_ec_restart\n"
"vga_ec_restart:\n"
".code32\n"
" movw $0x18, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
/* restore proper gdt and idt */
" lgdt %cs:gdtarg \n"
" lidt idtarg \n"
".globl vga__ec_exit\n"
"vga_ec_exit:\n"
" mov __stack, %esp\n"
" popal\n"
);
}
void
do_vgabios(void)
{
device_t dev;
unsigned long busdevfn;
unsigned int rom = 0;
unsigned char *buf;
unsigned int size = 64*1024;
int i;
/* clear vga bios data area */
for (i=0x400; i<0x500; i++) {
*(unsigned char *) i = 0;
}
dev = dev_find_class(PCI_CLASS_DISPLAY_VGA<<8 , 0);
if (! dev) {
printk_debug("NO VGA FOUND\n");
return;
}
printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
/* declare rom address here - keep any config data out of the way of core LXB stuff */
rom = 0xfffc0000;
pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1);
printk_debug("rom base, size: %x\n", rom);
buf = (unsigned char *) rom;
if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
memcpy((void *) 0xc0000, buf, size);
write_protect_vgabios(); // in northbridge
// check signature again
buf = (unsigned char *) 0xc0000;
if (buf[0]==0x55 && buf[1]==0xAA) {
busdevfn = (dev->bus->secondary << 8) | dev->path.u.pci.devfn;
printk_debug("bus/devfn = %#x\n", busdevfn);
real_mode_switch_call_vga(busdevfn);
} else
printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
} else
printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
}
// we had hoped to avoid this.
// this is a stub IDT only. It's main purpose is to ignore calls
// to the BIOS.
// no longer. Dammit. We have to respond to these.
struct realidt {
unsigned short offset, cs;
};
// from a handy writeup that andrey found.
// handler.
// There are some assumptions we can make here.
// First, the Top Of Stack (TOS) is located on the top of page zero.
// we can share this stack between real and protected mode.
// that simplifies a lot of things ...
// we'll just push all the registers on the stack as longwords,
// and pop to protected mode.
// second, since this only ever runs as part of linuxbios,
// we know all the segment register values -- so we don't save any.
// keep the handler that calls things small. It can do a call to
// more complex code in linuxbios itself. This helps a lot as we don't
// have to do address fixup in this little stub, and calls are absolute
// so the handler is relocatable.
void handler(void) {
__asm__ __volatile__ (
".code16\n"
"idthandle:\n"
" pushal\n"
" movb $0, %al\n"
" ljmp $0, $callbiosint16\n"
"end_idthandle:\n"
".code32\n"
);
}
void debughandler(void) {
__asm__ __volatile__ (
".code16\n"
"debughandle:\n"
" pushw %cx \n"
" movw $250, %cx \n"
"dbh1: \n"
" loop dbh1 \n"
" popw %cx \n"
" iret \n"
"end_debughandle:\n"
".code32\n"
);
}
// Calling conventions. The first C function is called with this stuff
// on the stack. They look like value parameters, but note that if you
// modify them they will go back to the INTx function modified.
// the C function will call the biosint function with these as
// REFERENCE parameters. In this way, we can easily get
// returns back to the INTx caller (i.e. vgabios)
void callbiosint(void) {
__asm__ __volatile__ (
".code16\n"
"callbiosint16:\n"
" push %ds \n"
" push %es \n"
" push %fs \n"
" push %gs \n"
// clean up the int #. To save space we put it in the lower
// byte. But the top 24 bits are junk.
"andl $0xff, %eax\n"
// this push does two things:
// - put the INT # on the stack as a parameter
// - provides us with a temp for the %cr0 mods.
"pushl %eax\n"
"movl %cr0, %eax\n"
//"andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
//"orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */
"orl $0x00000001, %eax\n" /* PE = 1 */
"movl %eax, %cr0\n"
/* Now that we are in protected mode jump to a 32 bit code segment. */
"data32 ljmp $0x10, $biosprotect\n"
"biosprotect:\n"
".code32\n"
" movw $0x18, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
" lidt idtarg \n"
" call biosint \n"
// back to real mode ...
" ljmp $0x28, $__rms_16bit2\n"
"__rms_16bit2: \n"
".code16 \n" /* 16 bit code from here on... */
/* Load the segment registers w/ properly configured segment
* descriptors. They will retain these configurations (limits,
* writability, etc.) once protected mode is turned off. */
" mov $0x30, %ax \n"
" mov %ax, %ds \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov %ax, %ss \n"
/* Turn off protection (bit 0 in CR0) */
" movl %cr0, %eax \n"
" andl $0xFFFFFFFE, %eax \n"
" movl %eax, %cr0 \n"
/* Now really going into real mode */
" ljmp $0, $__rms_real2 \n"
"__rms_real2: \n"
/* Setup a stack */
" mov $0x0, %ax \n"
" mov %ax, %ss \n"
/* ebugging for RGM */
" mov $0x11, %al \n"
" outb %al, $0x80\n"
" xor %ax, %ax \n"
" mov %ax, %ds \n"
" lidt __myidt \n"
" mov %ax, %es \n"
" mov %ax, %fs \n"
" mov %ax, %gs \n"
" mov $0x40, %ax \n"
" mov %ax, %ds \n"
// pop the INT # that you pushed earlier
" popl %eax\n"
" pop %gs \n"
" pop %fs \n"
" pop %es \n"
" pop %ds \n"
" popal\n"
" iret\n"
".code32\n"
);
}
enum {
PCIBIOS = 0x1a,
MEMSIZE = 0x12
};
int
pcibios(
unsigned long *pedi,
unsigned long *pesi,
unsigned long *pebp,
unsigned long *pesp,
unsigned long *pebx,
unsigned long *pedx,
unsigned long *pecx,
unsigned long *peax,
unsigned long *pflags
);
int
handleint21(
unsigned long *pedi,
unsigned long *pesi,
unsigned long *pebp,
unsigned long *pesp,
unsigned long *pebx,
unsigned long *pedx,
unsigned long *pecx,
unsigned long *peax,
unsigned long *pflags
);
extern void vga_exit(void);
int
biosint(
unsigned long intnumber,
unsigned long gsfs,
unsigned long dses,
unsigned long edi,
unsigned long esi,
unsigned long ebp,
unsigned long esp,
unsigned long ebx,
unsigned long edx,
unsigned long ecx,
unsigned long eax,
unsigned long cs_ip,
unsigned short stackflags
) {
unsigned long ip;
unsigned long cs;
unsigned long flags;
int ret = -1;
ip = cs_ip & 0xffff;
cs = cs_ip >> 16;
flags = stackflags;
printk_debug("biosint: # 0x%lx, eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
intnumber, eax, ebx, ecx, edx);
printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n", ebp, esp, edi, esi);
printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n", ip, cs, flags);
// cases in a good compiler are just as good as your own tables.
switch (intnumber) {
case 0 ... 15:
// These are not BIOS service, but the CPU-generated exceptions
printk_info("biosint: Oops, exception %u\n", intnumber);
if (esp < 0x1000) {
printk_debug("Stack contents: ");
while (esp < 0x1000) {
printk_debug("0x%04x ", *(unsigned short *) esp);
esp += 2;
}
printk_debug("\n");
}
printk_debug("biosint: Bailing out\n");
// "longjmp"
vga_exit();
break;
case PCIBIOS:
ret = pcibios( &edi, &esi, &ebp, &esp,
&ebx, &edx, &ecx, &eax, &flags);
break;
case MEMSIZE:
// who cares.
eax = 64 * 1024;
ret = 0;
break;
case 0x15:
ret=handleint21( &edi, &esi, &ebp, &esp,
&ebx, &edx, &ecx, &eax, &flags);
break;
default:
printk_info("BIOSINT: Unsupport int #0x%x\n",
intnumber);
break;
}
if (ret)
flags |= 1; // carry flags
else
flags &= ~1;
stackflags = flags;
return ret;
}
void setup_realmode_idt(void)
{
extern unsigned char idthandle, end_idthandle;
extern unsigned char debughandle, end_debughandle;
int i;
struct realidt *idts = (struct realidt *) 0;
int codesize = &end_idthandle - &idthandle;
unsigned char *intbyte, *codeptr;
// for each int, we create a customized little handler
// that just pushes %ax, puts the int # in %al,
// then calls the common interrupt handler.
// this necessitated because intel didn't know much about
// architecture when they did the 8086 (it shows)
// (hmm do they know anymore even now :-)
// obviously you can see I don't really care about memory
// efficiency. If I did I would probe back through the stack
// and get it that way. But that's really disgusting.
for (i = 0; i < 256; i++) {
idts[i].cs = 0;
codeptr = (char*) 4096 + i * codesize;
idts[i].offset = (unsigned) codeptr;
memcpy(codeptr, &idthandle, codesize);
intbyte = codeptr + 3;
*intbyte = i;
}
// fixed entry points
// VGA BIOSes tend to hardcode f000:f065 as the previous handler of
// int10.
// calling convention here is the same as INTs, we can reuse
// the int entry code.
codeptr = (char*) 0xff065;
memcpy(codeptr, &idthandle, codesize);
intbyte = codeptr + 3;
*intbyte = 0x42; /* int42 is the relocated int10 */
/* debug handler - useful to set a programmable delay between instructions if the TF bit is set upon
call to real mode */
idts[1].cs = 0;
idts[1].offset = 16384;
memcpy(16384, &debughandle, &end_debughandle - &debughandle);
}
enum {
CHECK = 0xb001,
FINDDEV = 0xb102,
READCONFBYTE = 0xb108,
READCONFWORD = 0xb109,
READCONFDWORD = 0xb10a,
WRITECONFBYTE = 0xb10b,
WRITECONFWORD = 0xb10c,
WRITECONFDWORD = 0xb10d
};
// errors go in AH. Just set these up so that word assigns
// will work. KISS.
enum {
PCIBIOS_NODEV = 0x8600,
PCIBIOS_BADREG = 0x8700
};
int
pcibios(
unsigned long *pedi,
unsigned long *pesi,
unsigned long *pebp,
unsigned long *pesp,
unsigned long *pebx,
unsigned long *pedx,
unsigned long *pecx,
unsigned long *peax,
unsigned long *pflags
) {
unsigned long edi = *pedi;
unsigned long esi = *pesi;
unsigned long ebp = *pebp;
unsigned long esp = *pesp;
unsigned long ebx = *pebx;
unsigned long edx = *pedx;
unsigned long ecx = *pecx;
unsigned long eax = *peax;
unsigned long flags = *pflags;
unsigned short func = (unsigned short) eax;
int retval = 0;
unsigned short devid, vendorid, devfn;
short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */
unsigned char bus;
device_t dev;
switch(func) {
case CHECK:
*pedx = 0x4350;
*pecx = 0x2049;
retval = 0;
break;
case FINDDEV:
{
devid = *pecx;
vendorid = *pedx;
devindex = *pesi;
dev = 0;
while ((dev = dev_find_device(vendorid, devid, dev))) {
if (devindex <= 0)
break;
devindex--;
}
if (dev) {
unsigned short busdevfn;
*peax = 0;
// busnum is an unsigned char;
// devfn is an int, so we mask it off.
busdevfn = (dev->bus->secondary << 8)
| (dev->path.u.pci.devfn & 0xff);
printk_debug("0x%x: return 0x%x\n", func, busdevfn);
*pebx = busdevfn;
retval = 0;
} else {
*peax = PCIBIOS_NODEV;
retval = -1;
}
}
break;
case READCONFDWORD:
case READCONFWORD:
case READCONFBYTE:
case WRITECONFDWORD:
case WRITECONFWORD:
case WRITECONFBYTE:
{
unsigned long dword;
unsigned short word;
unsigned char byte;
unsigned char reg;
devfn = *pebx & 0xff;
bus = *pebx >> 8;
reg = *pedi;
dev = dev_find_slot(bus, devfn);
if (! dev) {
printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
// idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
*peax = PCIBIOS_BADREG;
retval = -1;
}
switch(func) {
case READCONFBYTE:
byte = pci_read_config8(dev, reg);
*pecx = byte;
break;
case READCONFWORD:
word = pci_read_config16(dev, reg);
*pecx = word;
break;
case READCONFDWORD:
dword = pci_read_config32(dev, reg);
*pecx = dword;
break;
case WRITECONFBYTE:
byte = *pecx;
pci_write_config8(dev, reg, byte);
break;
case WRITECONFWORD:
word = *pecx;
pci_write_config16(dev, reg, word);
break;
case WRITECONFDWORD:
dword = *pecx;
pci_write_config32(dev, reg, dword);
break;
}
if (retval)
retval = PCIBIOS_BADREG;
printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx);
*peax = 0;
retval = 0;
}
break;
default:
printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
break;
}
return retval;
}
int handleint21( unsigned long *edi, unsigned long *esi, unsigned long *ebp,
unsigned long *esp, unsigned long *ebx, unsigned long *edx,
unsigned long *ecx, unsigned long *eax, unsigned long *flags)
{
int res=-1;
switch(*eax&0xffff)
{
case 0x5f19:
break;
case 0x5f18:
*eax=0x5f;
*ebx=0x545; // MCLK = 133, 32M frame buffer, 256 M main memory
*ecx=0x060;
res=0;
break;
case 0x5f00:
*eax = 0x8600;
break;
case 0x5f01:
*eax = 0x5f;
*ecx = (*ecx & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
res = 0;
break;
case 0x5f02:
*eax=0x5f;
*ebx= (*ebx & 0xffff0000) | 2;
*ecx= (*ecx & 0xffff0000) | 0x401; // PAL + crt only
*edx= (*edx & 0xffff0000) | 0; // TV Layout - default
res=0;
break;
case 0x5f0f:
*eax=0x860f;
break;
}
return res;
}

View File

@ -0,0 +1,10 @@
#ifndef _PC80_VGABIOS
#define _PC80_VGABIOS
extern struct chip_control pc80_vgabios_control;
struct pc80_vgabios_config {
int nothing;
};
#endif /* _PC80_VGABIOS */

View File

@ -10,6 +10,7 @@
#include <bitops.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include "chip.h"
#include "northbridge.h"
@ -19,6 +20,18 @@
* slower than normal, ethernet drops packets).
* Apparently these registers govern some sort of bus master behavior.
*/
static void dump_dev(device_t dev)
{
int i,j;
for(i = 0; i < 256; i += 16) {
printk_debug("0x%x: ", i);
for(j = 0; j < 16; j++) {
printk_debug("%02x ", pci_read_config8(dev, i+j));
}
printk_debug("\n");
}
}
static void northbridge_init(device_t dev)
{
device_t fb_dev;
@ -44,21 +57,25 @@ static void northbridge_init(device_t dev)
/* Fixup GART and framebuffer addresses properly.
* First setup frame buffer properly.
*/
fb = pci_read_config32(dev, 0x10); /* Base addres of framebuffer */
//fb = pci_read_config32(dev, 0x10); /* Base addres of framebuffer */
fb = 0xd0000000;
printk_debug("Frame buffer at %8x\n",fb);
c = pci_read_config8(dev, 0xe1) & 0xf0; /* size of vga */
c |= fb>>28; /* upper nibble of frame buffer address */
c = 0xdd;
pci_write_config8(dev, 0xe1, c);
c = (fb>>20) | 1; /* enable framebuffer */
c = 0x81; /* enable framebuffer */
pci_write_config8(dev, 0xe0, c);
pci_write_config8(dev, 0xe2, 0x42); /* 'cos award does */
}
//dump_dev(dev);
}
static void nullfunc(){}
static struct device_operations northbridge_operations = {
.read_resources = pci_dev_read_resources,
.read_resources = nullfunc,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = northbridge_init
@ -80,10 +97,11 @@ static void agp_init(device_t dev)
pci_write_config8(dev, 0x43, 0x44);
pci_write_config8(dev, 0x44, 0x34);
pci_write_config8(dev, 0x83, 0x02);
//dump_dev(dev);
}
static struct device_operations agp_operations = {
.read_resources = pci_bus_read_resources,
.read_resources = nullfunc,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = agp_init,
@ -100,12 +118,64 @@ static struct pci_driver agp_driver __pci_driver = {
static void vga_init(device_t dev)
{
// unsigned long fb;
msr_t clocks1,clocks2,instructions,setup;
printk_debug("VGA random fixup ...\n");
pci_write_config8(dev, 0x04, 0x07);
pci_write_config8(dev, 0x0d, 0x20);
pci_write_config32(dev,0x10,0xd8000008);
pci_write_config32(dev,0x14,0xdc000000);
/* Set the vga mtrrs - disable for the moment */
//dump_dev(dev);
// set up performnce counters for debugging vga init sequence
//setup.lo = 0x1c0; // count instructions
//wrmsr(0x187,setup);
//instructions.hi = 0;
//instructions.lo = 0;
//wrmsr(0xc2,instructions);
//clocks1 = rdmsr(0x10);
#if 0
/* code to make vga init go through the emulator - as of yet this does not workfor the epia-m */
dev->on_mainboard=1;
dev->rom_address = (void *)0xfffc0000;
pci_dev_init(dev);
call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
//clocks2 = rdmsr(0x10);
//instructions = rdmsr(0xc2);
printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
#else
/* code to make vga init run in real mode - does work but against the current Linuxbios philosophy */
printk_debug("INSTALL REAL-MODE IDT\n");
setup_realmode_idt();
printk_debug("DO THE VGA BIOS\n");
do_vgabios();
//clocks2 = rdmsr(0x10);
//instructions = rdmsr(0xc2);
//printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
//printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
//printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
vga_enable_console();
#endif
pci_write_config32(dev,0x30,0);
/* Set the vga mtrrs - disable for the moment as the add_var_mtrr function has vapourised */
#if 0
add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
fb = pci_read_config32(dev,0x10); // get the fb address
@ -113,8 +183,17 @@ static void vga_init(device_t dev)
#endif
}
static void vga_read_resources(device_t dev)
{
dev->rom_address = (void *)0xfffc0000;
dev->on_mainboard=1;
pci_dev_read_resources(dev);
}
static struct device_operations vga_operations = {
.read_resources = pci_dev_read_resources,
.read_resources = vga_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = vga_init,

View File

@ -1,90 +1,49 @@
/*
* (C) Copyright 2005 Nick Barker <nick.barker9@btinternet.com>
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
Automatically detect and set up ddr dram on the CLE266 chipset.
Assumes DDR memory, though chipset also supports SDRAM
Assumes at least 266Mhz memory as no attempt is made to clock
the chipset down if slower memory is installed.
So far tested on:
256 Mb 266Mhz 1 Bank (i.e. single sided)
256 Mb 266Mhz 2 Bank (i.e. double sided)
512 Mb 266Mhz 2 Bank (i.e. double sided)
*/
/* ported and enhanced from assembler level code in Linuxbios v1 */
#include <cpu/x86/mtrr.h>
#include "raminit.h"
/*
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
*/
/*
* 11/26/02 - kevinh@ispiri.com - The existing comments implied that
* this didn't work yet. Therefore, I've updated it so that it works
* correctly - at least on my VIA epia motherboard. 64MB DIMM in slot 0.
*/
/* Added automatic detection of first equipped bank and its MA mapping type.
* (Rest of configuration is done in C)
* 5/19/03 by SONE Takeshi <ts1@tsn.or.jp>
*/
/* converted to C 9/2003 Ron Minnich */
/* Set to 1 if your DIMMs are PC133 Note that I'm assuming CPU's FSB
* frequency is 133MHz. If your CPU runs at another bus speed, you
* might need to change some of register values.
*/
#ifndef DIMM_PC133
#define DIMM_PC133 0
#endif
// Set to 1 if your DIMMs are CL=2
#ifndef DIMM_CL2
#define DIMM_CL2 0
#endif
void dimm_read(unsigned long x)
void dimm_read(unsigned long bank,unsigned long x)
{
unsigned long eax;
//unsigned long eax;
volatile unsigned long y;
eax = x;
y = * (volatile unsigned long *) eax;
//eax = x;
y = * (volatile unsigned long *) (x+ bank) ;
}
void dimms_write(int x)
{
uint8_t c;
unsigned long eax = x;
for(c = 0; c < 6; c++) {
*(volatile unsigned long *) eax = 0;
eax += 0x10000000;
}
}
#ifdef DEBUG_SETNORTHB
void setnorthb(device_t north, uint8_t reg, uint8_t val)
{
print_debug("setnorth: reg ");
print_debug_hex8(reg);
print_debug(" to ");
print_debug_hex8(val);
print_debug("\r\n");
pci_write_config8(north, reg, val);
}
#else
#define setnorthb pci_write_config8
#endif
void
dumpnorth(device_t north)
@ -100,47 +59,242 @@ dumpnorth(device_t north)
print_debug("\r\n");
}
}
void print_val(char *str, int val)
{
print_debug(str);
print_debug_hex8(val);
}
static void sdram_set_registers(const struct mem_controller *ctrl)
static void ddr_ram_setup(const struct mem_controller *ctrl)
{
device_t north = (device_t) 0;
uint8_t c, r;
uint8_t b, c, bank;
uint16_t i,j;
unsigned long bank_address;
print_err("vt8623 init starting\r\n");
north = pci_locate_device(PCI_ID(0x1106, 0x3123), 0);
north = 0;
print_debug_hex32(north);
print_debug(" is the north\r\n");
print_debug_hex16(pci_read_config16(north, 0));
print_debug(" ");
print_debug_hex16(pci_read_config16(north, 2));
print_debug("\r\n");
/* All we are doing now is setting initial known-good values that will
* be revised later as we read SPD
*/
pci_write_config8(north,0x75,0x08);
/* since we only support epia-m at the moment, only ddr is supported */
/* setup cpu */
pci_write_config8(north,0x50,0xc8);
pci_write_config8(north,0x51,0xde);
pci_write_config8(north,0x52,0xcf);
pci_write_config8(north,0x53,0x88);
pci_write_config8(north,0x55,0x07);
pci_write_config8(north,0x55,0x04);
/* DRAM MA Map Type */
pci_write_config8(north,0x58,0xe0);
/*
DRAM MA Map Type Device 0 Offset 58
Determine memory addressing based on the module's memory technology and
arrangement. See Table 4-9 of Intel's 82443GX datasheet for details.
Bank 1/0 MA map type 58[7-5]
Bank 1/0 command rate 58[4]
Bank 3/2 MA map type 58[3-1]
Bank 3/2 command rate 58[0]
Read SPD byte 17, Number of banks on SDRAM device.
*/
c = 0;
b = smbus_read_byte(0xa0,17);
print_val("Detecting Memory\r\nNumber of Banks ",b);
if( b != 2 ){ // not 16 Mb type
/*
Read SPD byte 3, Number of row addresses.
*/
b = smbus_read_byte(0xa0,3);
print_val("\r\nNumber of Rows ",b);
if( b >= 0x0d ){ // not 64/128Mb (rows <=12)
/*
Read SPD byte 13, Primary DRAM width.
*/
b = smbus_read_byte(0xa0,13);
print_val("\r\nPriamry DRAM width",b);
if( b != 4 ) // mot 64/128Mb (x4)
c = 0x80; // 256Mb
}
/*
64/128Mb chip
Read SPD byte 4, Number of column addresses.
*/
b = smbus_read_byte(0xa0,4);
print_val("\r\nNo Columns ",b);
if( b == 10 || b == 11 ) c |= 0x60; // 10/11 bit col addr
if( b == 9 ) c |= 0x40; // 9 bit col addr
if( b == 8 ) c |= 0x20; // 8 bit col addr
}
print_val("\r\nMA type ",c);
pci_write_config8(north,0x58,c);
/*
DRAM bank size. See 4.3.1 pg 35
5a->5d set to end address for each bank. 1 bit == 16MB
5a = bank 0
5b = bank 0 + b1
5c = bank 0 + b1 + b2
5d = bank 0 + b1 + b2 + b3
*/
// Read SPD byte 31 Module bank density
c = 0;
b = smbus_read_byte(0xa0,31);
if( b & 0x02 ) c = 0x80; // 2GB
else if( b & 0x01) c = 0x40; // 1GB
else if( b & 0x80) c = 0x20; // 512Mb
else if( b & 0x40) c = 0x10; // 256Mb
else if( b & 0x20) c = 0x08; // 128Mb
else if( b & 0x10) c = 0x04; // 64Mb
else if( b & 0x08) c = 0x02; // 32Mb
else if( b & 0x04) c = 0x01; // 16Mb / 4Gb
else c = 0x01; // Error, use default
print_val("\r\nBank 0 (*16 Mb) ",c);
// set bank zero size
pci_write_config8(north,0x5a,c);
// SPD byte 5 # of physical banks
b = smbus_read_byte(0xa0,5);
print_val("\r\nNo Physical Banks ",b);
if( b == 2)
c <<=1;
print_val("\r\nTotal Memory (*16 Mb) ",c);
// set banks 1,2,3
pci_write_config8(north,0x5b,c);
pci_write_config8(north,0x5c,c);
pci_write_config8(north,0x5d,c);
/* Read SPD byte 18 CAS Latency */
b = smbus_read_byte(0xa0,18);
print_debug("\r\nCAS Supported ");
if(b & 0x04)
print_debug("2 ");
if(b & 0x08)
print_debug("2.5 ");
if(b & 0x10)
print_debug("3");
print_val("\r\nCycle time at CL X (nS)",smbus_read_byte(0xa0,9));
print_val("\r\nCycle time at CL X-0.5 (nS)",smbus_read_byte(0xa0,23));
print_val("\r\nCycle time at CL X-1 (nS)",smbus_read_byte(0xa0,25));
if( b & 0x10 ){ // DDR offering optional CAS 3
print_debug("\r\nStarting at CAS 3");
c = 0x30;
/* see if we can better it */
if( b & 0x08 ){ // DDR mandatory CAS 2.5
if( smbus_read_byte(0xa0,23) <= 0x75 ){ // we can manage 133Mhz at CAS 2.5
print_debug("\r\nWe can do CAS 2.5");
c = 0x20;
}
}
if( b & 0x04 ){ // DDR mandatory CAS 2
if( smbus_read_byte(0xa0,25) <= 0x75 ){ // we can manage 133Mhz at CAS 2
print_debug("\r\nWe can do CAS 2");
c = 0x10;
}
}
}else{ // no optional CAS values just 2 & 2.5
print_debug("\r\nStarting at CAS 2.5");
c = 0x20; // assume CAS 2.5
if( b & 0x04){ // Should always happen
if( smbus_read_byte(0xa0,23) <= 0x75){ // we can manage 133Mhz at CAS 2
print_debug("\r\nWe can do CAS 2");
c = 0x10;
}
}
}
/*
DRAM Timing Device 0 Offset 64
Row pre-charge 64[7]
RAS Pulse width 64[6]
CAS Latency 64[5,4]
SDR DDR
00 1T -
01 2T 2T
10 3T 2.5T
11 - 3T
RAS/CAS delay 64[2]
Bank Interleave 64[1,0]
Determine row pre-charge time (tRP)
T nS SPD*4 SPD
1T 7.5 0x1e
2T 15 0x3c
3T 22.5 0x5a
4T 30 0x1e
5T 37.5 0x25 .5?
6T 45 0x2d
Read SPD byte 27, min row pre-charge time.
*/
b = smbus_read_byte(0xa0,27);
print_val("\r\ntRP ",b);
if( b > 0x3c ) // set tRP = 3T
c |= 0x80;
/*
Determine RAS to CAS delay (tRCD)
Read SPD byte 29, min row pre-charge time.
*/
b = smbus_read_byte(0xa0,29);
print_val("\r\ntRCD ",b);
if( b > 0x3c ) // set tRCD = 3T
c |= 0x04;
/*
Determine RAS pulse width (tRAS)
Read SPD byte 30, device min active to pre-charge time.
*/
b = smbus_read_byte(0xa0,30);
print_val("\r\ntRAS ",b);
if( b > 0x25 ) // set tRAS = 6T
c |= 0x40;
/*
Determine bank interleave
Read SPD byte 17, Number of banks on SDRAM device.
*/
b = smbus_read_byte(0xa0,17);
if( b == 4) c |= 0x02;
else if (b == 2) c |= 0x01;
/* DRAM bank 0 - 3 size = 512M */
pci_write_config8(north,0x5a,0x10);
pci_write_config8(north,0x5b,0x10);
pci_write_config8(north,0x5c,0x10);
pci_write_config8(north,0x5d,0x10);
/* set DRAM timing for all banks */
pci_write_config8(north,0x64,0xe6);
pci_write_config8(north,0x64,c);
/* set DRAM type to DDR */
pci_write_config8(north,0x60,0x02);
@ -148,198 +302,284 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
/* DRAM arbitration timer */
pci_write_config8(north,0x65,0x32);
pci_write_config8(north,0x66,0x01);
pci_write_config8(north,0x68,0x59);
/* DRAM Frequency */
/*
CPU Frequency Device 0 Offset 54
CPU Frequency 54[7,6] bootstraps at 0xc0 (133Mhz)
DRAM burst length = 8 54[5]
*/
pci_write_config8(north,0x54,0xe0);
/*
DRAM Clock Device 0 Offset 69
DRAM/CPU speed 69[7,6] (leave at default 00 == CPU)
Controller que > 2 69[5]
Controller que != 4 69[4]
DRAM 8k page size 69[3]
DRAM 4k page size 69[2]
Multiple page mode 69[0]
*/
pci_write_config8(north,0x69,0x2d);
/* Delay >= 100ns after DRAM Frequency adjust, See 4.1.1.3 pg 15 */
udelay(200);
/* Enable CKE */
pci_write_config8(north,0x6b,0x10);
udelay(200);
/* Disable DRAM refresh */
pci_write_config8(north,0x6a,0x0);
/* set heavy drive */
pci_write_config8(north,0x6d,0x44);
pci_write_config8(north,0x61,0xff);
/* Set drive for 1 bank DDR (Table 4.4.2, pg 40) */
pci_write_config8(north,0x6d,0x044);
pci_write_config8(north,0x67,0x3a);
b = smbus_read_byte(0xa0,5); // SPD byte 5 # of physical banks
if( b > 1) {
// Increase drive control when there is more than 1 physical bank
pci_write_config8(north,0x6c,0x84); // Drive control: MA, DQS, MD/CKE
pci_write_config8(north,0x6d,0x55); // DC: Early clock select, DQM, CS#, MD
}
/* place frame buffer on last bank */
if( !b) b++; // make sure at least 1 bank reported
pci_write_config8(north,0xe3,b-1);
/* slot is the dram slot. Return size of side0 in lower 16-bit,
* side1 in upper 16-bit, in units of 8MB */
static unsigned long
spd_module_size(unsigned char slot)
{
/* for all the DRAMS, see if they are there and get the size of each
* module. This is just a very early first cut at sizing.
for( bank = 0 , bank_address=0; bank < b ; bank++){
/*
DDR init described in Via BIOS Porting Guide. Pg 28 (4.2.3.1)
*/
/* we may run out of registers ... */
unsigned int banks, rows, cols, reg;
unsigned int value = 0;
unsigned int module = ((0x50 + slot) << 1) + 1;
/* is the module there? if byte 2 is not 4, then we'll assume it
* is useless.
*/
print_info("Slot ");
print_info_hex8(slot);
if (smbus_read_byte(module, 2) != 4) {
print_info(" is empty\r\n");
return 0;
}
print_info(" is SDRAM ");
banks = smbus_read_byte(module, 17);
/* we're going to assume symmetric banks. Sorry. */
cols = smbus_read_byte(module, 4) & 0xf;
rows = smbus_read_byte(module, 3) & 0xf;
/* grand total. You have rows+cols addressing, * times of banks, times
* width of data in bytes */
/* Width is assumed to be 64 bits == 8 bytes */
value = (1 << (cols + rows)) * banks * 8;
print_info_hex32(value);
print_info(" bytes ");
/* Return in 8MB units */
value >>= 23;
/* We should have single or double side */
if (smbus_read_byte(module, 5) == 2) {
print_info("x2");
value = (value << 16) | value;
}
print_info("\r\n");
return value;
}
static int
spd_num_chips(unsigned char slot)
{
unsigned int module = ((0x50 + slot) << 1) + 1;
unsigned int width;
width = smbus_read_byte(module, 13);
if (width == 0)
width = 8;
return 64 / width;
}
static void sdram_set_spd_registers(const struct mem_controller *ctrl)
{
#define T133 7
unsigned char Trp = 1, Tras = 1, casl = 2, val;
unsigned char timing = 0xe4;
/* read Trp */
val = smbus_read_byte(0xa0, 27);
if (val < 2*T133)
Trp = 1;
val = smbus_read_byte(0xa0, 30);
if (val < 5*T133)
Tras = 0;
val = smbus_read_byte(0xa0, 18);
if (val < 8)
casl = 1;
if (val < 4)
casl = 0;
val = (Trp << 7) | (Tras << 6) | (casl << 4) | 4;
print_debug_hex8(val); print_debug(" is the computed timing\r\n");
/* don't set it. Experience shows that this screwy chipset should just
* be run with the most conservative timing.
* pci_write_config8(0, 0x64, val);
*/
}
static void set_ma_mapping(device_t north, int slot, int type)
{
unsigned char reg, val;
int shift;
reg = 0x58 + slot/2;
if (slot%2 >= 1)
shift = 0;
else
shift = 4;
val = pci_read_config8(north, reg);
val &= ~(0xf << shift);
val |= type << shift;
pci_write_config8(north, reg, val);
}
static void sdram_enable(int controllers, const struct mem_controller *ctrl)
{
unsigned char i;
static const uint8_t ramregs[] = {
0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
};
device_t north = 0;
uint32_t size, base, slot, ma;
/* NOP command enable */
pci_write_config8(north,0x6b,0x01);
pci_write_config8(north,0x6b,0x11);
/* read a double word from any addree of the dimm */
dimm_read(0x1f000);
udelay(200);
/* read a double word from any address of the dimm */
dimm_read(bank_address,0x1f000);
//udelay(200);
/* All bank precharge Command Enable */
pci_write_config8(north,0x6b,0x02);
dimm_read(0x1f000);
pci_write_config8(north,0x6b,0x12);
dimm_read(bank_address,0x1f000);
/* MSR Enable */
pci_write_config8(north,0x6b,0x03);
dimm_read(0x2000);
dimm_read(0x800);
pci_write_config8(north,0x6b,0x13);
dimm_read(bank_address,0x2000);
udelay(1);
dimm_read(bank_address,0x800);
udelay(1);
/* All banks precharge Command Enable */
pci_write_config8(north,0x6b,0x02);
dimm_read(0x1f200);
pci_write_config8(north,0x6b,0x12);
dimm_read(bank_address,0x1f200);
/* CBR Cycle Enable */
pci_write_config8(north,0x6b,0x04);
pci_write_config8(north,0x6b,0x14);
/* Read 8 times */
dimm_read(0x1f300);
dimm_read(bank_address,0x1f300);
udelay(100);
dimm_read(0x1f400);
dimm_read(bank_address,0x1f400);
udelay(100);
dimm_read(0x1f500);
dimm_read(bank_address,0x1f500);
udelay(100);
dimm_read(0x1f600);
dimm_read(bank_address,0x1f600);
udelay(100);
dimm_read(0x1f700);
dimm_read(bank_address,0x1f700);
udelay(100);
dimm_read(0x1f800);
dimm_read(bank_address,0x1f800);
udelay(100);
dimm_read(0x1f900);
dimm_read(bank_address,0x1f900);
udelay(100);
dimm_read(0x1fa00);
dimm_read(bank_address,0x1fa00);
udelay(100);
/* MSR Enable */
pci_write_config8(north,0x6b,0x03);
pci_write_config8(north,0x6b,0x13);
/* 0x150 if CAS Latency 2 or 0x350 CAS Latency 2.5 */
dimm_read(0x350);
/*
Mode Register Definition
with adjustement so that address calculation is correct - 64 bit technology, therefore
a0-a2 refer to byte within a 64 bit long word, and a3 is the first address line presented
to DIMM as a row or column address.
MR[9-7] CAS Latency
MR[6] Burst Type 0 = sequential, 1 = interleaved
MR[5-3] burst length 001 = 2, 010 = 4, 011 = 8, others reserved
MR[0-2] dont care
CAS Latency
000 reserved
001 reserved
010 2
011 3
100 reserved
101 1.5
110 2.5
111 reserved
CAS 2 0101011000 = 0x158
CAS 2.5 1101011000 = 0x358
CAS 3 0111011000 = 0x1d8
*/
c = pci_read_config8(north,0x64);
if( (c & 0x30) == 0x10 )
dimm_read(bank_address,0x150);
else if((c & 0x30) == 0x20 )
dimm_read(bank_address,0x350);
else
dimm_read(bank_address,0x1d0);
//dimm_read(bank_address,0x350);
/* Normal SDRAM Mode */
pci_write_config8(north,0x6b,0x58 );
/* Set the refresh rate */
bank_address = pci_read_config8(north,0x5a+bank) * 0x1000000;
} // end of for each bank
/* Adjust DQS (data strobe output delay). See 4.2.3.2 pg 29 */
pci_write_config8(north,0x66,0x41);
/* determine low bond */
if( b == 2)
bank_address = pci_read_config8(north,0x5a) * 0x1000000;
else
bank_address = 0;
for(i = 0 ; i < 0x0ff; i++){
c = i ^ (i>>1); // convert to gray code
pci_write_config8(north,0x68,c);
// clear
*(volatile unsigned long*)(0x4000) = 0;
*(volatile unsigned long*)(0x4100+bank_address) = 0;
*(volatile unsigned long*)(0x4200) = 0;
*(volatile unsigned long*)(0x4300+bank_address) = 0;
*(volatile unsigned long*)(0x4400) = 0;
*(volatile unsigned long*)(0x4500+bank_address) = 0;
// fill
*(volatile unsigned long*)(0x4000) = 0x12345678;
*(volatile unsigned long*)(0x4100+bank_address) = 0x81234567;
*(volatile unsigned long*)(0x4200) = 0x78123456;
*(volatile unsigned long*)(0x4300+bank_address) = 0x67812345;
*(volatile unsigned long*)(0x4400) = 0x56781234;
*(volatile unsigned long*)(0x4500+bank_address) = 0x45678123;
// verify
if( *(volatile unsigned long*)(0x4000) != 0x12345678)
continue;
if( *(volatile unsigned long*)(0x4100+bank_address) != 0x81234567)
continue;
if( *(volatile unsigned long*)(0x4200) != 0x78123456)
continue;
if( *(volatile unsigned long*)(0x4300+bank_address) != 0x67812345)
continue;
if( *(volatile unsigned long*)(0x4400) != 0x56781234)
continue;
if( *(volatile unsigned long*)(0x4500+bank_address) != 0x45678123)
continue;
// if everything verified then found low bond
break;
}
print_val("\r\nLow Bond ",i);
if( i < 0xff ){
c = i++;
for( ; i <0xff ; i++){
pci_write_config8(north,0x68,i ^ (i>>1) );
// clear
*(volatile unsigned long*)(0x8000) = 0;
*(volatile unsigned long*)(0x8100+bank_address) = 0;
*(volatile unsigned long*)(0x8200) = 0x0;
*(volatile unsigned long*)(0x8300+bank_address) = 0;
*(volatile unsigned long*)(0x8400) = 0x0;
*(volatile unsigned long*)(0x8500+bank_address) = 0;
// fill
*(volatile unsigned long*)(0x8000) = 0x12345678;
*(volatile unsigned long*)(0x8100+bank_address) = 0x81234567;
*(volatile unsigned long*)(0x8200) = 0x78123456;
*(volatile unsigned long*)(0x8300+bank_address) = 0x67812345;
*(volatile unsigned long*)(0x8400) = 0x56781234;
*(volatile unsigned long*)(0x8500+bank_address) = 0x45678123;
// verify
if( *(volatile unsigned long*)(0x8000) != 0x12345678)
break;
if( *(volatile unsigned long*)(0x8100+bank_address) != 0x81234567)
break;
if( *(volatile unsigned long*)(0x8200) != 0x78123456)
break;
if( *(volatile unsigned long*)(0x8300+bank_address) != 0x67812345)
break;
if( *(volatile unsigned long*)(0x8400) != 0x56781234)
break;
if( *(volatile unsigned long*)(0x8500+bank_address) != 0x45678123)
break;
}
print_val(" High Bond",i);
c = ((i - c)<<1)/3 +c;
print_val(" Setting DQS delay",c);
c = c ^ (c>>1); // convert to gray code
pci_write_config8(north,0x68,c);
pci_write_config8(north,0x68,0x42);
}else{
print_debug("Unable to determine low bond - Setting default\r\n");
pci_write_config8(north,0x68,0x59);
}
pci_write_config8(north,0x66,0x01);
pci_write_config8(north,0x55,0x07);
/*
DRAM refresh rate Device 0 Offset 6a
Units of 16 DRAM clock cycles. (See 4.4.1 pg 39)
Rx69 (DRAM freq) Rx58 (chip tech) Rx6a
133Mhz 64/128Mb 0x86
133Mhz 256/512Mb 0x43
100Mhz 64/128Mb 0x65
100Mhz 256/512Mb 0x32
*/
b = pci_read_config8(north,0x58);
if( b < 0x80 ) // 256 tech
pci_write_config8(north,0x6a,0x86);
else
pci_write_config8(north,0x6a,0x43);
pci_write_config8(north,0x67,0x22);
pci_write_config8(north,0x61,0xff);
//pci_write_config8(north,0x67,0x22);
/* pci */
pci_write_config8(north,0x70,0x82);
@ -351,14 +591,18 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
/* graphics aperture base */
pci_write_config8(north,0x13,0xd0);
//pci_write_config8(north,0x56,0x10);
//pci_write_config8(north,0x57,0x10);
//pci_write_config8(north,0xe1,0xdf);
//pci_write_config8(north,0xe2,0x42);
pci_write_config8(north,0xe0,0x00);
pci_write_config8(north,0x84,0x80);
pci_write_config16(north,0x80,0x610f);
pci_write_config32(north,0x88,0x00000002);
pci_write_config8(north,0xe0,0x80);
pci_write_config8(north,0xe1,0xdf);
pci_write_config8(north,0xe2,0x42);
pci_write_config8(north,0xa8,0x04);
pci_write_config8(north,0xac,0x2f);
@ -366,4 +610,18 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
print_err("vt8623 done\r\n");
dumpnorth(north);
print_err("AGP\r\n");
north = pci_locate_device(PCI_ID(0x1106, 0xb091), 0);
pci_write_config32(north,0x20,0xddf0dc00);
pci_write_config32(north,0x24,0xdbf0d800);
pci_write_config8(north,0x3e,0x0c);
//dumpnorth(north);
//print_err("VGA\n");
//north = pci_locate_device(PCI_ID(0x1106, 0x3122), 0);
//pci_write_config32(north,0x10,0xd8000008);
//pci_write_config32(north,0x14,0xdc000000);
//dumpnorth(north);
}

View File

@ -1,10 +1,11 @@
#ifndef _SOUTHBRIDGE_RICOH_RL5C476
#define _SOUTHBRIDGE_RICOH_RL5C476
extern struct chip_operations southbridge_ricoh_rl5c476_control;
extern struct chip_operations southbridge_ricoh_rl5c476_ops;
struct southbridge_ricoh_rl5c476_config {
int num;
int enable_cf;
};
#endif /* _SOUTHBRIDGE_RL5C476 */

View File

@ -14,10 +14,11 @@
*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* (C) Copyright 2005 Nick Barker <nick.barker@btinternet.com
brought into line with the current architecture of LinuxBios */
#include <arch/io.h>
@ -26,106 +27,43 @@
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include <device/cardbus.h>
#include "rl5c476.h"
#include "chip.h"
static int enable_cf_boot = 0;
static unsigned int cf_base;
static void udelay(int i){
for(; i > 0 ; i--)
inb(0x80);
}
static void
dump_south(void)
{
device_t dev0;
dev0 = dev_find_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, 0);
dev0 = dev_find_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, dev0);
int i,j;
for(i = 0; i < 256; i += 16) {
printk_debug("0x%x: ", i);
for(j = 0; j < 16; j++) {
printk_debug("%02x ", pci_read_config8(dev0, i+j));
}
printk_debug("\n");
}
printk_debug("Card32\n");
for(i = 0 ; i < 256 ; i+=16){
printk_debug("0x%x: ",i);
for(j = 0 ; j < 16 ; j++){
printk_debug(" %02x",*(unsigned char *)(0x80000000+i+j));
}
printk_debug("\n");
}
printk_debug("Card16\n");
for(i = 0; i < 256; i += 16) {
printk_debug("0x%x: ", i);
for(j = 0; j < 16; j++) {
printk_debug("%02x ", *(unsigned char *)(0x80000800+ i+j));
}
printk_debug("\n");
}
printk_debug("CF Config\n");
for(i = 0 ; i < 256 ; i+=16){
printk_debug("0x%x: ",i);
for(j=0 ; j < 16 ; j++){
printk_debug("%02x ",*(unsigned char *)(0x81000200 + i + j));
}
printk_debug("\n");
}
}
static void rl5c476_init(device_t dev)
{
//unsigned char enables;
pc16reg_t *pc16;
int i;
#error "FIXME implement carbus bridge support"
#error "FIXME this code is close to a but the conversion needs more work"
unsigned char *base;
/* cardbus controller function 1 for CF Socket */
printk_debug("rl5c476 init\n");
/* setup pci header manually because 'pci_device.c' doesn't know how to handle
* pci to cardbus bridges - (header type 2 I think)
*/
printk_debug("CF Base = %0x\n",cf_base);
/* initialize function zero - pcmcia socket so it behaves itself */
/* FIXME - statically put control memory at 0xe0000000 for now
* one day the pci_device allocator might do this */
pci_write_config32(dev,0x10,0xe0000000);
pci_write_config8(dev,0x0d,0x20);
pci_write_config8(dev,0x19,0x02);
pci_write_config8(dev,0x1a,0x02);
pci_write_config8(dev,0x1b,0x20);
//pci_write_config8(dev,0x3c,0);
pci_write_config8(dev,0x82,0x00a0);
pci_write_config16(dev,0x04,0x07);
/* get second function - i.e. compact flash socket */
dev = dev_find_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, dev);
/* FIXME - control structure statically declared at 0xe0008000 for now */
pci_write_config32(dev,0x10,0xe0008000);
pci_write_config8(dev,0x0d,0x20);
pci_write_config8(dev,0x19,0x03);
pci_write_config8(dev,0x1a,0x03);
pci_write_config8(dev,0x1b,0x20);
//pci_write_config8(dev,0x3c,0x0);
pci_write_config16(dev,0x3e,0x0780);
/* misc control register */
pci_write_config16(dev,0x82,0x00a0);
pci_write_config16(dev,0x04,0x07);
/* set up second slot as compact flash port if asked to do so */
if( enable_cf_boot && (PCI_FUNC(dev->path.u.pci.devfn) == 1)){
/* make sure isa interrupts are enabled */
pci_write_config16(dev,0x3e,0x0780);
/* pick up where 16 bit card control structure is */
pc16 = (pc16reg_t *)(0xe0008800);
/* pick up where 16 bit card control structure is (0x800 bytes into config structure) */
base = (unsigned char *)pci_read_config32(dev,0x10);
pc16 = (pc16reg_t *)(base + 0x800);
/* disable memory and io windows and turn off socket power */
pc16->pwctrl = 0;
@ -139,38 +77,45 @@ static void rl5c476_init(device_t dev)
/* reset card, configure for I/O and set IRQ line */
pc16->igctrl = 0x69;
// set io window 0 for 1e8 - 1ef
pc16->iostl0 = 0xe8;
// set io window 0 for 1e0 - 1ef
/* note this now sets CF up on a contiguous I/O window of 16 bytes, 0x1e0 to 0x1ef
Be warned that this is not a standard IDE address as automatically detected by the likes
of Filo, and would need patching to recognise these addresses as an IDE drive */
/* an earlier version of this driver set up 2 io windows to emulate the expected addresses
for IDE2, however the pcmcia package within Linux then could not re-initiailse the
device as it tried to take control of it. So I belive it is easier to patch Filo or the like
to pick up this drive rather than playing silly games as the kernel tries to boot.
*/
pc16->iostl0 = 0xe0;
pc16->iosth0 = 1;
pc16->iospl0 = 0xef;
pc16->iosph0 = 1;
// add io offset of 8 so that CF card will decode 0x1e8 as 0x1f0 i.e. the first byte of
// a 16 byte aligned, 16 byte window etc
pc16->ioffl0 = 0x8;
pc16->ioffl0 = 0;
pc16->ioffh0 = 0;
// set io window 1 for 3ed - 3ee
pc16->iostl1 = 0xed;
pc16->iosth1 = 3;
// clear window 1
pc16->iostl1 = 0;
pc16->iosth1 = 0;
pc16->iospl1 = 0xee;
pc16->iosph1 = 3;
pc16->iospl1 = 0;
pc16->iosph1 = 0;
pc16->ioffl1 = 0x0;
pc16->ioffh1 = 0;
// FIXME statically declare CF config window at 0xe1000000
pc16->smstl0 = 0;
pc16->smsth0 = 0;
pc16->smspl0 = 0;
pc16->smsph0 = 0x80;
// set up CF config window
pc16->smpga0 = cf_base>>24;
pc16->smsth0 = (cf_base>>20)&0x0f;
pc16->smstl0 = (cf_base>>12)&0xff;
pc16->smsph0 = ((cf_base>>20)&0x0f) | 0x80;
pc16->smspl0 = (cf_base>>12)&0xff;
pc16->moffl0 = 0;
pc16->moffh0 = 0x40;
pc16->smpga0 = 0xe1;
// set I/O width for Auto Data width
pc16->ioctrl = 0x22;
@ -191,29 +136,65 @@ static void rl5c476_init(device_t dev)
pc16->igctrl = 0x69;
unsigned char *cptr;
cptr = (unsigned char *)(0xe1000200);
printk_debug("CF Config = %x\n",*cptr);
// FIX Me 16 bit CF always have first config byte at 0x200 into Config structure,
// 16 bit CF always have first config byte at 0x200 into Config structure,
// but CF+ May Not according to spec - should locate through reading tuple data,
// but this will do for now !!!
unsigned char *cptr;
cptr = (unsigned char *)(cf_base + 0x200);
printk_debug("CF Config = %x\n",*cptr);
// set CF to decode 16 IO bytes on any 16 byte boundary - rely on the io
// windows of the bridge set up above to map those bytes into the
// addresses for ide controller 3 (0x1e8 - 0x1ef and 0x3ed - 0x3ee)
*cptr = 0x41;
}
}
void rl5c476_read_resources(device_t dev)
{
struct resource *resource;
/* for cf socket we need an extra memory window for the control structure of the cf itself */
if( enable_cf_boot && (PCI_FUNC(dev->path.u.pci.devfn) == 1)){
resource = new_resource(dev,1); /* fake index as it isn't in pci config space */
resource->flags |= IORESOURCE_MEM ;
resource->size = 0x1000;
resource->align = resource->gran = 12;
resource->limit= 0xffff0000;
//compute_allocate_resource(&dev->link[0],resource,resource->flags,resource->flags);
}
cardbus_read_resources(dev);
}
void rl5c476_set_resources(device_t dev)
{
struct resource *resource;
printk_debug("%s In set resources \n",dev_path(dev));
if( enable_cf_boot && (PCI_FUNC(dev->path.u.pci.devfn) == 1)){
resource = find_resource(dev,1);
if( !(resource->flags & IORESOURCE_STORED) ){
resource->flags |= IORESOURCE_STORED ;
compute_allocate_resource(&dev->link[0],resource,resource->flags,resource->flags);
printk_debug("%s 1 ==> %x\n",dev_path(dev),resource->base);
cf_base = resource->base;
}
}
pci_dev_set_resources(dev);
}
static struct device_operations ricoh_rl5c476_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.inti = rl5c476_init,
.scan_bus = pci_scan_bridge,
.read_resources = rl5c476_read_resources,
.set_resources = rl5c476_set_resources,
.enable_resources = cardbus_enable_resources,
.init = rl5c476_init,
.scan_bus = cardbus_scan_bridge,
};
static struct pci_driver ricoh_rl5c476_driver __pci_driver = {
@ -222,7 +203,15 @@ static struct pci_driver ricoh_rl5c476_driver __pci_driver = {
.device = PCI_DEVICE_ID_RICOH_RL5C476,
};
struct chip_operations southbridge_ricoh_rl5c476_control = {
void southbridge_init(device_t dev)
{
struct southbridge_ricoh_rl5c476_config *conf = dev->chip_info;
enable_cf_boot = conf->enable_cf;
}
struct chip_operations southbridge_ricoh_rl5c476_ops = {
CHIP_NAME("RICOH RL5C476")
.enable = southbridge_init,
.enable_dev = southbridge_init,
};

View File

@ -14,8 +14,8 @@
*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* rl5c476 routines and defines*/

View File

@ -10,7 +10,7 @@
/*
* Base VT8235.
*/
static device_t lpc_dev;
static int enabled = 0;
void hard_reset(void)
{
@ -22,18 +22,15 @@ static void keyboard_on(struct device *dev)
unsigned char regval;
regval = pci_read_config8(dev, 0x51);
// regval |= 0x0f;
/* !!!FIX let's try this */
regval |= 0x1d;
regval |= 0x05;
regval &= 0xfd;
pci_write_config8(dev, 0x51, regval);
init_pc_keyboard(0x60, 0x64, 0);
}
void dump_south(void)
void dump_south(device_t dev0)
{
device_t dev0;
dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, 0);
int i,j;
for(i = 0; i < 256; i += 16) {
@ -45,23 +42,53 @@ void dump_south(void)
}
}
void set_led(struct device *dev)
void set_led()
{
// set power led to steady now that lxbios has virtually done its job
device_t dev;
dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, 0);
pci_write_config8(dev, 0x94, 0xb0);
}
static void vt8235_enable(struct device *dev)
{
struct southbridge_via_vt8235_config *conf = dev->chip_info;
unsigned char regval;
unsigned short vendor,model;
vendor = pci_read_config16(dev,0);
model = pci_read_config16(dev,0x2);
printk_debug("In vt8235_enable %04x %04x.\n",vendor,model);
/* if this is not the southbridge itself just return */
/* this is necessary because USB devices are slot 10, whereas this device is slot 11
therefore usb devices get called first during the bus scan */
if( (vendor != PCI_VENDOR_ID_VIA) || (model != PCI_DEVICE_ID_VIA_8235))
return;
printk_debug("Initialising Devices\n");
setup_i8259(); // make sure interupt controller is configured before keyboard init
/* enable RTC and ethernet */
regval = pci_read_config8(dev, 0x51);
regval |= 0x18;
pci_write_config8(dev, 0x51, regval);
/* turn on keyboard */
keyboard_on(dev);
/* enable USB 1.1 & USB 2.0 -redundant really since we've already been there - see note above*/
regval = pci_read_config8(dev, 0x50);
regval &= ~(0x36);
pci_write_config8(dev, 0x50, regval);
printk_debug("In vt8235_enable.\n");
if (!lpc_dev) {
lpc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_8235, 0);
if (conf->enable_keyboard)
keyboard_on(lpc_dev);
}
}
struct chip_operations southbridge_via_vt8235_ops = {

View File

@ -17,8 +17,8 @@
*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* winbond access routines and defines*/

View File

@ -13,7 +13,7 @@ static void ide_init(struct device *dev)
printk_info("Enabling VIA IDE.\n");
if (!conf->enable_native_ide) {
/*if (!conf->enable_native_ide) { */
/*
* Run the IDE controller in 'compatiblity mode - i.e. don't
* use PCI interrupts. Using PCI ints confuses linux for some
@ -28,7 +28,7 @@ static void ide_init(struct device *dev)
enables = pci_read_config8(dev, 0x42);
printk_debug("enables in reg 0x42 read back as 0x%x\n",
enables);
}
/* } */
enables = pci_read_config8(dev, 0x40);
printk_debug("enables in reg 0x40 0x%x\n", enables);

View File

@ -10,21 +10,30 @@
#include "vt8235.h"
#include "chip.h"
/*
* Taken some liberties - changed irq structures to pins numbers so that it is
* easier to change PCI irq assignments without having to change each PCI
* function individually
*
* pciIrqs contains the irqs assigned for PCI pins A-D
*
* Setting will depend on motherboard as irqs can be quite scarce e.g on
* EPIA-MII, 16 bit CF card wants a dedicated IRQ. A 16 bit card in pcmcia
* socket may want another - for now only claim 3 interupts for PCI, leaving at
* least one spare for CF. On EPIA-M one could allocated all four irqs to
* different numbers since there are no cardbus devices
*/
/* The epia-m is really short on interrupts available, so PCI interupts A & D are ganged togther and so are B & C.
This is how the Award bios sets it up too.
epia can be more generous as it does not need to reserve interrupts for cardbus devices, but if changed then
make sure that ACPI dsdt is changed to suit.
static const unsigned char pciIrqs[4] = { 11 , 5, 10 , 12 };
IRQ 0 = timer
IRQ 1 = keyboard
IRQ 2 = cascade
IRQ 3 = COM 2
IRQ 4 = COM 1
IRQ 5 = available for PCI interrupts
IRQ 6 = floppy or availbale for PCI if floppy controller disabled
IRQ 7 = LPT or available if LPT port disabled
IRQ 8 = rtc
IRQ 9 = available for PCI interrupts
IRQ 10 = cardbus slot or available for PCI if no cardbus (ie epia)
IRQ 11 = cardbus slot or available for PCI if no cardbus (ie epia)
IRQ 12 = PS2 mouse (hardwired to 12)
IRQ 13 = legacy FPU interrupt
IRQ 14 = IDE controller 1
IRQ 15 = IDE controller 2
*/
static const unsigned char pciIrqs[4] = { 5 , 9 , 9, 5 };
static const unsigned char usbPins[4] = { 'A','B','C','D'};
static const unsigned char enetPins[4] = { 'A','B','C','D'};
@ -32,14 +41,9 @@ static const unsigned char slotPins[4] = { 'B','C','D','A'};
static const unsigned char firewirePins[4] = { 'B','C','D','A'};
static const unsigned char vt8235Pins[4] = { 'A','B','C','D'};
static const unsigned char vgaPins[4] = { 'A','B','C','D'};
static const unsigned char cbPins[4] = { 'A','B','C','D'};
static const unsigned char cbPins[4] = { 'D','A','B','C'};
static const unsigned char riserPins[4] = { 'A','B','C','D'};
/*
Our IDSEL mappings are as follows
PCI slot is AD31 (device 15) (00:14.0)
Southbridge is AD28 (device 12) (00:11.0)
*/
static unsigned char *pin_to_irq(const unsigned char *pin)
{
@ -54,19 +58,12 @@ static unsigned char *pin_to_irq(const unsigned char *pin)
static void pci_routing_fixup(struct device *dev)
{
printk_info("%s: dev is %p\n", __FUNCTION__, dev);
if (dev) {
/* initialize PCI interupts - these assignments depend
on the PCB routing of PINTA-D
PINTA = IRQ11
PINTB = IRQ5
PINTC = IRQ10
PINTD = IRQ12
*/
/* set up PCI IRQ routing */
pci_write_config8(dev, 0x55, pciIrqs[0] << 4);
pci_write_config8(dev, 0x56, pciIrqs[1] | (pciIrqs[2] << 4) );
pci_write_config8(dev, 0x57, pciIrqs[3] << 4);
}
// firewire built into southbridge
printk_info("setting firewire\n");
@ -201,12 +198,6 @@ static void vt8235_init(struct device *dev)
// Set 0x58 to 0x03 to match Award
pci_write_config8(dev, 0x58, 0x03);
// enable the ethernet/RTC
if (dev) {
enables = pci_read_config8(dev, 0x51);
enables |= 0x18;
pci_write_config8(dev, 0x51, enables);
}
/* enable serial irq */
pci_write_config8(dev, 0x52, 0x9);
@ -224,6 +215,36 @@ static void vt8235_init(struct device *dev)
rtc_init(0);
}
/* total kludge to get lxb to call our childrens set/enable functions - these are not called unless this
device has a resource to set - so set a dummy one */
void vt8235_read_resources(device_t dev)
{
struct resource *resource;
pci_dev_read_resources(dev);
resource = new_resource(dev, 1);
resource->flags |= IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO | IORESOURCE_STORED;
resource->size = 2;
resource->base = 0x2e;
}
void vt8235_set_resources(device_t dev)
{
struct resource *resource;
//resource = find_resource(dev,1);
//resource->flags |= IORESOURCE_STORED;
pci_dev_set_resources(dev);
}
void vt8235_enable_resources(device_t dev)
{
/* vt8235 is not a pci bridge and has no resources of its own (other than standard PC i/o addresses)
however it does control the isa bus and so we need to manually call enable childrens resources on that bus */
pci_dev_enable_resources(dev);
enable_childrens_resources(dev);
}
static void southbridge_init(struct device *dev)
{
vt8235_init(dev);
@ -231,9 +252,9 @@ static void southbridge_init(struct device *dev)
}
static struct device_operations vt8235_lpc_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.read_resources = vt8235_read_resources,
.set_resources = vt8235_set_resources,
.enable_resources = vt8235_enable_resources,
.init = &southbridge_init,
.scan_bus = scan_static_bus,
};

View File

@ -5,11 +5,14 @@
#include <device/pci_ids.h>
#include "vt8235.h"
/* really nothing to do here, both usb 1.1 & 2.0 are normal PCI devices and so get resources allocated
properly. They are part of the southbridge and are enabled in the chip enable function for the southbridge */
static void usb_init(struct device *dev)
{
printk_debug("Configuring VIA USB 1.1\n");
pci_write_config8(dev, 0x04, 0x07);
/* pci_write_config8(dev, 0x04, 0x07); */
/*
* To disable; though do we need to do this?
@ -25,6 +28,7 @@ static void usb_init(struct device *dev)
*/
}
/*
static struct device_operations usb_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
@ -39,3 +43,4 @@ static struct pci_driver northbridge_driver __pci_driver = {
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_82C586_2,
};
*/

View File

@ -14,8 +14,8 @@
*
* 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., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* vt1211 routines and defines*/
@ -58,6 +58,25 @@ static void pnp_exit_ext_func_mode(device_t dev)
outb(0xaa, dev->path.u.pnp.port);
}
static void vt1211_set_iobase(device_t dev, unsigned index, unsigned iobase)
{
switch (dev->path.u.pnp.device) {
case VT1211_FDC:
case VT1211_PP:
case VT1211_SP1:
case VT1211_SP2:
pnp_write_config(dev, index + 0, (iobase >> 2) & 0xff);
break;
case VT1211_HWM:
default:
pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
pnp_write_config(dev, index + 1, iobase & 0xff);
break;
}
}
static void init_hwm(unsigned long base)
{
int i;
@ -79,6 +98,9 @@ static void vt1211_init(struct device *dev)
}
switch (dev->path.u.pnp.device) {
case VT1211_FDC:
case VT1211_PP:
break;
case VT1211_SP1:
res0 = find_resource(dev, PNP_IDX_IO0);
init_uart8250(res0->base, &conf->com1);
@ -95,24 +117,12 @@ static void vt1211_init(struct device *dev)
printk_info("vt1211 asked to initialise unknown device!\n");
}
/* activate com2
start_conf_pnp(3);
write_pnp(0x60,0xbe);
write_pnp(0x70,0x3);
write_pnp(0xf0,0x02);
write_pnp(0x30,0x01);
end_conf_pnp();
// Activate the vt1211 hardware monitor
start_conf_pnp(0x0b);
write_pnp(0x60,0xec);
write_pnp(0x30,1);
end_conf_pnp(); */
}
void vt1211_pnp_enable_resources(device_t dev)
{
printk_debug("%s - enabling\n",dev_path(dev));
pnp_enter_ext_func_mode(dev);
pnp_enable_resources(dev);
pnp_exit_ext_func_mode(dev);
@ -120,8 +130,54 @@ void vt1211_pnp_enable_resources(device_t dev)
void vt1211_pnp_set_resources(struct device *dev)
{
int i;
struct resource *resource;
#if CONFIG_CONSOLE_SERIAL8250 == 1
if( dev->path.u.pnp.device == 2 ){
for( i = 0 ; i < dev->resources; i++){
resource = &dev->resource[i];
resource->flags |= IORESOURCE_STORED;
report_resource_stored(dev, resource, "");
}
return;
}
#endif
pnp_enter_ext_func_mode(dev);
pnp_set_resources(dev);
/* Select the device */
pnp_set_logical_device(dev);
/* Paranoia says I should disable the device here... */
for(i = 0; i < dev->resources; i++) {
resource = &dev->resource[i];
if (!(resource->flags & IORESOURCE_ASSIGNED)) {
printk_err("ERROR: %s %02x %s size: 0x%010Lx not assigned\n",
dev_path(dev), dev->resource->index,
resource_type(resource),
resource->size);
continue;
}
/* Now store the resource */
if (resource->flags & IORESOURCE_IO) {
vt1211_set_iobase(dev, resource->index, resource->base);
}
else if (resource->flags & IORESOURCE_DRQ) {
pnp_set_drq(dev, resource->index, resource->base);
}
else if (resource->flags & IORESOURCE_IRQ) {
pnp_set_irq(dev, resource->index, resource->base);
}
else {
printk_err("ERROR: %s %02x unknown resource type\n",
dev_path(dev), resource->index);
return;
}
resource->flags |= IORESOURCE_STORED;
report_resource_stored(dev, resource, "");
}
pnp_exit_ext_func_mode(dev);
}
@ -148,7 +204,7 @@ static struct pnp_info pnp_dev_info[] = {
{ &ops, VT1211_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
{ &ops, VT1211_SP1, PNP_IO0 | PNP_IRQ0, { 0x07f8, 0}, },
{ &ops, VT1211_SP2, PNP_IO0 | PNP_IRQ0, { 0x07f8, 0}, },
{ &ops, VT1211_HWM, PNP_IO0 , { 0xfff8, 0 }, },
{ &ops, VT1211_HWM, PNP_IO0 , { 0xff00, 0 }, },
};
static void enable_dev(struct device *dev)

View File

@ -18,7 +18,7 @@ option HAVE_FALLBACK_BOOT=1
### Compute the location and size of where this firmware image
### (linuxBIOS plus bootloader) will live in the boot rom chip.
###
option FALLBACK_SIZE=131072
option FALLBACK_SIZE=0x30000
## LinuxBIOS C code runs at this location in RAM
option _RAMBASE=0x00004000
@ -30,26 +30,32 @@ option _RAMBASE=0x00004000
###
#
# Via EPIA-M
# EPIA-M
#
romimage "normal"
option USE_FALLBACK_IMAGE=0
option ROM_IMAGE_SIZE=0x10000
option LINUXBIOS_EXTRA_VERSION=".0Normal"
#romimage "normal"
# option USE_FALLBACK_IMAGE=0
# option ROM_IMAGE_SIZE=0xc000
# option ROM_SECTION_OFFSET=0x10000
# option ROM_SECTION_SIZE=0x18000
# option XIP_ROM_BASE=0xfffd0000
# option LINUXBIOS_EXTRA_VERSION=".0Normal"
# payload /usr/share/etherboot/5.1.9pre2-lnxi-lb/tg3--ide_disk.zelf
# payload ../../../../tg3--ide_disk.zelf
# payload ../../../../../lnxieepro100.ebi
payload ../../../payloads/filo.elf
end
# payload /filo.elf
#end
romimage "fallback"
option USE_FALLBACK_IMAGE=1
option ROM_IMAGE_SIZE=0x10000
option ROM_SECTION_OFFSET=0x10000
option ROM_SECTION_SIZE=0x30000
# option XIP_ROM_BASE=0xfffe0000
option LINUXBIOS_EXTRA_VERSION=".0Fallback"
# payload /usr/share/etherboot/5.1.9pre2-lnxi-lb/tg3--ide_disk.zelf
# payload ../../../../tg3--ide_disk.zelf
# payload ../../../../../lnxieepro100.ebi
payload ../../../payloads/filo.elf
payload /filo.elf
end
buildrom ./linuxbios.rom ROM_SIZE "normal" "fallback"
buildrom ./linuxbios.rom ROM_SIZE "fallback"