8 hours ago, lamb-duh said:
I've been following along with the thread, but I'm still a bit confused about a few different things,
1. what does it mean that driver software will need to be relocatable-- does this mean code that does not use any absolute addressing, or is there going to be some kind of loader that supports relocation in some way?
2. if I'm writing a driver for a serial port, I would be writing new routines for chrin, chrout, &c, right? so that means that I replace each routine with a new one that will check if this call is directed at this piece of hardware, and process it if it is, or else call the original routine (I guess you would do that based on the device id in this case?)
3. what does non-driver software have to do to not interfere drivers? are drivers loaded in ram somewhere already marked for kernel use?
4. given that (unless I'm completely wrong on #2) every driver that is loaded will slow down certain system calls, do we really want to autoload drivers when the system comes on? I think in most cases it would make more sense to write startup scripts for software that needs certain drivers that load the needed drivers and start the program. but on the other hand, there are some drivers you might want to always load immediately, and having the option isn't going to hurt anything.
1. Relocatable in some way. If the driver has it's own loader program, it is up to each driver how it relocates. But whether the driver has it's "check and call" routine in Golden RAM, or by pulling down the top of Basic RAM, that code will need to adapt to how much Golden RAM is alread in use or where the top of Basic is located. And if the Driver routines are stored in a free High RAM segment, it will have to store the bank number somewhere in its "check and call" routines.
Note that the check and call routine can be LARGELY relocatable, since each check and call routine will be relatively short. You might have only the call to the prior routine in the chain and the far call to the the driver routine in high RAM to patch.
2. Exactly. The loader program will store the vector that is already there, and the "check and call" routine will call the prior vector if the check shows it is not used.
3. 3a: nothing other than respect RAM allocation. Grab low RAM from the top of available Basic RAM. If Golden RAM has some allocation mechanism (standard or de facto), respect it. If a High RAM segment is marked as in use, don't use it. 3b: No, in the original mechanism there is no marking of what is used for an OPEN/CLOSE/CHRIN/CHROUT driver, and there hasn't been any promise of adding something like that. To be clear, I don't know if a High RAM segment BAM is promised, but it's been mentioned as a possibility and since it is only 32 bytes, I am hoping it will be included. At present the only memory allocation information is the top of RAM available for a Basic program.
When using this kind of KERNAL routine wedge in the C64, "where to put it" was always an issue. But since there so much less RAM available for it, loading multiple KERNAL routine wedges was rarely contemplated and the KERNAL wedge technique not used very often: most wedges used the character input routine in Basic or the Syntax Error vector. KERNAL wedges most often used Golden RAM at $C000-$CFFF, and if you used it, it killed any soft loaded command line wedge. So unless you had a fast loader cart with your Basic command line wedge in ROM, the KERNAL routine wedge wasn't very useful.
4. There is that tradeoff. OPEN will have to always have to be live, but if the driver handles one open channel, the other routines can pass through when the device is not open, which is something the CLOSE routine can handle.
Since the chain is literally each driver storing the address of the vector address when it is loading, you can't close by extracting yourself from the chain. But you easily reduce your overhead in the other calls to 5 clocks by having the start of each check and call routine be:
Driver_op: NOP : NOP
Prior_op: JMP RESET ; This is patched to the prior op vector by the loader routine
Driver_op1: ...
... and when the channel is opened, the nop's are replaced by "BRA Driver_op1". When the device is closed, the BRA Driver_op1 is replaced by "NOP
: NOP". That also conserves Low RAM, since most driver API routines will not have to check whether their device is open ... they only execute when their device is open. Only OPEN itself needs to keep track.
This is why it is handy if a new configuration script can be executed at any time, so you can set up the configuration you want to do something, rather than loading up every driver in your SD card "just in case", which could bog down the KERNAL calls.