+FarmerPotato Posted October 5 Share Posted October 5 21 hours ago, Lee Stewart said: I think it is even possible it was used by TI programmers on the 990 computers (@FarmerPotato?), but just not passed on to us in the E/A manual That's an interesting question. Coincidentally, I was just reading about file access under DX10, a widely-used operating system for a 990. Main difference: GPL must scan all ROMs for DSRs every time. DX10 has all the information in one linked list in the operating system, let's call it PDTTBL. It's permanent--you don't just plug in new devices. (See SYSGEN below) The CRU address is only used by the DSR code itself. There's no ROM to turn on. CRU address is not stashed per file - only in the device PDT entry, which is permanent. (By GPL I mean in the definition of our operating system, the way the 99/4 works. Documents like 'The GPL interface to the disk peripheral" cover the DSR ROM.) The OPEN #1 we all started with in TI BASIC? The #1 is a system-wide concept for DX10: the LUNO or logical unit number! Before using a device or file, you gave it a LUNO, logical unit number. The table with LUNO stored file#, name, system buffer address, etc. Maybe it cached the DSR entry point. There were global LUNOs for printers, and each user created private LUNOs. BASIC: OPEN #1:"DS01.DOCUMNT.DOC", OUTPUT (DX10 filenames were 7.3 = familiar 10 chars total!) In BASIC on DX10, I imagine it does this: 1. Set LUNO #144 to "DS01.DOCUMNT.DOC". That's done through an XOP. The DSR gets looked up and stashed in the LUNO table. 2. Make a SCB starting with a 0 for DSR, the opcode 0 for OPEN, some flags, 0 for default record length, the LUNO #144 etc. (Our PAB is a subset of this. Alas, PAB has no file #.) 3. XOP @SCB,15 4. Check error code The LUNO is constant through all OPEN,CLOSE,REWIND,CLOSE.. Other than through 99/4 BASIC, we have no LUNO table. If there were, that's where DSRLNK would cache the DSR, CRU etc. And the device name need not be a part of every PAB. There are many more similarities and differences in the actual DSRs. The 99/4 interface is clearly a subset of DX10. 1 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted October 5 Share Posted October 5 Gobs of detail on what a DSRLNK looks like in DX10. DSRLNK? PAB? The analogue of a PAB is a Service Control Block. All the XOPs have a SCB. If you make Service Call 0, you fill out the rest of SCB. The next byte after 0 is the DSR opcode, followed by flags and stuff that would be familiar to us. The analogue of DSRLNK is the Service Call 0 (clearly, the first and most important of service calls!) You first set up a service control block: MYFCB0 BYTE 0 * 0 is my desired function, I/O BYTE 0 * say I want the OPEN opcode ... more DATA ... then XOP @MYFCB0,15 or DXOP SVC,15. * makes SVC a macro for XOP 15 SVC @MYFCB0 There's some great sample code in DX10 Volume 3 section Operating System Code is much simpler than DSRLNK! In DX10, inside Service Call 0, I imagine there is some code to match the device name, 2 characters like 'DS' for disk. (CS is cassette!) It has to walk the global linked list, PDTTBL. Remember that PDTTBL is permanent and has all the known devices. Each entry of PDTTBL is analogous to the DSR list under one of our ROM headers. (Thierry calls this list the true DSRs, as opposed to the other linked lists in our ROM.) If the PDTNAM field matches, it calls that DSR with a BLWP. The DSR gets its own workspace, which is always set up with useful values. So I imagine code like this to match the 2 character device name: LI R0,'DS' the device we're looking for LI R1,PDTTBL pointer to the global table DSR010 MOV *R1,R1 go to first or next entry JEQ DSR030 ?end of list, device not found C PDTNAM(R1),R0 is this a match for our device? JNE DSR010 DSR020 AI PDT$,R1 point to the BLWP vector BLWP *R1 enter the DSR DSR030 * error, device not found ORI R15,>2000 set the EQ bit (i made this up) RTWP See how nice it is to have 2-char device names? Just one Compare instruction! The PDTTBL is a linked list of this data structure: Reference: 5.3.1 WS for PDT - physical device table * Layout of a PDT entry (pretend these are all DATA statements) DORG 0 PDTLNK Link to next PDT PDTMAP Pointer to DSR map file PDTR0 R0 Scratch PDTPRB R1 Pointer to PRB PDTSDF R2 Device status flags PDTDTF R3 Device type flags PDTIB R4 Pointer to device info block R5 Available for the DSR to use ... R11 R12 CRU base R13 Saved WS registers for RTWP ... R15 PDT$ PDT workspace address PDTDSR DSR entry point PDTERR, PDTFLG, error code and flags PDTNAM Device name (2 characters like 'DS') PDTSL1 system log 1 PDTSL2 system log 2 PDTBUF not used PDTBLN Buffer length PDTINT Pointer to DSR interrupt routine PDTDVQ Device queue anchor PDTTM1 Time out count 1 PDTTM2 Time out count 2 PDTSRB Saved PRB address PDTFQL Priority DSR schedule queue word DX10 enters the DSR with a BLWP. The code above sets up R1 to point to PDT$. After BLWP, the new WP points to the PDTR0 in the record. The DSR will use RTWP to return. GeneveOS GeneveOS has one 'Master DSR' list like this. Unfortunately, that ignores our GPL convention. Fortunately, ROMPAGE and the GeneveOS maintainers opened that up to scan PBox cards' DSR ROMs. GEN990 or SYSGEN DX10 is custom assembled and linked on every system when it is installed. This is neat, because it doesn't bloat up with code for devices or features you don't use. A program called GEN990 asks you about all the peripherals you have connected, the CRU address, the interrupt level, and the filename of each DSR. From that, it is able to write the source code to make the PDTTBL. After it generates code, the assembler is invoked. Then the linker connects all the DX10 object code with the custom object. (actually my knowledge is extrapolated from the SYSGEN of its baby operating system, TXDS, which has all this on floppy disk.) (Caveat: I'm still just a beginner. Read the DX10 books yourself.) 1 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted October 5 Share Posted October 5 For complete information: DX10 Operating System Application Programming Guide, Volume 3 (946250-9703) DX10 Operating System Systems Programming Guide, Volume 5 (946250-9705) All volumes available on Bitsavers See: Volume 3, Section 3: DX10 I/O System 3.5 Logical Unit Numbers and Devices Volume 3, Section 7: Using Supervisor Calls (SVCs) Volume 3, Section 9: Device I/O Supervisor Calls Volume 3, Section 10: File I/O SVCs Volume 5, Section 5: How to Write a Device Service Routine 3 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted October 5 Share Posted October 5 (edited) 55 minutes ago, FarmerPotato said: It has to walk the global linked list, PDTTBL. Remember that PDTTBL is permanent and has all the known devices. Similar to how the p-system does. But the p-system allows for a fixed number of devices (on the 99/4A, due to memory constraints), so it's suffcicient with a normal array. You simply index it with the device number to find pointers for where the code to implement the intrinsics unitclear, unitread, unitwrite and unitbusy are located. On machines with bigger memory the table can be larger than the 32 units available in the 99/4A. Edited October 5 by apersson850 4 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 17 Author Share Posted November 17 On 10/3/2023 at 10:37 PM, Lee Stewart said: In dissecting the various DSRLNK incarnations before the Bagnaresi/Sullivan DSRLNK, I am wondering why all of them, including the E/A version from which they were all derived (as far as I can tell) save the following (labels vary), even though they are not used within the routine or elsewhere (that I can find—maybe someone knows?): SAVCRU DATA 0 CRU Address of the Peripheral SAVENT DATA 0 Entry Address of DSR or Subprogram SAVLEN DATA 0 Device or Subprogram name length SAVPAB DATA 0 Pointer to Device or Subprogram in the PAB SAVVER DATA 0 Version # of DSR Most or all of these persist long enough to be captured after return to the calling routine without the need to save them in the above manner—even in the console DSRLNK, which does not save them elsewhere. The only one that surely does not survive is SAVVER (GPLWS R1)—and I am not sure it is necessary. Perhaps these saved values were intended for debugging. I am even considering keeping the MG DSRLNK and trying to manage reruns of the various DSRs/subprograms in its shadow. The only feature I would like to have that will likely not be possible is starting the DSR search at a particular CRU address and circling around back to it to complete the search. Folks are probably used to managing CRU addresses in hardware to manage search order, but starting the DSR search at any desired CRU address from >1000 to >1F00 and circling back around to the starting address is a nifty feature of the Bagnaresi/Sullivan DSRLNK, which I kind of hate to give up. Just thinking out loud here.... ...lee Getting back to this project after a hiatus cleaning up speech and sound management for the upcoming fbForth 3.0, it looks like GPLWS R1 does, in fact, survive a call to DSRLNK if it is sampled immediately following the return from DSRLNK. So...staying with the MG DSRLNK, I will only be giving up the ability of starting at any desired CRU. As to the term DSR “version” saved as SAVVER, I changed them to “instance” and SAVNST, which clarifies the fact that we are not talking about the DSR version stored at >4001, but rather how many times a particular DSR or subprogram name was found before the one that actually worked. I still do not understand the utility of knowing this value, but I suppose I will keep it because the RS232 cards require it (see @JasonACT’s and my posts below. Here is my current version of the Bagnaresi/Sullivan DSRLNK: DSRLNK_LES_mod_of_Bagnaresi_V3B.a99 ...lee 3 Quote Link to comment Share on other sites More sharing options...
JasonACT Posted November 17 Share Posted November 17 10 hours ago, Lee Stewart said: but rather how many times a particular DSR or subprogram name was found before the one that actually worked. I still do not understand the utility of knowing this value, but I suppose I will keep it. Quote R1(>83E2) contains the number of time a routine with that name was called. Normally it is 1. The card DSR check the DSR name in VDP memory to know if the user is accessing the first card (RS232, RS232/1, RS232/2, PIO or PIO/1) or the second (RS232/3, RS232/4, PIO/2). If the call is meant for the second card, the routine checks the content of R1 and returns with B *R11 if it is 1. This will cause the DSR scanning routine to keep looking for cards with the same DSR name in their ROMs. If the content of R1 matches the card number, the DSR is executed. https://www.unige.ch/medecine/nouspikel/ti99/rs232c.htm#RomDSR 1 1 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted November 18 Share Posted November 18 I'm going to take you back a-ways... Device Service Routine Link * by Texas Instruments * Modified by John Clulow, 1982 bcscat.pdf BCS001.DSK 5 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 18 Author Share Posted November 18 2 hours ago, JasonACT said: https://www.unige.ch/medecine/nouspikel/ti99/rs232c.htm#RomDSR Thanks for that. From the above reference on Thierry’s site: R1(>83E2) contains the number of time a routine with that name was called. Normally it is 1. The card DSR check the DSR name in VDP memory to know if the user is accessing the first card (RS232, RS232/1, RS232/2, PIO or PIO/1) or the second (RS232/3, RS232/4, PIO/2). If the call is meant for the second card, the routine checks the content of R1 and returns with B *R11 if it is 1. This will cause the DSR scanning routine to keep looking for cards with the same DSR name in their ROMs. If the content of R1 matches the card number, the DSR is executed. My focus here has been disk I/O, but, indeed, the above answers the instance question—certainly unnecessary for any disk DSR I know of. I believe the RS232 cards constitute the only case for needing GPLWS R1 preserved. Obviously, calling an RS232 DSR directly without having GPLWS R1 set to 1 or 2 will never work because of the following code from the TI RS232 ROM: A415E LI 6,>0001 pio pio/1 JMP A4168 * ... A4164 LI 6,>0002 pio/2 A4168 SETO 3 R3=pio flag CLR 2 R2=cru base JMP A4190 A416E LI 6,>0001 rs232 rs232/1 JMP A4184 A4174 LI R6,>0001 rs232/2 JMP A418A A417A LI R6,>0002 rs232/4 JMP A418A A4180 LI R6,>0002 rs232/3 A4184 LI R2,>0040 JMP A418E A418A LI R2,>0080 A418E CLR R3 A4190 STWP R4 save workspace (>83E0) MOV R11,@>FF84(R4) ret address in >8364 C R1,R6 <----THIS COMPARISON REQUIRES R1 SET TO.. * ..1 (FIRST CARD) OR 2 (SECOND CARD) ELSE---+ JEQ A419E r1: calls the 1st or 2nd program (card) | B @A4480 ret with error: not found <------------<-----+ A419E * ... A4480 ANDI 12,>FF00 return MOV @>FF84(4),11 ====== SBO 2 handshake out->1 SBZ 1 pio SBZ 7 light off B *11 Definitely keeping management of GPLWS R1 in place. Thanks again. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 26 Author Share Posted November 26 Just a little update: Many of you may well already know that I had wrong the value of the PAB pointer passed to the DSR by DSRLNK. I thought it pointed to the filename that follows the ‘.’ separating the device name from the filename. Wrong! It actually points to the ‘.’—I misread the code. I didn’t figure it out until I got deeper into the TI disk DSR ROM. Here is the updated copy of the Bagnaresi/Sullivan DSRLNK routine: DSRLNK_LES_mod_of_Bagnaresi_V3B.a99 ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted November 26 Share Posted November 26 I have been fighting the virus du jour the last few days so have been mostly horizontal. When I realized that what DSR really wanted was that address of the '.' character I thought that it should be in a field in an extended PAB. That way you eliminate the text searching stuff on file operations after a file was opened. I think the DSR code could factored so that there is an entry for FOPEN and an entry for all the other functions. 2 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 26 Author Share Posted November 26 6 hours ago, TheBF said: I have been fighting the virus du jour the last few days so have been mostly horizontal. I thought you were plagued with a computer virus until I saw “horizontal”. Get well soon (from Platitudes-R-Us)—but, seriously, I hope you mend quickly. 6 hours ago, TheBF said: When I realized that what DSR really wanted was that address of the '.' character I thought that it should be in a field in an extended PAB. That way you eliminate the text searching stuff on file operations after a file was opened. I think the DSR code could factored so that there is an entry for FOPEN and an entry for all the other functions. That is an interesting idea, but I think you would need too much carnal knowledge of the DSRs for that to work across different controllers. You might craft a workable solution for specific controllers, but that seems like a lot of work for little gain. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted November 26 Share Posted November 26 Thanks for the platitudes. Ah. Other controllers. Ok. I have no knowledge of them at all. I guess what I have is probably the safest albeit not the most efficient. 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted Wednesday at 08:38 PM Share Posted Wednesday at 08:38 PM Yes, don't fall in the compatibility trap. It's never a good idea to assume that a DSR has a certain more or less peculiar behavior just because another DSR, trying to accomplish the same thing, does do that peculiar trick. 1 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.