• Please review our updated Terms and Rules here

PCI on 8086

Joined
Feb 22, 2024
Messages
10
Hey guys,

Does anyone know how to read a PCI bus on 8086 machines? I've been looking at PCISLEEP and it has:

getpci: ; bus CH, device.function CL (5+3 bits), read register BL to EAX
push dx ; register must be multiple of 4
mov dx,0cf8h
mov eax,ecx
and eax,0ffffh
shl eax,8
or eax,80000000h
mov al,bl
out dx,eax
add dx,4
in eax,dx
pop dx
ret

But eax is a 32-bit register not a 16-bit one so it won't work on an 8086 CPU. Any help would be great.
 
This is likely not going to work without hardware support (you'll need a latch that will read 32bits at once from the bus and then read that latch in two 16bit chunks into the CPU).
 
Does anyone know how to read a PCI bus on 8086 machines?
You don't. PCI is a 32-bit bus and cannot be used on 8086 machines.
If you have bridge hardware, consult its documentation.

If you want to use "8086 instructions only", then the answer is: You don't.
Maybe you can use two 16-bit accesses (to ports N and N+2), but that will not work on all chipsets.
 
You don't. PCI is a 32-bit bus and cannot be used on 8086 machines.
Ohh okay, thanks for that info. As PCISLEEP is for FreeDOS I assumed that it may be possible on all machines, I guess FreeDOS does some 32-bit stuff as well.

Just curious then if there's a better way at talking to/probing/querying hardware then other than say checking for carry flags. For example, one way to query a disk would be:

mov ax, 0201h
mov cx, 0001h
mov dx, 0000h ; First, floppy drive
int 0x13
jc .drive_not_ready

but is that the only/best way to do things?
 
The BIOS and DOS APIs generally work by setting register values, doing a software interrupt, then checking the carry flag for success/failure. That is the contract you have to follow if you want to use them.

You are free to do it in other ways, but then you are using a different interface.
 
If all you want to do is check if a drive exists (as far as DOS knows), you could use INT 21h / AH=29h. It's intended for parsing filenames, but if you give it a string like "A:" followed by a space, and a 12 byte "scratch" buffer for the FCB, the return code will indicate if the drive letter is valid.

There is also the BIOS configuration info returned by INT 11h, which has some bitfields for number of installed floppy drives and serial/parallel ports.
 
Hopefully I explain this properly/get it right, since I haven't written all that much code like this myself.

For disks for example, there are some layers like:

IBM/MS-DOS (interrupt 21h)
PC BIOS (interrupt 13h)
Whatever interface the actual hardware provides

Compatibility decreases the further you go down the list: If you use the DOS API/interrupts, then you software should work on any DOS machine even if it's not IBM-compatible. If you make standard IBM PC BIOS calls, then your software is compatible with fewer machines, but certainly the majority of machines people think of when they think of "DOS". If you talk directly to the hardware, your software will work with fewer machines still.

On the other hand, the closer to the hardware you get, the more you can control and the more information you can get.

If you use DOS's interface, then you might want to think about which versions to support. Whatever interface you use, you should read Ralf Brown's Interrupt List and see all the quirks of different DOS versions, different BIOSes, etc., and consider whether you want to put in the effort to work around some weird behaviour in PTS-DOS, very early IBM PC BIOSes, or whatever comes up in the particular areas you're working in.

If you think about SCSI controllers, they probably have very different low-level interfaces from an ATA/IDE controller most of us are somewhat familiar with, but they will often optionally install an interrupt 13h handler so that they can be accessed like other devices.

So there are tradeoffs to be made - either you pick some layer, stick to it, and accept the limitations, or you actually write your software to detect what is available, use it and adapt to it. In the latter case you might detect that you're running on a non-PC machine and tell your user "This machine is not IBM compatible, certain features will not be available."

In my case, I think that worrying about what other people might do with my software is probably going a bit far though, I should probably wait to see if anyone tries to use it first :LOL: I think I'll just say it only works with X and Y, may not work with Z based on what I read in Ralf Brown's Interrupt List, and please let me know if you would like it to do something else.
 
I thought someone made or is making an PCI -> 8 bit ISA adapter for specific cards or classes of devices...

8086 is 16/16 CPU, it cannot execute 32-bit instructions nor it can address 32-bit space needed for PCI access.
In 32 bit platform access DOS is not actually working in normal real mode, but protected 32 bit mode via DPMI. That's why you can program PCI device drivers for DOS. Although you can execute 32-bit instructions in real mode, you cannot access the memory space, therefore this mechanism is severely limited to cases that don't deal with memory.

The running context of those drivers is 32-bit protected mode. It has little to do with 16-bit DOS heritage. PCI on DOS is 32-bit in hardware and in driver.

DPMI is a source of confusion for a lot of stuff, especially classification of stuff. A DPMI game like Quake interacts with hardware it a more similar fashion to Windows 95 than to DOS. DOS+DPMI is a 32bit environment with some 16bit device access, just like Windows 3.1, and just like most of the "back in the day" Windows 95 installations were.
 
Back
Top