reifsnyderb Posted September 6, 2023 Share Posted September 6, 2023 Has anyone re-mapped a drive via firmware? In the XL/XE OS, any calls to SIO first go through PIO. So, in theory, a parallel device should be able to re-map disk drives. Thus far, I have this partially working. My theory is that since Atari uses $31 in DDEVIC and DUNIT is the drive number that it should be possible to, via a parallel card, swap out DUNIT to another drive number and be able to re-map the drives. i.e. DDEVIC $31, DUNIT 4 (D4:) is called but you'd like to map D4: to physical D2: The firmware, on a parallel device, should be able to swap out DUNIT 4 for DUNIT 2 then return without handling anything else. So, the SIO would pick this up and access D2:. To do this, it appears that DUNIT is also stored on the stack prior to calling an parallel device as the OS R2 source code shows: ;** PIO - Parallel Input/Output ;* ;* ENTRY JSR PIO ;* ;* NOTES ;* Problem: in the CRASS65 section, CRITIC was: ;* zero-page. ;* ;* MODS ;* Y. M. Chen 02/18/83 ;* 1. Bring closer to Coding Standard (object unchanged). ;* R. K. Nordin 11/01/83 PIO = * ;entry ; Initialize. LDA #1 ; STA CRITIC ;indicate critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD LDA DUNIT ;device unit number PHA ;save device unit number LDA PDVMSK ;device selection mask BEQ PIO2 ;if no device to select ; For each device, pass request to device I/O routine: LDX #TPDSL ;offset to first byte beyond table PIO1 JSR SNP ;select next parallel device BEQ PIO2 ;if no device selected TXA PHA ;save offset JSR PDIOV ;perform parallel device I/O PLA ;saved offset TAX ;restore offset BCC PIO1 ;if device did not field request ; Restore Floating Point Package. LDA #$00 ;select FPP (deselect device) STA SHPDVS ;device select shadow STA PDVS ;device select BEQ PIO3 ;exit ; Perform SIO. PIO2 JSR SIO ;perform SIO ; Exit. PIO3 PLA ;saved device unit number STA DUNIT ;restore device unit number LDA #0 ; STA CRITIC ;indicate non-critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD STY DSTATS LDY DSTATS ;status (re-establish N) RTS ;return So, part of my parallel device code swaps out DUNIT as follows: ; Re-map physical drives ; On entry, Device ID is in A RDREMP = * TAX ; Move device ID to X LDA #low RDDMAP ; Setup page 0 pointer STA RDA1 LDA #high RDDMAP STA RDA2 TXA ; Load A with Device ID LDY #$04 ; Index on Y RDRMP1 DEY ; Set value of Y CMP (RDA1),Y ; Compare Device ID with new Device ID BEQ RDRMP2 ; If DUNIT = new DUNIT, map it CPY #$00 ; If no match found, exit. BEQ RDRMP4 ; skip unmapping device for debugging....was RDRMP3 JMP RDRMP1 RDRMP2 INY ; Y is the new DUNIT PLA ; Get the low byte of the return address STA RDA3 ; Save it PLA ; Get the high byte of the return address STA RDA4 ; Save it PLA ; Get DUNIT and discard it. TYA ; Put the new DUNIT on the stack PHA LDA RDA4 ; Put the high byte of the return address back PHA LDA RDA3 ; Put the low byte of the return address back PHA JMP RDRMP4 ; CLC ; Clear carry to indicate I/O not handled by the RAM Disk ; RTS This starts to work but still has problems. Altirra's Performance Analyzer shows that repeated calls are made to the emulated physical device until it responds. When it responds, the directory has the wrong number of sectors reported. Has anyone tried this before? Am I missing something somewhere? Thanks! Quote Link to comment Share on other sites More sharing options...
E474 Posted September 6, 2023 Share Posted September 6, 2023 The UnoCart uses a modified Altirra OS which remaps calls to D1 to the SD card on the UnoCart. The modified code is in (IIRC) : https://github.com/robinhedwards/UnoCart/blob/master/source/Atari/UnoCartOS/pio.s Quote Link to comment Share on other sites More sharing options...
reifsnyderb Posted September 7, 2023 Author Share Posted September 7, 2023 2 hours ago, E474 said: The UnoCart uses a modified Altirra OS which remaps calls to D1 to the SD card on the UnoCart. The modified code is in (IIRC) : https://github.com/robinhedwards/UnoCart/blob/master/source/Atari/UnoCartOS/pio.s Interesting. However, I am trying to remap the drives with a stock OS as the card will run on a 1090XL. Quote Link to comment Share on other sites More sharing options...
phaeron Posted September 7, 2023 Share Posted September 7, 2023 There is indeed precedent for doing this -- the 1450XLD parallel disk drive firmware does it. ;=============================================================================== ; SIO vector ; D8F9: AD 4F 02 LDA $024F D8FC: C9 FF CMP #$FF D8FE: F0 28 BEQ $D928 D900: AD 00 03 LDA DDEVIC ;Get device D903: 18 CLC ;Add unit D904: 6D 01 03 ADC DUNIT ; " D907: 38 SEC ;Subtract $32 (D1: + 1, since no unit-1) D908: E9 32 SBC #$32 ; " D90A: 90 1C BCC $D928 ;Exit not handled if <D1: D90C: C9 08 CMP #$08 ;Check if above D8: D90E: B0 18 BCS $D928 ;Exit not handled if >D8: D910: AA TAX ;Use as index D911: AD 48 02 LDA SHPDVS ;Load current PBI device D914: DD 08 D6 CMP $D608,X ;Check against PBI device table D917: F0 11 BEQ $D92A ;Proceed if match D919: CD 4F 02 CMP $024F ; D91C: D0 0A BNE $D928 D91E: AD 01 03 LDA DUNIT ;Get device unit D921: 38 SEC ;Reduce by PBI device count D922: ED 4E 02 SBC $024E ; " D925: 8D 01 03 STA DUNIT ;Update device unit D928: 18 CLC ;Not handled D929: 60 RTS Of course, if you are testing in Altirra, you will need to either disable disk SIO patch or switch it to PBI mode so it can see the modified DUNIT value. 1 1 Quote Link to comment Share on other sites More sharing options...
reifsnyderb Posted September 7, 2023 Author Share Posted September 7, 2023 18 minutes ago, phaeron said: There is indeed precedent for doing this -- the 1450XLD parallel disk drive firmware does it. ;=============================================================================== ; SIO vector ; D8F9: AD 4F 02 LDA $024F D8FC: C9 FF CMP #$FF D8FE: F0 28 BEQ $D928 D900: AD 00 03 LDA DDEVIC ;Get device D903: 18 CLC ;Add unit D904: 6D 01 03 ADC DUNIT ; " D907: 38 SEC ;Subtract $32 (D1: + 1, since no unit-1) D908: E9 32 SBC #$32 ; " D90A: 90 1C BCC $D928 ;Exit not handled if <D1: D90C: C9 08 CMP #$08 ;Check if above D8: D90E: B0 18 BCS $D928 ;Exit not handled if >D8: D910: AA TAX ;Use as index D911: AD 48 02 LDA SHPDVS ;Load current PBI device D914: DD 08 D6 CMP $D608,X ;Check against PBI device table D917: F0 11 BEQ $D92A ;Proceed if match D919: CD 4F 02 CMP $024F ; D91C: D0 0A BNE $D928 D91E: AD 01 03 LDA DUNIT ;Get device unit D921: 38 SEC ;Reduce by PBI device count D922: ED 4E 02 SBC $024E ; " D925: 8D 01 03 STA DUNIT ;Update device unit D928: 18 CLC ;Not handled D929: 60 RTS Of course, if you are testing in Altirra, you will need to either disable disk SIO patch or switch it to PBI mode so it can see the modified DUNIT value. This looks more like a device is selected based upon DUNIT. This differs from what I am doing as I am trying to use a parallel device to intercept and change the DUNIT value. I played around with Altirra's configuration with no effect. Here's the config: I always wondered why I can't just turn off the SIO exceleration mode.... I am not sure making those changes would do anything as I've hacked this OS so that I can use it for development. So, the PIO routine is hacked to just run the RAM Disk functions as so.... PIO = * ;entry ; Initialize. LDA #1 ; STA CRITIC ;indicate critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD LDA DUNIT ;device unit number PHA ;save device unit number ;; LDA PDVMSK ;device selection mask ;; BEQ PIO2 ;if no device to select ; For each device, pass request to device I/O routine: ;; LDX #TPDSL ;offset to first byte beyond table ;;PIO1 JSR SNP ;select next parallel device ;; BEQ PIO2 ;if no device selected ;; TXA ;; PHA ;save offset ;;; JSR PDIOV ;perform parallel device I/O JSR RDISK ; ************************ RAM DISK CODE ;; PLA ;saved offset ;; TAX ;restore offset ;; BCC PIO1 ;if device did not field request BCC PIO2 ; if device did not field request ; Restore Floating Point Package. ;; LDA #$00 ;select FPP (deselect device) ;; STA SHPDVS ;device select shadow ;; STA PDVS ;device select ;; BEQ PIO3 ;exit JMP PIO3 ; Perform SIO. PIO2 JSR SIO ;perform SIO ; Exit. PIO3 PLA ;saved device unit number STA DUNIT ;restore device unit number LDA #0 ; STA CRITIC ;indicate non-critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD STY DSTATS LDY DSTATS ;status (re-establish N) RTS ;return I figure that once the RAM Disk code is working, it's any easy job to convert it to a PBI device. 🙂 Quote Link to comment Share on other sites More sharing options...
phaeron Posted September 7, 2023 Share Posted September 7, 2023 49 minutes ago, reifsnyderb said: This looks more like a device is selected based upon DUNIT. This differs from what I am doing as I am trying to use a parallel device to intercept and change the DUNIT value. No, it also modifies DUNIT. Look at the end of the routine. If DUNIT doesn't correspond to one of the devices that the PBI firmware handles, it subtracts off that number of drives so the next unit number accesses SIO D1:. 49 minutes ago, reifsnyderb said: I played around with Altirra's configuration with no effect. Here's the config: I always wondered why I can't just turn off the SIO exceleration mode.... You don't have any SIO device patches enabled, so the acceleration mode won't do anything. It only takes effect if you have one of the SIO patches checked. Quote Link to comment Share on other sites More sharing options...
reifsnyderb Posted September 7, 2023 Author Share Posted September 7, 2023 10 minutes ago, phaeron said: No, it also modifies DUNIT. Look at the end of the routine. If DUNIT doesn't correspond to one of the devices that the PBI firmware handles, it subtracts off that number of drives so the next unit number accesses SIO D1:. Ok, I see it now. However, if the OS would take control then the OS would take the DUNIT value off of the stack and put it back in DUNIT. I also checked the 1450XLD OS with OS R2 and both have identical PIO functions as follows: ;** PIO - Parallel Input/Output ;* ;* ENTRY JSR PIO ;* ;* NOTES ;* Problem: in the CRASS65 section, CRITIC was: ;* zero-page. ;* ;* MODS ;* Y. M. Chen 02/18/83 ;* 1. Bring closer to Coding Standard (object unchanged). ;* R. K. Nordin 11/01/83 PIO = * ;entry ; Initialize. LDA #1 ; STA CRITIC ;indicate critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD LDA DUNIT ;device unit number PHA ;save device unit number LDA PDVMSK ;device selection mask BEQ PIO2 ;if no device to select ; For each device, pass request to device I/O routine: LDX #TPDSL ;offset to first byte beyond table PIO1 JSR SNP ;select next parallel device BEQ PIO2 ;if no device selected TXA PHA ;save offset JSR PDIOV ;perform parallel device I/O PLA ;saved offset TAX ;restore offset BCC PIO1 ;if device did not field request ; Restore Floating Point Package. LDA #$00 ;select FPP (deselect device) STA SHPDVS ;device select shadow STA PDVS ;device select BEQ PIO3 ;exit ; Perform SIO. PIO2 JSR SIO ;perform SIO ; Exit. PIO3 PLA ;saved device unit number STA DUNIT ;restore device unit number LDA #0 ; STA CRITIC ;indicate non-critical section .BYTE $8D, low CRITIC, high CRITIC ;originally VFD STY DSTATS LDY DSTATS ;status (re-establish N) RTS ;return PIO is where DUNIT is put on the stack, the device firmware is then excecuted, and PIO3, above, is where the DUNIT value is taken off of the stack and stored into DUNIT. My thought is that to re-map the drives, the DUNIT value needs to be removed from the stack and replaced with a new value like I did here: RDRMP2 INY ; Y is the new DUNIT PLA ; Get the low byte of the return address STA RDA3 ; Save it PLA ; Get the high byte of the return address STA RDA4 ; Save it PLA ; Get DUNIT and discard it. TYA ; Put the new DUNIT on the stack PHA LDA RDA4 ; Put the high byte of the return address back PHA LDA RDA3 ; Put the low byte of the return address back PHA JMP RDRMP4 Unfortunately, this only partial works. The drive is re-mapped but certain things aren't quite right. The number of sectors returned is wrong and it takes several SIO requests for the emulated drive to respond. I've been using the Performance Analyzer to try to find the problem but it's a needle in the proverbial haystack. 10 minutes ago, phaeron said: You don't have any SIO device patches enabled, so the acceleration mode won't do anything. It only takes effect if you have one of the SIO patches checked. Good to know. I didn't realize it was related to the SIO patches, above. Now it makes sense. 🙂 Quote Link to comment Share on other sites More sharing options...
phaeron Posted September 7, 2023 Share Posted September 7, 2023 4 hours ago, reifsnyderb said: PIO is where DUNIT is put on the stack, the device firmware is then excecuted, and PIO3, above, is where the DUNIT value is taken off of the stack and stored into DUNIT. Sure, but it's restored in the epilogue right before returning to user code, after the regular code runs to send the request out to the SIO bus. The parallel disk device doesn't eat the request, so it falls through to the rest of the PBI devices which also don't, and then it calls the regular SIO code at PIO2 before DUNIT is restored. The caller won't see a change in DUNIT, but the request sent out on the SIO bus will. 1 Quote Link to comment Share on other sites More sharing options...
reifsnyderb Posted September 7, 2023 Author Share Posted September 7, 2023 (edited) 5 hours ago, phaeron said: Sure, but it's restored in the epilogue right before returning to user code, after the regular code runs to send the request out to the SIO bus. The parallel disk device doesn't eat the request, so it falls through to the rest of the PBI devices which also don't, and then it calls the regular SIO code at PIO2 before DUNIT is restored. The caller won't see a change in DUNIT, but the request sent out on the SIO bus will. Ok, I just read and re-read what you wrote and looked at the PIO code again. For some stupid reason, I mis-read the PIO code. 😞 I was thinking that PIO took DUNIT from the stack before calling SIO. So, I only put the new DUNIT value on the stack and didn't bother over-writing DUNIT itself. I was wrongly thinking PIO would overwrite DUNIT, using the stack value, no matter what I did....then spent hours trying to figure out why my code wasn't working correctly. But it partly worked, so that added to the confusion. So, the good news is I added one extra line of code to overwrite DUNIT and it now works and re-maps the drive! Thank you! Below is the code to store the re-mapped DUNIT.... RDRMP2 INY ; Y is the new DUNIT PLA ; Get the low byte of the return address STA RDA3 ; Save it PLA ; Get the high byte of the return address STA RDA4 ; Save it PLA ; Get DUNIT and discard it. TYA ; Put the new DUNIT on the stack PHA LDA RDA4 ; Put the high byte of the return address back PHA LDA RDA3 ; Put the low byte of the return address back PHA STY DUNIT ; Overwrite DUNIT with new DUNIT value. JMP RDRMP4 Edited September 7, 2023 by reifsnyderb Quote Link to comment Share on other sites More sharing options...
reifsnyderb Posted September 7, 2023 Author Share Posted September 7, 2023 I just realized that by changing the DUNIT value, in the stack, might break the "illusion" of re-mapping the drives by providing the real drive to any software that checks the DUNIT value after the SIO request is made. So, I now think the stack should be left alone and just DUNIT changed. For example: RDRMP2 INY ; Y is the new DUNIT STY DUNIT ; Overwrite DUNIT with new DUNIT value. JMP RDRMP4 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.