• Please review our updated Terms and Rules here

Option ROMs and interrupt vectors

tom.storey

Experienced Member
Joined
Nov 18, 2022
Messages
107
Location
London, UK
Hi all,

Sorry if this isnt the correct place to post, please move if there is somewhere better.

Im planning to build a card for my XT that will contain a bunch of stuff, and part of this will be to include a socket for an option ROM that I can use for development purposes.

But I have a question. Lets say you have an option ROM that wants to intercept an interrupt. There may or may not already be an existing ISR installed at a particular vector, and your option ROM potentially needs to become part of a chain, potentially calling that existing ISR.

How or where does one save the address of that existing ISR so that it can be called after your own ISR is complete?

So far the best solution I can come up with is to have some RAM that lives within the option ROM's address space and constitues the last 512 bytes (one option ROM "block" size) before the next 2k boundary. This means your option ROM size can be reported as n-1 so that the last 512 bytes doesnt get counted as part of the ROM, and the next option ROM can start immediately after. Unless I misunderstand how that bit works...

Ive seen that some option ROMs copy the existing vector to a new vector location, such that maintaining the chain simply becomes a matter of calling the address at that other vector location (or doing an INT Xh for it). But that sounds like a bit of a nightmare if you just happen to choose the same vector that some other piece of software also happens to use, or vice versa...

Insight appreciated.

Thanks!
 
Most drivers that use hardware interrupts do "chain" to an existing vector and you do need some RAM to save the address. Software interrupts follow the same convention. For example, a hard disk adapter moves the existing interrupt 13h vector to interrupt 40h and inserts its vector in the interrupt 13h location. This allows a hard disk adapter to function without using an extra RAM. So the procedure is "look at the request; if it's not for me, long-jump to the next handler in the chain.
 
I see in the docs that memory corresponding to int 40h is specifically allocated for saving the fixed disk vector, and 41h also has an allocated purpose.

While examining a VGA BIOS disassembly I noticed that it chose to store a vector in memory corresponding to int 42h, being the first "free" location. I found a couple of further references to this so I assume that int 42h already has a sort of "unofficial" purpose of saving video related vectors.

Additional memory corresponding with int 43h-59h on both the PC and XT doesn't appear to be allocated for anything in particular (roughly similar but not exactly on the AT), so is it just a matter of "flipping a coin" and hoping for the best? I don't suppose there's any kind of register or unofficial list of what typically goes at these vectors to be able to choose something safely is there? Assuming that this is kind of a "dumping ground" for saving existing vectors ...

Cheers!
 
I've not checked it, but the Phoenix books do document the use of the various interrupt vectors. Are you checking Ralf Brown's interrupt list? Unused vectors are usually initialized by the BIOS to a known IRET routine, so anything other than that address would indicate that the vector has been claimed.
 
I haven't checked any of those yet, I've just been reading the BIOS listings supplied in the IBM technical references.

So far I've only come across one piece of code that initialises a block of vectors, and I think it's just for the hardware IRQs, and at that there are only 8 of them. The software vectors must come from elsewhere, but I haven't found that just yet.

Some of those IQR vectors are initialised to a basic IRET routine, but to detect that I imagine you would need to know the address of that routine as it differs across all of the BIOS versions, and to me that sounds like a "hard coded address" problem.

Ralf Browns list looks good! I will take a look through that and see what I can learn.
 
To make sure I'm on the same page as you here, are you talking about manually inspecting the interrupt vectors to find one that is unused? If so I agree with the methodology.

But if this is something that my code is meant to do, I then need to store the vector number that I found, which takes me back to the original problem. :)
 
I'd be tempted to automate the procedure--just write a loop and compare vectors, one by one; select the one with the most matches. You've got to find the RAM somewhere! Alternatively, use jumpers or EEPROM to manually specify a vector.

All of which goes to my thinking that the PC designers were not the best of the bunch. On any system, it's pretty important to track allocatable resources, whether it's I/O ports, interrupt vectors, DMA channels, etc. That this wasn't implemented as part of the BIOS is very surprising.
 
I suppose it's also possible that they just never imagined all of the things people would try to do with the platform. Everyone was trying things back in the days, and it was all different and in its infancy - no one really knew what the future was going to entail or require. It's probably easy to say in hindsight that they missed what is some really obvious stuff today.

As time goes on I've been thinking that a small block of RAM dedicated to each 2k option ROM block might not have been a bad idea. It needs a little computation to figure out where your block is, but it gives you somewhere deterministic to put things. But also, RAM was at a premium in some ways, every little bit allocated here and there subtracts from everything else that the system could do otherwise.

The configuration jumper idea is interesting but then requires an IO address to be able to read it and that's got to come from somewhere too.

In all honesty I think it should really just be a compile time software problem. Access to programmers and assemblers/compilers is not as much of an issue today as it was "back in the day". If I ever released anything publicly it would likely come with the software open source, and if anyone had a conflict they could just modify it and program a non-conflicting version of the software. Job done. Not entirely plug and play but pretty darn close.

Ive got a few more thoughts and ideas to mull over now at least.
 
From what I've always been told, there is no "100% safe vector" to use (because if there were someone would use it and it wouldn't be "safe" anymore).

You could browse through the old Ralf Brown Interrupt List (http://www.ctyme.com/intr/int.htm) and see if you can find one that seems to have no known relevant use (say if your card is for an XT class PC and a given INT was only ever observed in a specific 386+ only instance). Some of these http://www.ctyme.com/intr/cat-034.htm seem fairly unlikely to be found in the wild.

It's also not unheard of for devices to "appropriate" unlikely-to-be-used memory in the BDA space. For example, some Western Digital XT hard drive adapters (62-000043-0xx for sure) use space near the bottom of the BIOS temporary boot stack (around 30:C4 - 30:D2 I believe) for their own configuration/state data after POST. Not suggesting that, just saying it's been tried and done by a major manufacturer.

Either way, you'd still be playing the odds game, so just a matter of weighing the pros and cons of adding hardware (RAM) versus the odds that there *may* be a conflict, and in that rare situation it'd be fairly simple to offer a patched version for such a specific corner case. :unsure:
 
Last edited:
Some SCSI adapter chips implemented a small (e.g. 64 byte) "scratchpad" RAM. One that comes to mind is the NCR 53C400, but I don't know if it was ever used to "chain" interrupt ISRs. ISA interrupts have always been a pain in the posterior on the PC architecture. ISA PnP sort of handles this--until it doesn't.
 
You can always steal 1K from the top of conventional memory.
 
On memory-starved applications, that doesn't always play well. But you see what I mean about the BIOS being poorly thought out. No boot-time memory reservation request mechanism. You need to take multiples of 1KB even if all you need is 4 bytes.
 
Sure it's not ideal but if you need RAM it works. Good enough for XTIDE and not any worse than a TSR.
 
I know--I used it in SIMCGA for "booter" games. Load the resident in high memory; decrease the amount seen by the BIOS and INT 19H to get the game to load. It worked surprisingly well. But that was, what--35 years ago?
 
Back
Top