Jump to content

Hardware Expansion and Driver Handling


Recommended Posts

13 hours ago, BruceMcF said:

Why not in one of the unused ROM segments? They surely won't be filling up all 512K of the ROM.

That would work. Additionally, from what I gathered, there are still additional select lines available on the $01 register. We could use one of those lines to select internal or external ROM. So this basically would double the bank count, where half of the banks are the user ROM chip.

So here's the fun part... each 8K bank on the ROM could be a different user-installed program, and the programs that require more than one bank would need to be smart enough to read the current bank register before doing a far jump. The code won't even need to be relocatable, because the 16-bit address would be the same for each bank. 

This does make me think of an additional change for the OS... a small block of RAM should be set aside for driver configuration. I don't think it needs to be much, maybe just a single page, with a set number of addresses per User bank. Assuming there are 8 banks of User ROM, then each bank would have a 32 byte block in configuration RAM. 

So the convention would be...

If the card is in slot 0, the driver software is in bank 0, and the configuration data is in 0-31 of the configuration page. 
If the card is in slot 1, the driver software is in bank 1, and the configuration data is in 32-63 of the configuration page. 
If the card is in slot 2, the driver software is in bank 2, and the configuration data is in 64-95 of the configuration page. 
If the card is in slot 3, the driver software is in bank 3, and the configuration data is in 96-127 of the configuration page. 

That leaves banks 4-7 for option ROM software.

 

 

Edited by TomXP411
Link to comment
Share on other sites

Actually, we don't even need to do that. From what I gathered, there are still additional select lines available on the $01 register. We could use one of those lines to select internal or external ROM. So this basically would double the bank count, where half of the banks are the user ROM chip. 

 

No you can’t. Not without supporting circuitry on the motherboard. The onboard ROM will still activate it will just end up mirroring. If you hooked up an extra ROM then both the extra ROM and the internal ROM would activate. You would need to add an extra circuit that disables the onboard ROM and then an extra ROM would work.

 

 

Sent from my iPhone using Tapatalk

Link to comment
Share on other sites

22 minutes ago, Lorin Millsap said:

 
No you can’t. Not without supporting circuitry on the motherboard. The onboard ROM will still activate it will just end up mirroring.
 

Kevin said the board would support that, here: 

The easy way to do this is put a ROM chip on the expansion card and run a jumper wire from the chip's CS pin to the unused bank pin on the motherboard. Bank out the system RAM and bank in the ROM by setting the correct value in $01, and code is running from the expansion ROM. 

 
Edited by TomXP411
Link to comment
Share on other sites

Kevin said the board would support that, here: 
The easy way to do this is put a ROM chip on the expansion card and run a jumper wire from the chip's CS pin to the unused bank pin on the motherboard. Bank out the system RAM and bank in the ROM by setting the correct value in $01, and code is running from the expansion ROM. 
 

You are probably right. The board as it is now doesn’t support that though the pins are free. It just needs a way to disable the onboard ROM and select a separate one instead and that just doesn’t exist on the current design. This could be accomplished via a single 138 chip connected to the extra 3 pins, with the first select going to the onboard ROM. If a larger connector was used for the expansion then you could put ROMs on the expansion. However o don’t think that’s going to happen as it drives up cost and uses more board real estate.

So from that standpoint I would rather see a couple I2C lines on the expansion instead if we wanted ROMs. I don’t know that it will happen though. Technically if you wanted I2C you could just use a pin header and a jumper to the existing I2C pins on the user port.


Sent from my iPhone using Tapatalk
Link to comment
Share on other sites

9 hours ago, TomXP411 said:

Kevin said the board would support that, here: 

The easy way to do this is put a ROM chip on the expansion card and run a jumper wire from the chip's CS pin to the unused bank pin on the motherboard. Bank out the system RAM and bank in the ROM by setting the correct value in $01, and code is running from the expansion ROM.

 

Though the easiest way altogether is just use one of the however many User available FlashROM banks, because the selection logic for that is already done.

It would be straightforward to program the kernel to do a Far call to a specific ROM bank entry point based on the startup code stored in the RTC. Indeed, that could be the autostart mechanism ... if nothing is selected, the utility stores the ROM bank entry point for Basic COLD start, if you select autostart, the utility stores the ROM bank entry point for the autostart routine in Kernel, and you can explicitly specify a Far call location to run start-up code stored in a User segment of FlashROM.

BTW, FlashROM segments are 16K.

A parsimonious way to support ROM on an expansion card would to put the bits of the ROM bank out on an eight pin block header, and a ROM expansion card simply has it's own matching pin block header and a ribbon cable, with the specification that bit7 should be high to select external ROM and then bit5&6 select which card is being addressed. That allows 128K ROM per card. Then the extension required to the prototype logic is simply that internal ROM is not selected when bit7 is high ...

... then it's up to the card to detect that the address is in the ROM range at the same time that the high bit of the ROM bank is high, but that's only ROMB7=A15=A14=1, and ROMB5:ROMB6 matches the value in the jumper block.

But I don't know if the game is worth the candle, since with a single User FlashROM segment you can easily have the program support to access 3-wire serial ROM, and if there are enough GPIO free on the Serial Port after supporting the bit banged serial port, you can bit bang one of the serial ROM interfaces and have thee select pins to allow a User port daughter-board with four sockets for 3 wire serial ROM. Ditto on an expansion card, except it includes the VIA ... but same programming, just different I/O space.

And just as easily, a User FlashROM segment can just load a set of RAM segments with code on the SD card, and you have the equivalent effect, with no additional hardware overhead. And the files from the SD card would likely load faster than data from a serial ROM if it uses base I2C or 3-wire Microwire.

 

Edited by BruceMcF
Link to comment
Share on other sites

5 hours ago, BruceMcF said:

Though the easiest way altogether is just use one of the however many User available FlashROM banks, because the selection logic for that is already done.

It would be straightforward to program the kernel to do a Far call to a specific ROM bank entry point based on the startup code stored in the RTC. Indeed, that could be the autostart mechanism ... if nothing is selected, the utility stores the ROM bank entry point for Basic COLD start, if you select autostart, the utility stores the ROM bank entry point for the autostart routine in Kernel, and you can explicitly specify a Far call location to run start-up code stored in a User segment of FlashROM.

BTW, FlashROM segments are 16K.

A parsimonious way to support ROM on an expansion card would to put the bits of the ROM bank out on an eight pin block header, and a ROM expansion card simply has it's own matching pin block header and a ribbon cable, with the specification that bit7 should be high to select external ROM and then bit5&6 select which card is being addressed. That allows 128K ROM per card. Then the extension required to the prototype logic is simply that internal ROM is not selected when bit7 is high ...

... then it's up to the card to detect that the address is in the ROM range at the same time that the high bit of the ROM bank is high, but that's only ROMB7=A15=A14=1, and ROMB5:ROMB6 matches the value in the jumper block.

But I don't know if the game is worth the candle, since with a single User FlashROM segment you can easily have the program support to access 3-wire serial ROM, and if there are enough GPIO free on the Serial Port after supporting the bit banged serial port, you can bit bang one of the serial ROM interfaces and have thee select pins to allow a User port daughter-board with four sockets for 3 wire serial ROM. Ditto on an expansion card, except it includes the VIA ... but same programming, just different I/O space.

And just as easily, a User FlashROM segment can just load a set of RAM segments with code on the SD card, and you have the equivalent effect, with no additional hardware overhead. And the files from the SD card would likely load faster than data from a serial ROM if it uses base I2C or 3-wire Microwire.

 

I'm making the (perhaps unfounded) assumption that the system ROM banks will all be occupied. If not, then the obvious answer is to flash the system ROM... and hope you don't screw it up.  😃

Maybe something like the GGLabs Flash ROM, which sits in a DIP carrier....  

https://gglabs.us/node/1933

 

Link to comment
Share on other sites

I'm making the (perhaps unfounded) assumption that the system ROM banks will all be occupied. If not, then the obvious answer is to flash the system ROM... and hope you don't screw it up.  [emoji2]

Maybe something like the GGLabs Flash ROM, which sits in a DIP carrier....  

https://gglabs.us/node/1933

 

The internal ROM is writable, with limitations. However you may have the routines you can put on slots, that doesn’t mean the KERNAL knows that they exist or how to use them, and patching the routines is actually easier and cleaner to do again through the SD card. Easier to implement and easier to fix if you screw up.

 

 

Sent from my iPhone using Tapatalk

  • Like 1
Link to comment
Share on other sites

2 hours ago, TomXP411 said:

I'm making the (perhaps unfounded) assumption that the system ROM banks will all be occupied. If not, then the obvious answer is to flash the system ROM... and hope you don't screw it up.  😃

Maybe something like the GGLabs Flash ROM, which sits in a DIP carrier....  

https://gglabs.us/node/1933

 

When they went from 128K and 8 ROM banks to 512K and 32 ROM banks, I think that put paid to the assumption that they'd fill up every bank with essential system code.

But given the speed of the SD card, it you fill up a page of Golden RAM and a couple of High RAM segments with drivers, that would load fast enough you wouldn't really notice it.

Edited by BruceMcF
Link to comment
Share on other sites

The SD card bit still confuses me a little bit - is it correct to say that for heavierweight drivers this could require more RAM than if they were stored in ROM? I'm thinking say like some sort of network or serial API to various hardware cards where the driver might be hiding a lot of the low level details so programs just have to worry about reading or write bytes or some such. Here I could see lots of jumps over to driver routines to do things where ROM might be more efficient than having to shuffle RAM around or to/from the SD card? Thinking about a big program here (say a game with lots of music and graphics being loaded into banks and things).

I do agree, though, that updating drivers would be much easier (and safer) using the SD card for sure. I know folks are worried about blowing away the kernel on the main ROM but a jumper to the WE pin might suffice for that? Might be slightly annoying to open up the case on a driver update, but one would have to do that to initially install the card anyway and I suppose brave souls can leave WE enabled. I'd imagine folks that have a ROM reader can just back the chip up directly and, if the kernel did get blown away, can just reflash the chip. Of course not everyone will have the capability (or desire) to do that.

Link to comment
Share on other sites

3 hours ago, m00dawg said:

The SD card bit still confuses me a little bit - is it correct to say that for heavierweight drivers this could require more RAM than if they were stored in ROM? I'm thinking say like some sort of network or serial API to various hardware cards where the driver might be hiding a lot of the low level details so programs just have to worry about reading or write bytes or some such. Here I could see lots of jumps over to driver routines to do things where ROM might be more efficient than having to shuffle RAM around or to/from the SD card? Thinking about a big program here (say a game with lots of music and graphics being loaded into banks and things).

I do agree, though, that updating drivers would be much easier (and safer) using the SD card for sure. I know folks are worried about blowing away the kernel on the main ROM but a jumper to the WE pin might suffice for that? Might be slightly annoying to open up the case on a driver update, but one would have to do that to initially install the card anyway and I suppose brave souls can leave WE enabled. I'd imagine folks that have a ROM reader can just back the chip up directly and, if the kernel did get blown away, can just reflash the chip. Of course not everyone will have the capability (or desire) to do that.

I don't know about to/from RAM, but yes, loading the bulk of the drivers into a High RAM segment would by definition use more High RAM than using a ROM slot. They seem like they would be basically equivalent in terms of low RAM use, which would be mostly the routine called directly in the vector chain checking whether the device or file it is managing is being referred to, and if not calling the previous routine in the chain. If it is the one to call, that'd be a far jump and the end of the low RAM usage.

As far as resource conflicts, that comes with the territory of working within resource constraints. A game that maxes out its use of High RAM might need you to cold start the system and then rerun CONFIG when done with it.

It's not that they are stored in ROM that saves the High RAM, it's that they would execute in the ROM window, so they would only need to use a High RAM segment for data.

I don't see that the WE for the flashROM would be left enabled ... filling in a User slot would be something done with a substantial amount of care, and I would very much prefer a card for which it is an option, but not the only option, so soft loading the driver into one or more High RAM segments is also an option. But once a ROM slot has been written, the WE can be bumpered out again to return to "less likely to brick your board" mode.

 

Link to comment
Share on other sites

6 minutes ago, BruceMcF said:

I don't see that the WE for the flashROM would be left enabled ... filling in a User slot would be something done with a substantial amount of care, and I would very much prefer a card for which it is an option, but not the only option, so soft loading the driver into one or more High RAM segments is also an option. But once a ROM slot has been written, the WE can be bumpered out again to return to "less likely to brick your board" mode.

This is why I wanted to see a second slot for user ROMs. David explicitly said, at one point, that he does not want to install an In System Programmer for the KERNAL ROM, so if we want to re-flash the KERNAL, we will have to remove the chip, flash it with a programmer, and re-install it. 

 

Edited by TomXP411
  • Like 1
Link to comment
Share on other sites

4 minutes ago, BruceMcF said:

I don't see that the WE for the flashROM would be left enabled ... filling in a User slot would be something done with a substantial amount of care, and I would very much prefer a card for which it is an option, but not the only option, so soft loading the driver into one or more High RAM segments is also an option. But once a ROM slot has been written, the WE can be bumpered out again to return to "less likely to brick your board" mode.

That was more highlighting my preference since, in a pinch, I could just reflash the ROM. Unless it's some crazy part, I already have a ROM burner I used for other projects. In general though, I agree, the expectation should probably be to only enable said jumper during the installation process of a card or a driver upgrade?

These seems like rare events, relative to day to day use anyway, to the point that I think it would be a reasonable approach - if one that needed to be well documented. To eb it's just too tantalizing not to use all that available ROM space for something.

  • Like 1
Link to comment
Share on other sites

On 1/11/2021 at 6:59 AM, BruceMcF said:
On 1/10/2021 at 9:04 PM, Cyber said:


I thought KERNAL would be in ROM, and would run directly from there. So how do I change its vector entries in ROM?

There is a set of vectors that various I/O routines use, between the hardware stack at $01xx and the Golden RAM at $0400-$07FF.

As I did not previously know of these vectors, I went hunting and found this...

I believe that the Commodore 64 vectors are as follows (and Commander X16 seems to be the same):

$0314-$0315
788-789

Execution address of interrupt service routine.
Default: $EA31.

$0316-$0317
790-791

Execution address of BRK service routine.
Default: $FE66.

$0318-$0319
792-793

Execution address of non-maskable interrupt service routine.
Default: $FE47.

$031A-$031B
794-795

Execution address of OPEN, routine opening files.
Default: $F34A.

$031C-$031D
796-797

Execution address of CLOSE, routine closing files.
Default: $F291.

$031E-$031F
798-799

Execution address of CHKIN, routine defining file as default input.
Default: $F20E.

$0320-$0321
800-801

Execution address of CHKOUT, routine defining file as default output.
Default: $F250.

$0322-$0323
802-803

Execution address of CLRCHN, routine initializating input/output.
Default: $F333.

$0324-$0325
804-805

Execution address of CHRIN, data input routine, except for keyboard and RS232 input.
Default: $F157.

$0326-$0327
806-807

Execution address of CHROUT, general purpose data output routine.
Default: $F1CA.

$0328-$0329
808-809

Execution address of STOP, routine checking the status of Stop key indicator, at memory address $0091.
Default: $F6ED.

$032A-$032B
810-811

Execution address of GETIN, general purpose data input routine.
Default: $F13E.

$032C-$032D
812-813

Execution address of CLALL, routine initializing input/output and clearing all file assignment tables.
Default: $F32F.

$032E-$032F
814-815

Unused.
Default: $FE66.

$0330-$0331
816-817

Execution address of LOAD, routine loading files.
Default: $F4A5.

$0332-$0333
818-819

Execution address of SAVE, routine saving files.
Default: $F5ED.

Information taken from https://sta.c64.org/cbm64mem.html

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

20 hours ago, Lorin Millsap said:

On a lot of this it boils down to system side software support, much of which is not yet implemented.

An idea I advocate is that the config files are in plain text, and that some code in the KERNAL reads them one line at a time and then dumps them into the buffer in BASIC, so line numbers don’t matter so much, and a program getting overwritten is less of an issue as it’s just doing it all in immediate mode. There are some limitations to this, things like condition checks and branches often rely on line numbers. But it would work well enough for loading in subprograms, including assembly. If it calls an assembly program we just have to trust that it returns control, otherwise the rest of the “script” won’t get executed.


Sent from my iPhone using Tapatalk

Note that if the config script file is opened in a known channel, you can have a program that does condition checking and optional execution by reading the test from the following text, reading the optionally performed action, but only stuffing it into the line buffer if the test was passed. Either way, the subsequent line is next to be read when control passes back to the configuration script routine.

Link to comment
Share on other sites

7 minutes ago, m00dawg said:

That was more highlighting my preference since, in a pinch, I could just reflash the ROM. Unless it's some crazy part, I already have a ROM burner I used for other projects. In general though, I agree, the expectation should probably be to only enable said jumper during the installation process of a card or a driver upgrade?

These seems like rare events, relative to day to day use anyway, to the point that I think it would be a reasonable approach - if one that needed to be well documented. To eb it's just too tantalizing not to use all that available ROM space for something.

Oh, I'm definitely having some tables and optimized multiply routines, the only open question is how many.

  • Like 1
Link to comment
Share on other sites

3 hours ago, TomXP411 said:

This is why I wanted to see a second slot for user ROMs. David explicitly said, at one point, that he does not want to install an In System Programmer for the KERNAL ROM, so if we want to re-flash the KERNAL, we will have to remove the chip, flash it with a programmer, and re-install it. 

 

I had not seen that, but given "work", the curse of the programming hobbyist, I certainly have not always been able to keep up.

And I have already seen how cheap some of those are when looking for ones that would handle Microchip SLDs (which are not the cheap ones), so it's surely nowhere near as expensive as it used to be back in the days of actual EPROMs to get a FlashEPROM programmer.

But it's six of one, half a dozen of the other ... I surely would not be wanting to insert and remove a User ROM every time I wanted to use a card, so if there was more than one set of ROM images to write in the FlashROM in the User ROM socket, it would still be a case of putting the FlashROM into a programmer to build it's set of ROM slots.

The only alternative that avoids that is the ROM on the card, which requires the Kernal ROM to not be selected when the high bit of the ROM bank is set ... but as mentioned, a block pin header to allow the rest of the bank bits to come out on a ribbon cable would probably be cheaper than a ZIF socket.

 

Edited by BruceMcF
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

 

 

 

Edited by BruceMcF
Link to comment
Share on other sites

3 hours ago, BruceMcF said:

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.

From a software architecture point of view, It makes sense only if you want to override the vector.
But if you want to print chars on screen or to a serial link, you want to have both vectors and you want to access them directly.
So instead of having a vector checking I don't know what in order to know if the call was meant for it or another, I would prefer a kinda generic call with a parameter being an output descriptor.
Does it make sense ?

Link to comment
Share on other sites

On 1/11/2021 at 6:26 PM, TomXP411 said:

The easy way to do this is put a ROM chip on the expansion card and run a jumper wire from the chip's CS pin to the unused bank pin on the motherboard. Bank out the system RAM and bank in the ROM by setting the correct value in $01, and code is running from the expansion ROM. 

This is a good idea that can be done natively using the expansion connector, with only minor changes to the current design.  First we need to free up some expansion connector pins.

I never understood the peculiar idea to send five IO selects to every expansion connector.  It wastes four connector pins and burdens every expansion card with switches to pick one of them.  Instead, send a different IO select to each connector.  32 bytes of memory-mapped IO is plenty for most applications.  For those that want more we can exploit the unused ROM banks as described next.

Each expansion slot now has four free pins.  Use one pin as the slot select, which is a trivial decode of ROM bank register upper bits and the existing ROM address space decode.  The remaining three bits can be just the three LSBs of the bank register.  This sparse decoding "wastes" lots of ROM banks but they were unused anyway.  Now each slot has eight banks = 128KB of address space to use as desired.  Nothing says ROMs need to live here of course.  It can be used for anything.  A dumb frame buffer might be a fun project.

Yes, this idea does require a minor addition to decoding glue logic.  I think it's a bargain but this isn't my project.

What to do with the remaining unused IO select?  I would use it for a UART but I doubt the team has the stomach for that.

Link to comment
Share on other sites

46 minutes ago, kktos said:

From a software architecture point of view, It makes sense only if you want to override the vector.
But if you want to print chars on screen or to a serial link, you want to have both vectors and you want to access them directly.
So instead of having a vector checking I don't know what in order to know if the call was meant for it or another, I would prefer a kinda generic call with a parameter being an output descriptor.
Does it make sense ?

The original call does not have to check anything, it just jumps to the Kernel routine to perform that action. And the Kernel does NOT have anything set-up to "install" device drivers for devices it does not handle. #0 is the keyboard, #1 was the datasette in the C64, it is the SD card in the CX16, #2 is the serial interface implemented through bit banging the User Port, #3 is the display, and #4-#30 are IEC devices (though I guess the CX16 Kernel treats #8 as a synonym for #1).

So when it does a OPEN on Device #7, if your device driver is handling the device that is being referred to as #7, it HAS to say, "oh, wait, don't go do the Kernel routine and put that out on the IEC bus, I am going to handle that instead. The Kernel has no mechanism for "installing" your API for device #7. Instead, you (or, in practice, an installation program) preempts that call, and jumps to it's own OPEN routine when the current DEVICE# set by SETLFS is #7. But if the DEVICE# registered by SETLFS is not #7, it jumps to the routine that was in the vector when the driver installer was run.

Now if you have #7 is your parallel port slipnet and you have a serial port extension card, one of those two driver installation programs will be running after the other one, but if both of them respect the rudimentary memory allocation facilities, it's fine, since the most recently installed vector will be in place when the second driver installation program runs, so when OPEN is called, first the serial port driver checks if #2 has been registered by SETLFS, if not then it jumps the next in the chain and the parallel port driver checks if #7 has been registered, if not it jumps to the next in the chain and the Kernel OPEN routine executes.

Now, if complex configurations become commonplace, a more efficient dispatcher is a central device manager that loads on top of the coldstart vector, copies the cold start vector, and has dispatch tables and an API for installing a device into the device manager. And if makers of hardware or other programmers write driver install programs that use that 3rd party device manager API, then you have a more efficient system that checks the device number and directly dispatches the correct driver.

But for the case where some particular 3rd party device driver is the only device driver installed, the original Kernel vector system is more efficient and where it's only a couple installed, it's probably not slower than an explicit device driver dispatch system. So I'd expect the original Kernel system to be supported for those who want Basic access to a device, and other systems specialized for more complex configurations to be supported by a smaller set of hardware.

Note that since this is not running on an operating system, there is no necessity to use the Kernel API, so lots of card might ship with just their own API that you can load into High RAM and instructions how to call it's routines. For those, the Kernel API device drivers might be written by a 3rd party.

Link to comment
Share on other sites

1 hour ago, picosecond said:

This is a good idea that can be done natively using the expansion connector, with only minor changes to the current design.  First we need to free up some expansion connector pins.

I never understood the peculiar idea to send five IO selects to every expansion connector.  It wastes four connector pins and burdens every expansion card with switches to pick one of them.  Instead, send a different IO select to each connector.  32 bytes of memory-mapped IO is plenty for most applications.  For those that want more we can exploit the unused ROM banks as described next.

Each expansion slot now has four free pins.  Use one pin as the slot select, which is a trivial decode of ROM bank register upper bits and the existing ROM address space decode.  The remaining three bits can be just the three LSBs of the bank register.  This sparse decoding "wastes" lots of ROM banks but they were unused anyway.  Now each slot has eight banks = 128KB of address space to use as desired.  Nothing says ROMs need to live here of course.  It can be used for anything.  A dumb frame buffer might be a fun project.

Yes, this idea does require a minor addition to decoding glue logic.  I think it's a bargain but this isn't my project.

What to do with the remaining unused IO select?  I would use it for a UART but I doubt the team has the stomach for that.

I don't think it's a question of stomach, I think its a question of build cost. They were going to go with the WDC UART until they found out there was a bug, then tried to add a UART for the VERA, but then decided the pins were more important for register addressing, then decided to go with bit-banging serial on the VIA based User port. And given the variety of preferences in how to have the UART work, it really is the kind of thing the expansion cards are FOR.

So the unused I/O select is going to continue to go to the expansion cards.

I would LIKE the /IOSelect direct 4-7 to slots 1-4 and /IOSelect 3 decode A3 and A4 to distribute an additional 8 bytes to slots 1-4, so each I/O space has a distinct slot it connects to ... which would free up three current /IOSEL pins for other uses ... but I expect the design team is going to go for the approach that makes it easier to have a single slot on the small form factor card that can still support multiple slots through a riser board.

Link to comment
Share on other sites

3 hours ago, BruceMcF said:

a more efficient dispatcher is a central device manager that loads on top of the coldstart vector, copies the cold start vector, and has dispatch tables and an API for installing a device into the device manager. And if makers of hardware or other programmers write driver install programs that use that 3rd party device manager API, then you have a more efficient system that checks the device number and directly dispatches the correct driver.

precisely what I was thinking 🙂
I do love this idea. Clean and Neat.

Either for each command a vector table for each devices.
Or the other way round for compactness:
For each "allocated" device, its vectors table.

Ok, as you said, no OS..... but that does mean we cannot do the things properly 😉 I know this is retrocomputing... but we're grown up now ;oD
I know how my 16 years old self would have done it on his //c ...... I'd rather try differently now :oD

Link to comment
Share on other sites

The thing about being able to work on the bare metal is there is no obstacle to a community created dispatcher. The vector tab!e is entire?y agnostic as to what is getting executed, as long as the calls that do not have a replacement routine are directed to the original Kernal routine.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use