[Savage40] s3switch & prosavage8 [KM266/KL266]
Tim Roberts
timr at probo.com
Tue Nov 23 10:26:13 PST 2004
I sent this message through to the whole list, because it is becoming a FAQ.
Daniel Lindenaar wrote:
> Hi everybody,
> Since a few months i've switched to using linux only on my laptop. The
> only thing that doesn't work for me is the s3switch utility. it
> reports that all connections are enabled (CRT,LCD and TV), but there
> is no output at the tv connector. Switching to, for example, LCD only,
> blanks the screen and prints:
> -----
> daniel at s465417:~/s3switch$ ./s3switch lcd
> vm86() failed
> return = 0x1
> eax = 0x00003e02
> ebx = 0xc0000000
> ecx = 0x00000007
> edx = 0x00006a99
> esi = 0x00006a84
> edi = 0x00006aa9
> ebp = 0x00000fc4
> eip = 0x00006931
> cs = 0xc000
> esp = 0x00000f62
> ss = 0x1000
> ds = 0x0000
> es = 0x0000
> fs = 0x0000
> gs = 0x0000
> eflags = 0x000b3246
> cs:ip = [ e6 eb e2 fc a8 01 75 03 e8 15 00 9d 5f 5e 5a 59 ]
> Could not set device (vm86 failure)
> Devices attached: CRT LCD TV
> Devices active: CRT LCD TV
> Current TV format is NTSC-J
What you're seeing here is boneheadedness on the part of BIOS writers.
It is very difficult to debug a BIOS, especially a video BIOS, because
there's nowhere to put the debug output. So, many manufacturers have
special test points on their motherboards connected up to specific,
otherwise unused, I/O ports. The BIOS code can write values to these
debug ports as they progress, and the manufacturer can monitor the
progress with an oscilloscope or logic analyzer.
In a perfect world, the manufacturers would remove all of this debug
code before shipping. In the real world, many do not. Once it works,
"ship it!" That's what you are seeing here: the video BIOS is
accessing I/O ports that a video BIOS should not be touching. A
user-mode program in Linux has to ask for permission to touch I/O
ports. Since I didn't ask for permission for these ports, BOOM,
s3switch gets a protection fault inside the vm86 syscall.
Fortunately, the answer is pretty easy, especially if you know x86
code. In the source for s3switch.c, in the function IOAccess, you'll
see a series of "ioperm" calls. These are the calls that get I/O port
permissions. You just need to add the ones your BIOS uses.
There are two places in the dump to look for clues: the instruction
sequence at cs:ip, and the edx register. In this example:
> edx = 0x00006a99
> cs:ip = [ e6 eb e2 fc a8 01 75 03 e8 15 00 9d 5f 5e 5a 59 ]
The "e6" instruction is an I/O port OUT instruction, with a one-byte
literal port number. So, this is trying to access I/O port 0xeb. You
need to add an ioperm call for port 0xeb, as in "ioperm( 0xeb, 1, enable
);".
This is an iterative process. After you add this and rebuild s3switch,
you might find another port. 0x70 is a common culprit.
If the first byte at cs:ip is "ee" instead of "e6", that version of the
OUT instruction gets the port number from the low-order 16 bits of the
edx register. Add an "ioperm" call with that number as well.
Good luck.
--
- Tim Roberts, timr at probo.com
Providenza & Boekelheide, Inc.
More information about the Savage40
mailing list