Hi,
I've been looking at a number of VGA cards recently, and I've started
wondering out the Linux resource management as far as allocation of
IO ports. I've come to the conclusion that it does not contain all
information necessary to allow allocations to be made safely.
Thus far, VGA cards that I've looked at scatter extra registers through
out the PCI IO memory region without appearing in the PCI BARs. In fact,
for some cards there wouldn't be enough BARs to list them all.
For example, S3 cards typically use:
0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
0xff00 - 0xff44
And Trident TGUI9440 uses:
0x2120, 0x43c4
Cyber2000-type cards use:
0x0102, 0x46e8
These aren't guaranteed to be exhaustive listings either.
Some of these cards require writes to these registers to "wake them up"
so I think we can assume that these cards are listening for accesses to
those ports. If we allocate another device to use that region, we could
well end up getting IO port clashes.
Surely we should be reserving these regions before we start to allocate
resources to PCI cards?
Comments?
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
Russell King wrote:
> I've been looking at a number of VGA cards recently, and I've started
> wondering out the Linux resource management as far as allocation of
> IO ports. I've come to the conclusion that it does not contain all
> information necessary to allow allocations to be made safely.
>
> Thus far, VGA cards that I've looked at scatter extra registers through
> out the PCI IO memory region without appearing in the PCI BARs. In fact,
> for some cards there wouldn't be enough BARs to list them all.
> For example, S3 cards typically use:
>
> 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> 0xff00 - 0xff44
[...]
> Surely we should be reserving these regions before we start to allocate
> resources to PCI cards?
I tried to push this through when I was hacking heavily on fbdev
drivers, especially S3, and it didn't fly. On x86's, those addresses
are already reserved:
[jgarzik@rum linux_2_4]$ cat /proc/iomem
00000000-0009efff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000c7fff : Video ROM
000f0000-000fffff : System ROM
[...]
If they are not reserved on your arch, I think the driver should
definitely reserve the region. (though if its an ISA-compatible arch,
Linus might desire the above reservations as done by the core, not by
the fbdev driver)
Another alternative I thought of is freeing the resource if it is
allocated by the system, and having the driver allocate its own
resource. When the driver unloads, it frees its resources and allocates
the whole region back to the system. I look at this as the fbdev
driver's "clarifying the picture" of the hardware resource usage.
[again, this hullabaloo might only be necessary on x86]
Jeff
--
Jeff Garzik |
Building 1024 | The chief enemy of creativity is "good" sense
MandrakeSoft | -- Picasso
Jeff Garzik writes:
> > For example, S3 cards typically use:
> >
> > 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> > 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> > 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> > 0xff00 - 0xff44
^^^^ PCI IO addresses
> I tried to push this through when I was hacking heavily on fbdev
> drivers, especially S3, and it didn't fly. On x86's, those addresses
> are already reserved:
No they're not.
> [jgarzik@rum linux_2_4]$ cat /proc/iomem
> 00000000-0009efff : System RAM
> 000a0000-000bffff : Video RAM area
> 000c0000-000c7fff : Video ROM
> 000f0000-000fffff : System ROM
> [...]
^^^^^^^^^^^^^ PCI memory addresses.
> Another alternative I thought of is freeing the resource if it is
> allocated by the system, and having the driver allocate its own
> resource. When the driver unloads, it frees its resources and allocates
> the whole region back to the system. I look at this as the fbdev
> driver's "clarifying the picture" of the hardware resource usage.
If the driver isn't loaded, the port is still used by the hardware. Therefore,
it should be reserved independent of whether we have the driver loaded/in kernel
or not.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
Russell King wrote:
>
> Hi,
>
> I've been looking at a number of VGA cards recently, and I've started
> wondering out the Linux resource management as far as allocation of
> IO ports. I've come to the conclusion that it does not contain all
> information necessary to allow allocations to be made safely.
>
> Thus far, VGA cards that I've looked at scatter extra registers through
> out the PCI IO memory region without appearing in the PCI BARs. In fact,
> for some cards there wouldn't be enough BARs to list them all.
>
> For example, S3 cards typically use:
>
> 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> 0xff00 - 0xff44
This is an artifact from the ISA 10-bit IO bus. Many ISA cards do not
decode all 16 address bits so you get aliases of the 0x100-0x3ff region
throughout IO space. PCI cards should only use the first 256 ports of
any 1k block to avoid aliases unless they claim the base alias. For
example, all the xxe8 addresses for the S3 are aliases of 0x02e8 to an
ISA card. Video cards are an exception to the general rule because they
have to support all the legacy VGA crap.
> These aren't guaranteed to be exhaustive listings either.
>
> Some of these cards require writes to these registers to "wake them up"
> so I think we can assume that these cards are listening for accesses to
> those ports. If we allocate another device to use that region, we could
> well end up getting IO port clashes.
>
> Surely we should be reserving these regions before we start to allocate
> resources to PCI cards?
The current code already tries to avoid the ISA alias areas:
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
* addresses to be allocated in the 0x000-0x0ff region
* modulo 0x400.
*
* Why? Because some silly external IO cards only decode
* the low 10 bits of the IO address. The 0x00-0xff region
* is reserved for motherboard devices that decode all 16
* bits, so it's ok to allocate at, say, 0x2800-0x28ff,
* but we want to try to avoid allocating at 0x2900-0x2bff
* which might have be mirrored at 0x0100-0x03ff..
*/
--
Brian Gerst
Russell King wrote:
> Jeff Garzik writes:
> > > For example, S3 cards typically use:
> > >
> > > 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> > > 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> > > 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> > > 0xff00 - 0xff44
> ^^^^ PCI IO addresses
Oops, you're right :)
> If the driver isn't loaded, the port is still used by the hardware. Therefore,
> it should be reserved independent of whether we have the driver loaded/in kernel
> or not.
That logic doesn't work. If you believe that, then the core kernel
needs to be doing 100% of the request_region calls, right at bootup...
If XFree86 not fbdev is using the hardware, you can always have a stub
driver that does nothing but reserve the ports. Remember, too, that the
ports claimed depend on register settings in the video card and PCI
config space..
Jeff
--
Jeff Garzik |
Building 1024 | The chief enemy of creativity is "good" sense
MandrakeSoft | -- Picasso
Brian Gerst writes:
> This is an artifact from the ISA 10-bit IO bus. Many ISA cards do not
> decode all 16 address bits so you get aliases of the 0x100-0x3ff region
> throughout IO space. PCI cards should only use the first 256 ports of
> any 1k block to avoid aliases unless they claim the base alias. For
> example, all the xxe8 addresses for the S3 are aliases of 0x02e8 to an
> ISA card. Video cards are an exception to the general rule because they
> have to support all the legacy VGA crap.
No. All xxe8 addresses access specific registers. For example:
0x9ea8 is the drawing command
0xa2e8 is the background colour register
0xa6e8 is the foreground colour register
So, as you see they aren't aliases.
> /*
> * We need to avoid collisions with `mirrored' VGA ports
> * and other strange ISA hardware, so we always want the
> * addresses to be allocated in the 0x000-0x0ff region
> * modulo 0x400.
> *
> * Why? Because some silly external IO cards only decode
> * the low 10 bits of the IO address. The 0x00-0xff region
> * is reserved for motherboard devices that decode all 16
> * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
> * but we want to try to avoid allocating at 0x2900-0x2bff
> * which might have be mirrored at 0x0100-0x03ff..
> */
Ah ha, I'll nick that for the ARM stuff then. Thanks for pointing it out.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
Jeff Garzik writes:
> Russell King wrote:
> > Jeff Garzik writes:
> > > > For example, S3 cards typically use:
> > > >
> > > > 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> > > > 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> > > > 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> > > > 0xff00 - 0xff44
>
> If XFree86 not fbdev is using the hardware, you can always have a stub
> driver that does nothing but reserve the ports. Remember, too, that the
> ports claimed depend on register settings in the video card and PCI
> config space..
I wish. Unfortunately, ones of this nature tend to be rather fixed. No amount
of config space twiddling will move them. However, as someone else pointed out,
x86 gets around this problem by only allowing IO ports to be allocated in the
(addr & 0x0300) == 0 range, thereby avoiding the problem.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
Russell King wrote:
>
> Brian Gerst writes:
> > This is an artifact from the ISA 10-bit IO bus. Many ISA cards do not
> > decode all 16 address bits so you get aliases of the 0x100-0x3ff region
> > throughout IO space. PCI cards should only use the first 256 ports of
> > any 1k block to avoid aliases unless they claim the base alias. For
> > example, all the xxe8 addresses for the S3 are aliases of 0x02e8 to an
> > ISA card. Video cards are an exception to the general rule because they
> > have to support all the legacy VGA crap.
>
> No. All xxe8 addresses access specific registers. For example:
>
> 0x9ea8 is the drawing command
> 0xa2e8 is the background colour register
> 0xa6e8 is the foreground colour register
>
> So, as you see they aren't aliases.
Oh yeah, if you are writing for S3 specifically, you can do 100% MMIO,
and simply turn off all I/O decoding. Check out Keith Packard's
kdrive/s3trio in the XFree86 tree...
Jeff
--
Jeff Garzik |
Building 1024 | The chief enemy of creativity is "good" sense
MandrakeSoft | -- Picasso
Russell King wrote:
> Jeff Garzik writes:
> > If XFree86 not fbdev is using the hardware, you can always have a stub
> > driver that does nothing but reserve the ports. Remember, too, that the
> > ports claimed depend on register settings in the video card and PCI
> > config space..
>
> I wish. Unfortunately, ones of this nature tend to be rather fixed. No amount
> of config space twiddling will move them. However, as someone else pointed out,
> x86 gets around this problem by only allowing IO ports to be allocated in the
> (addr & 0x0300) == 0 range, thereby avoiding the problem.
Dig through the video card docs, even older ISA video cards let you
disable I/O decoding on all but a few ports, and/or relocate the ports
it does use to other areas. Different with every video card, of course,
but most of them can do this to a greater or lesser extent.
Jeff
--
Jeff Garzik |
Building 1024 | The chief enemy of creativity is "good" sense
MandrakeSoft | -- Picasso
Jeff Garzik writes:
> Dig through the video card docs, even older ISA video cards let you
> disable I/O decoding on all but a few ports, and/or relocate the ports
> it does use to other areas. Different with every video card, of course,
> but most of them can do this to a greater or lesser extent.
Unfortunately, when you start thinking about x86 and running the BIOSes
to (re-)initialise VGA cards back to text mode, they don't take it well
if you do this sort of messing.
However, I believe that my problem is sorted by use of that function from
pci-i386.c.
Thanks to people who helped.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
On Fri, 17 Nov 2000, Jeff Garzik wrote:
> Russell King wrote:
> > I've been looking at a number of VGA cards recently, and I've started
> > wondering out the Linux resource management as far as allocation of
> > IO ports. I've come to the conclusion that it does not contain all
> > information necessary to allow allocations to be made safely.
> >
> > Thus far, VGA cards that I've looked at scatter extra registers through
> > out the PCI IO memory region without appearing in the PCI BARs. In fact,
> > for some cards there wouldn't be enough BARs to list them all.
>
> > For example, S3 cards typically use:
> >
> > 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> > 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> > 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> > 0xff00 - 0xff44
> [...]
> > Surely we should be reserving these regions before we start to allocate
> > resources to PCI cards?
>
This can't be. If the IO decode doesn't exist in the BAR, the board
can't access that address if it exists above 0x1000. Some ISA compatibable
ports are decoded by some SVGA boards so that the BIOS can do an
early initialization of compatible boards before the board's ROM bios
is located, shadowed, then executed.
Anything you see above 0x1000, that seems to be coming from a PCI
video board, has got to be an ISA alias and can be ignored.
When you write bits to the base address registers, these turn out
to be the physical bits set into the hardware decoder. That's why,
if you need N kb of address space, it needs to be on a N kb boundary.
If these bits are not set, the board is isolated.
In the same vain, Linux may not have the information available to
properly allocate addresses to PCI and AGP boards. This happens
because some devices will fail if you change their addresses once
they are initialized (Most SCSI controllers). Therefore you
can't change them.
This means that you can't really change anything else.
What the BIOS does:
(1) Learn the last address occupied by memory.
(2) Learn the lowest unaliased port address above 0x1000.
(3) Starting with the bridge, allocate resources both
ports and memory addresses.
The memory addresses start after the last RAM.
The port addresses start after the last alias.
The I/O or memory enables are usually left OFF.
(4) Copy any BIOS found for screen cards and IPL devices,
shadow them, remove the BIOS decode, then execute
their initialization code. These I/O or memory enables
are left ON.
If Linux tries to do this after, say a BusLogic SCSI controller
booted it, it may set a different I/O address for the SCSI controller.
Since the SCSI controller needs a hardware reset to accept new
I/O decodes, you are dead. Several "smart" controllers are like
this. They have processors that "remember" stuff that you'd like
them to forget.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
Richard B. Johnson writes:
> This can't be.
Richard, before I read any further, I suggest that you get some
documentation on a few PCI VGA cards and read up on the register
addresses. You may want to change your assumptions about what can and
can't be. ;)
And I can definitely say that if you don't allow access to these "extended"
VGA ports, BIOSes either enter infinite loops or else terminate without
initialising the card. Trust me; I've been successfully running various
PCI VGA card BIOSes under an x86 emulator on an ARM machine for the past
few months.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
> And I can definitely say that if you don't allow access to these "extended"
> VGA ports, BIOSes either enter infinite loops or else terminate without
PCI cards also exist that snoop the ISA bus. Several cards snoop the PCI
transactions that eventually go on to the ISA bus in order to emulate ISA bus
DMA
On Fri, 17 Nov 2000, Russell King wrote:
> Richard B. Johnson writes:
> > This can't be.
>
> Richard, before I read any further, I suggest that you get some
> documentation on a few PCI VGA cards and read up on the register
> addresses. You may want to change your assumptions about what can and
> can't be. ;)
>
> And I can definitely say that if you don't allow access to these "extended"
> VGA ports, BIOSes either enter infinite loops or else terminate without
> initialising the card. Trust me; I've been successfully running various
> PCI VGA card BIOSes under an x86 emulator on an ARM machine for the past
> few months.
If a board has the capability of snooping their own special addresses,
you don't have to do anything about them. They snoop <period>.
If you look as how I showed that the resources are allocated, you
will see that it works. The I/O addresses that are used (for everything),
start at the lowest __unaliased__ address. This means that if a board
is already snooping an address, it will appear to be aliased.
The code necessary to find the lowest unaliased address looks like
this:
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; This initializes memory and port allocation space for PCI
; device resource allocation.
;
ALIGN 4
INIT_PCI_RES:
PUSH DS ; Save segment
MOV AX,PCI_OBJ_ALLOC ; Segment address for storage
MOV DS,AX ; Set segment
MOV DWORD PTR DS:[PCI_MEM],(INSTALLED_MEM SHL 14H) ; For PCI
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; Find the lowest port address (above PCI_OFF) that doesn't have
; any devices responding at possible aliases.
;
MOV EDX,0000F002H ; Highest possible even port
FPRT: SUB DX,02H ; Keep on a WORD boundary
IN AX,DX ; See if anything there
SLOW_IO ; Bus settle time for slow devices
INC AX ; 0FFFFH -> 0000H
JNZ SHORT PRTFND ; We found an alias
CMP DX,PCI_OFF ; Lowest port
JNC FPRT ; Continue
PRTFND: ADD DX,02H ; Last good port
MOV DWORD PTR DS:[PCI_PRT], EDX
POP DS ; Restore segment
RET
The code necesary to allocate resources looks like this:
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; This allocates PCI-bus memory-space. Upon entry EAX contains
; the DWORD read from the PCI-bus memory address register. This
; can be zero (no memory to reserve). Upon exit, EAX contains
; the value to be written back to this register, including possibly
; zero.
;
ALIGN 4
ALLOC_PCI_ADDR:
PUSH EBX ; Save nonvolatile registers
PUSH DS ; Save segment
PUSH PCI_OBJ_ALLOC ; Where we save last result
POP DS ; DS = PCI_OBJ_ALLOC
TEST EAX,1 ; IO port?
JZ SHORT NOTIOP ; Not an IO port
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; This allocates an I/O port for the device. They are allocated on
; 16-byte boundaries even if we don't need the space.
;
AND EAX,(NOT 3) ; Mask port/reserved bits
JZ SHORT NOALOC ; No space required
MOV ECX,EAX ; Start with first address bit
NEG ECX ; ECX = length required
CMP ECX,000000010H ; At least 16 bytes?
JNC SHORT WAS16 ; Yes
MOV ECX,000000010H ; At least 16 bytes
WAS16: MOV EBX,ECX ; Save allocation length
MOV EAX,DWORD PTR DS:[PCI_PRT] ; Get present value
ADD EAX,ECX ; New offset value
DEC EAX ; Adjust for previous math
NEG ECX ; Create a mask
AND EAX,ECX ; N-byte boundary
ADD EBX,EAX ; EBX = for this allocation
MOV DWORD PTR DS:[PCI_PRT],EBX ; Ready next
JMP SHORT NOALOC ; We are done
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; This allocates I/O memory-space. A defect (feature) of the
; PCI addressing scheme is that a N-byte allocation must start
; on a N-byte boundary. This means that a 4 megabyte allocation
; for a PCI screen-card wastes nearly 4 megabytes of address-space.
;
NOTIOP: AND EAX,0FFFFFFF0H ; Clear non-address bits
JZ SHORT NOALOC ; No memory required
MOV ECX,EAX ; Start with first address bit
NEG ECX ; ECX = length required
MOV EBX,ECX ; Save allocation length
MOV EAX,DWORD PTR DS:[PCI_MEM] ; Get present value
ADD EAX,ECX ; New offset value
DEC EAX ; Adjust for previous math
NEG ECX ; Create a mask
AND EAX,ECX ; N-byte boundary
ADD EBX,EAX ; EBX = for this allocation
MOV DWORD PTR DS:[PCI_MEM],EBX ; Ready next
NOALOC: NEG ECX ; Return with length
POP DS ; Restore segment
POP EBX
RET
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; This attempts to set up the PCI bus. This does a PCI
; snoop, finding PnP devices, allocating memory, and enabling
; them. Note that this machine has only one bridge so we
; don't have to check for bridges behind bridges.
;
ALIGN 4
SET_PCI:
XOR SI,SI ; Start at device zero, the bridge.
READ_PCI SI, 0 ; See if the bridge is there
INC EAX ; 0xffffffff becomes zero
JNZ SHORT BRIDGE ; There is a bridge
RET ; Forget it, no bridge
;
BRIDGE: READ_PCI SI, PCI_CMD_STA ; Get command/status register
OR AX,07H ; Enable I/O, Memory, Master
WRITE_PCI SI, PCI_CMD_STA, EAX ; Enable it.
;
READ_PCI SI, PCI_AMD ; AMD Specific PCI retry count
MOV AL,80H ; Recommended value
WRITE_PCI SI, PCI_AMD, EAX ; Set timeout value
;
READ_PCI SI,PCI_LAT_CACHE ; Latency, etc.
MOV AX,4008H ; Latency / cache line size
WRITE_PCI SI, PCI_LAT_CACHE,EAX ; Set it (if possible)
;
PCIDEV: INC SI ; Ready next device
READ_PCI SI, 0 ; Get device ID
INC EAX ; Anybody home? 0xffffffff becomes 0
JZ PCINXT ; Nope
;
READ_PCI SI, PCI_CMD_STA ; Get command/status register
OR AX,7 ; Enable I/O, Memory, Bus master
WRITE_PCI SI, PCI_CMD_STA, EAX ; Enable it.
;
READ_PCI SI,PCI_LAT_CACHE ; Latency, etc.
MOV AX,4008H ; Latency / cache line size
WRITE_PCI SI, PCI_LAT_CACHE,EAX ; Set it (if possible)
;
MOV DI,PCI_BASE0 ; First base address offset
PCIRES: MOV EAX,0FFFFFFFFH ; All bits set
WRITE_PCI SI, DI, EAX ; Try to set all bits
READ_PCI SI, DI ; Get the results
CALL ALLOC_PCI_ADDR ; Allocate resources
WRITE_PCI SI, DI, EAX ; Write base address (could be zero)
INC DI ; Ready next base address
CMP DI,PCI_CARDBUS ; Check limits
JC PCIRES ; Next possible address
;
READ_PCI SI, PCI_INTER ; Interrupt pin
TEST AX,0F00H ; Isolate interrupt pin
JZ SHORT PCINOI ; No interrupt required
CALL GET_IRQ ; Get IRQ value from table
PCINOI: OR EAX,18180000H ; Could be writable
WRITE_PCI SI, PCI_INTER, EAX ; Set IRQ (could be zero)
PCINXT: CMP SI,PCI_MAX ; End of devices?
JC PCIDEV ; Nope
PARK_PCI ; Park on the bridge
RET
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Cheers,
Dick Johnson
Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
Followup to: <[email protected]>
By author: Russell King <[email protected]>
In newsgroup: linux.dev.kernel
>
> I've been looking at a number of VGA cards recently, and I've started
> wondering out the Linux resource management as far as allocation of
> IO ports. I've come to the conclusion that it does not contain all
> information necessary to allow allocations to be made safely.
>
> Thus far, VGA cards that I've looked at scatter extra registers through
> out the PCI IO memory region without appearing in the PCI BARs. In fact,
> for some cards there wouldn't be enough BARs to list them all.
>
This (and ISA) is why PCs usually allocate only addresses that match
the following equation for PCI IO:
(port >= 0x1000 && (port & 0x0300) == 0).
As you can see, the ports you list below all violate the second
criterion, they are thus "ISA equivalent ports".
The downside is that it's impossible to allocate more than 256
consecutive ports.
> For example, S3 cards typically use:
>
> 0x0102, 0x42e8, 0x46e8, 0x4ae8, 0x8180 - 0x8200, 0x82e8, 0x86e8,
> 0x8ae8, 0x8ee8, 0x92e8, 0x96e8, 0x9ae8, 0x9ee8, 0xa2e8, 0xa6e8,
> 0xaae8, 0xaee8, 0xb2e8, 0xb6e8, 0xbae8, 0xbee8, 0xe2e8,
> 0xff00 - 0xff44
>
> And Trident TGUI9440 uses:
>
> 0x2120, 0x43c4
>
> Cyber2000-type cards use:
>
> 0x0102, 0x46e8
>
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt
Followup to: <[email protected]>
By author: Russell King <[email protected]>
In newsgroup: linux.dev.kernel
>
> Brian Gerst writes:
> > This is an artifact from the ISA 10-bit IO bus. Many ISA cards do not
> > decode all 16 address bits so you get aliases of the 0x100-0x3ff region
> > throughout IO space. PCI cards should only use the first 256 ports of
> > any 1k block to avoid aliases unless they claim the base alias. For
> > example, all the xxe8 addresses for the S3 are aliases of 0x02e8 to an
> > ISA card. Video cards are an exception to the general rule because they
> > have to support all the legacy VGA crap.
>
> No. All xxe8 addresses access specific registers. For example:
>
> 0x9ea8 is the drawing command
> 0xa2e8 is the background colour register
> 0xa6e8 is the foreground colour register
>
> So, as you see they aren't aliases.
>
They aren't, but because early ISA cards did use these as aliases,
board manufacturers said "hey, we only need to allocate the bottom 10
bits, and we can use the remaining 6 address lines as we please."
Sigh.
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt
Richard B. Johnson writes:
> The code necessary to find the lowest unaliased address looks like
> this:
Any chance of providing something more readable? I may be able to read
some x86 asm, but I don't have the time to try to decode that lot.
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
On Fri, 17 Nov 2000, Russell King wrote:
> Richard B. Johnson writes:
> > The code necessary to find the lowest unaliased address looks like
> > this:
>
> Any chance of providing something more readable? I may be able to read
> some x86 asm, but I don't have the time to try to decode that lot.
It's Intel assembly on Intel machines. It's a hell of a lot more
readable than AT&T assembly. This stuff has to be set up before you
have any resources necessary to execute the output of a 'C' compiler,
so, if you are looking for 'C' syntax, you are out of luck.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
Richard B. Johnson writes:
> It's Intel assembly on Intel machines. It's a hell of a lot more
> readable than AT&T assembly. This stuff has to be set up before you
> have any resources necessary to execute the output of a 'C' compiler,
> so, if you are looking for 'C' syntax, you are out of luck.
Hello Dick!
Come in!
I don't care about what style of assembly it is. Believe it or not,
this may come as a dramatic revelation to you, but not every single
person on this planet knows X86 assembler of any form.
I am one of the lucky people who doesn't have his brain crambed full
of the intracies of such a language. Instead I have my brain full of
ARM assembler instead, which is a hell of a lot more readable than
X86 assembler.
Therefore, you quoting bits of X86 assembler to me is meaningless.
-EAGAIN (try again)
_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King [email protected] --- ---
| | | | http://www.arm.linux.org.uk/personal/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |
Followup to: <[email protected]>
By author: Russell King <[email protected]>
In newsgroup: linux.dev.kernel
>
> Richard B. Johnson writes:
> > The code necessary to find the lowest unaliased address looks like
> > this:
>
> Any chance of providing something more readable? I may be able to read
> some x86 asm, but I don't have the time to try to decode that lot.
>
Ignore this code. It's bullshit -- you can't just go and poke random
boards -- even with IN's -- indiscriminately. As usual, Richard is
writing long lectures on subjects he is seriously mistaken about (and
probably will send me yet another email trying to browbeat me into not
calling him on all his errors.)
The standard algorithm, documented in many places, is the one I gave
before:
(port >= 0x1000 && (port & 0x0300) == 0)
Allocating ports in any other ranges is unsafe.
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt
On Fri, 17 Nov 2000, Russell King wrote:
> Richard B. Johnson writes:
> > It's Intel assembly on Intel machines. It's a hell of a lot more
> > readable than AT&T assembly. This stuff has to be set up before you
> > have any resources necessary to execute the output of a 'C' compiler,
> > so, if you are looking for 'C' syntax, you are out of luck.
>
> Hello Dick!
>
> Come in!
>
> I don't care about what style of assembly it is. Believe it or not,
> this may come as a dramatic revelation to you, but not every single
> person on this planet knows X86 assembler of any form.
>
> I am one of the lucky people who doesn't have his brain crambed full
> of the intracies of such a language. Instead I have my brain full of
> ARM assembler instead, which is a hell of a lot more readable than
> X86 assembler.
>
> Therefore, you quoting bits of X86 assembler to me is meaningless.
>
> -EAGAIN (try again)
Okay. I'll bite (byte). The last port available is 0xffff. It's an
odd number, so start at 0xfffe because all the PCI port bases start
at even numbers (actually long words).
Then, you read the port as a WORD (16 bits). If nothing responds,
you get the value of 0xffff. If somebody is responding, you will
read something if it's enabled for writes by devices (reads by the CPU).
You keep decrementing the port number by 2 until either somebody responds
or you get to 0x1000. The lowest port number, without anybody reponding
is the first port you can allocate. However, the allocation has to
be a correct PCI allocation, i.e., if somebody wants 16 bytes, you
must allocate on a 16-byte boundary, potentially wasting 15 bytes
of address space.
The first aliased addresses will usually start to appear below 0x8000.
This typically gives you almost 32k of I/O space to allocate.
Since PCI devices can come alive in just about any state, before
you actually do the snoop, your code should disable I/O for all
PCI devices found except the first bridge. You do this by reading
the second longword for each device, anding off the lowest 3 bits,
then writing it back. (Command/Status register). The low word is
the command register. The high word is the status register. Since
any bits set in the status register, will be written back (this
is how the bits get reset), you automatically reset any errors the
device may have accumulated upon startup.
If you have a PCI to ISA bridge (like PIIX4) , you have to enable
it even though ISA bridge decodes are full 32-bit decodes. This is
because the board itself will not do a 32-bit decode and can result in
aliases.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
On 17 Nov 2000, H. Peter Anvin wrote:
> Followup to: <[email protected]>
> By author: Russell King <[email protected]>
> In newsgroup: linux.dev.kernel
> >
> > Richard B. Johnson writes:
> > > The code necessary to find the lowest unaliased address looks like
> > > this:
> >
> > Any chance of providing something more readable? I may be able to read
> > some x86 asm, but I don't have the time to try to decode that lot.
> >
>
> Ignore this code. It's bullshit -- you can't just go and poke random
> boards -- even with IN's -- indiscriminately. As usual, Richard is
> writing long lectures on subjects he is seriously mistaken about (and
> probably will send me yet another email trying to browbeat me into not
> calling him on all his errors.)
It's not bullshit, and as usual, you will never learn.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
[email protected] ("Richard B. Johnson") writes:
[about PCI setup code]
> This stuff has to be set up before you
> have any resources necessary to execute the output of a 'C' compiler,
> so, if you are looking for 'C' syntax, you are out of luck.
Sorry, but that's plain rubbish.
Some things in bootcode usually have to be done in assembly, but
PCI setup is definitely *not* among them, unless you have some
really unique hardware. Hell, I've even written bootcode where
the memory-controller is set up from C.
//Marcus
--
-------------------------------+-----------------------------------
Marcus Sundberg | Phone: +46 707 452062
Embedded Systems Consultant | Email: [email protected]
Cendio Systems AB | http://www.cendio.com
On Fri, 17 Nov 2000, Russell King wrote:
> Therefore, it should be reserved independent of whether we have the
> driver loaded/in kernel or not.
Is this not an argument for a more flexible resource allocation
API? One offering both:
res = allocate_resource(restype, dev, RES_ALLOC_UNUSED, region);
and
res = allocate_resource(restype, dev_ RES_ALLOC_HW, region);
?
Maybe the kernel might ask:
allocate_resource(restype, dev, RES_ALLOC_UNMOVABLE_HW, region);
Matthew.
Followup to: <Pine.LNX.4.10.10011172134510.27177-100000@sphinx.mythic-beasts.com>
By author: Matthew Kirkwood <[email protected]>
In newsgroup: linux.dev.kernel
>
> On Fri, 17 Nov 2000, Russell King wrote:
>
> > Therefore, it should be reserved independent of whether we have the
> > driver loaded/in kernel or not.
>
> Is this not an argument for a more flexible resource allocation
> API? One offering both:
>
> res = allocate_resource(restype, dev, RES_ALLOC_UNUSED, region);
>
> and
>
> res = allocate_resource(restype, dev_ RES_ALLOC_HW, region);
>
One way to do this is to treat PCI IO and ISA IO as two separate
address spaces. The PCI IO address space is a 14-bit address space
(bits 9:8 are always zero) ranging from 0x1000 to 0xFCFF. ISA IO is a
10-bit space (bits 15:10 are available for the card to use) ranging
from 0x100 to 0x3FF.
VGA cards may be PCI and AGP, but still have allocations in the ISA
range.
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt
On Fri, Nov 17, 2000 at 03:27:28PM -0500, Richard B. Johnson wrote:
> Then, you read the port as a WORD (16 bits). If nothing responds,
> you get the value of 0xffff. If somebody is responding, you will
> read something if it's enabled for writes by devices (reads by the CPU).
What guarantees you that:
1- No device will respond 0xffff for an address it decodes
2- No device will crap up on you simply because you've read one
particular address
If any of these if true for any device out there (I think I have one
in my computer that does the 1/ part in some cases), your code is
unsafe.
OG.
Followup to: <[email protected]>
By author: Olivier Galibert <[email protected]>
In newsgroup: linux.dev.kernel
>
> What guarantees you that:
> 1- No device will respond 0xffff for an address it decodes
> 2- No device will crap up on you simply because you've read one
> particular address
>
> If any of these if true for any device out there (I think I have one
> in my computer that does the 1/ part in some cases), your code is
> unsafe.
>
It is. There are plenty of devices for which an arbitrary IN is an
irrecoverable state transition.
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt
> It is. There are plenty of devices for which an arbitrary IN is an
> irrecoverable state transition.
The ne2000 clones being the most infamous of them. Blind ISA read probing is
not a safe business
>
>One way to do this is to treat PCI IO and ISA IO as two separate
>address spaces. The PCI IO address space is a 14-bit address space
>(bits 9:8 are always zero) ranging from 0x1000 to 0xFCFF. ISA IO is a
>10-bit space (bits 15:10 are available for the card to use) ranging
>from 0x100 to 0x3FF.
>
>VGA cards may be PCI and AGP, but still have allocations in the ISA
>range.
I'd love to see PCI and ISA IOs treated differently too.
I'm seeing more and more esoteric PCI setups (especially on some huge PPCs
with several host bridges), various different ways to access PCI mem and
ISA, various ways to handle the ISA "special case" for memory, etc...
When you have to deal with various separate PCI IO spaces, each one having
it's own address space, and each one potentially having devices that want
to do IOs or "legacy" ISA IOs, then you are screwed.
Currently, we don't really support IOs on anything but the "primary" PCI bus
(choosen arbitrarily) unless platform-specific driver hacking is done.
We could use the MMU mappings to let the kernel think all those IO spaces
are actually one big contiguous region, and remap them all together. This way,
a simple resource fixup would make PCI drivers using IO resources work at
least.
But in this case, "ISA" IOs will have to be restricted to one of the IO
busses,
decided arbitrarily.
But what about 2 video cards on the AGP port and one PCI slot of a G4 Mac ?
This machine, just an example, have those on different host controllers with
separate IO spaces. If those cards need to be driven with VGA accesses (for
running a BIOS emulator for example, or just because you have no choice),
then you are screwed. All you can do is have one bus support VGA IOs.
Another issue is ISA memory space, for the same reason as above (multiple
busses), but also because a lot of PCI controller setup can't forward
memory cycles below 0x80000000 or such arbitrary physical address. Some
of them (most but not all) provide a way via a separate physical address
to access a 64k "ISA" memory space that generates low-address PCI cycles.
So you can have one or more ISA IO busses, and 0 or more ISA memory busses.
A solution for that would be to have VGA and other legacy ISA drivers in
the kernel change the way they use the IO access macros.
One idea I have, would be to either keep a virtual ISA "bus number" along
with kernel support functions to count them, get virtual base addresses for
IO & memory, query about availability of those, etc...
Another would be to link that more tighly with PCI by adding generic functions
to request the virtual base address of each PCI IO and ISA-memory space.
We already have a syscall on some platforms (PPC, Alpha) to request those
informations from userland (XFree).
I'm not sure about the best way that could fit in the resource
architecture yet. I have different problems with PCI resources for now
(mostly with host bridges that provide several discontiguous decoding
ranges)...
Ben.
[email protected] (Alan Cox) wrote on 18.11.00 in <[email protected]>:
> > It is. There are plenty of devices for which an arbitrary IN is an
> > irrecoverable state transition.
>
> The ne2000 clones being the most infamous of them. Blind ISA read probing is
> not a safe business
Hell, I've had machines crashing in the BIOS pre-boot stuff because it was
doing INs where a NE2000 sat.
MfG Kai