Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cornell!batcomputer!sun.soe.clarkson.edu!dean From: dean@sun.soe.clarkson.edu (Dean Swan) Newsgroups: comp.sys.ibm.pc Subject: Re: Disk I/O in Resident MS-DOS Program Message-ID: <2506@sun.soe.clarkson.edu> Date: 21 Feb 89 00:51:32 GMT References: <1872@holos0.UUCP> Sender: dean@sun.soe.clarkson.edu Lines: 93 From article <1872@holos0.UUCP>, by lbr@holos0.UUCP (Len Reed): > I have an MS-DOS terminate-and-stay resident program that must be able > to open/close/read/write hard disk files. It appears that the "file > handles" move on me. That is, if this routine opens a file, as the > foreground processes spawn and die, I lose my handles since they > really belong to the foreground processes. > > BTW--the application is a communications package that sits in the background > and steals time to transfer/receive files to/from a mainframe. I have written more TSR's that do DOS I/O than I'd like to admit. Anyway, your problem is VERY SIMPLE to solve. Ok, DOS I/O from TSR's lesson #1: 1) When doing DOS I/O from TSR's you have to make sure that your routine didn't get called while the foreground process was doing any I/O of it's own. MS-DOS is not re-entrant, and neither is the BIOS, so you have to hook up to a lot more interrupts than you might think just to be able to safely do DOS I/O. 2) INTERRUPTS TO LINK TO: int 1Ch timer interrupt - use it to activate your program int 13h BIOS disk handler You basically have to link a piece of code in that sets a BIOS_busy flag, then calls the bios function, then clears your flag. This flag is then used by your ISR tied to the timer interrupt to tell if its safe to call the BIOS disk handler. If your flag is set when the timer ISR is called it isn't safe. int 28h This is the DOS special interrupt. It gets called only when nothing else is going on. Whenever an ISR linked to this interrupt is called it is always safe to do DOS I/O (and BIOS I/O too.) int 24h DOS critical error handler - hook up to this so you can process DOS errors. int 1Bh break - so you don't get nuked by break interrupts If you want to do a "Hot Key" thing then you also have to grab int09h. 3) Always check the DOS Busy flag when you enter an ISR that's going to do I/O. Int 21h, funtion 34h returns a far pointer to the busy flag in ES:BX. The flag is a byte value and will be 0 if DOS isn't busy. If this flag is non-zero then just return and wait for the next time you get called. 4) Always reset the 8259, or it will get tempermental and refuse to generate any more interrupts. This is easy. Just do an MOV AL,20h OUT 20h, AL or equivalent code at the beginning of your timer ISR and everything will be ok. 5) If your OPEN a file handle in an ISR, BE SURE TO CLOSE THE HANDLE BEFORE PASSING CONTROL BACK TO THE FOREGROUND PROCESS. Basically, never leave a file open when you leave your ISR. If you were writing to a file and need to add more later, re-open it and append to it, instead of trying to leave it open. If you're reading from a file, just remember the current position in the file, close the file, and exit your ISR. The next time your ISR gets called, simply re-open the file and seek to the position you remembered from last time and pick up where you left off. 6) ONE LAST THING: Keep a busy flag for each of your own ISR's because an interrupt can ocurr while you are servicing one and re-call your ISR. Then check the flag whenever you enter your own ISR's. If its set then do and IRET right away. This prevents recursive ISR calls, which can make a debugger's worst nightmare, not to mention lock up your machine. Well, I guess that's it. I write all my TSR's in Turbo C, and use assembly where appropriate. There's not much point to doing everything in assembly anymore, so why make life difficult. The only thing you lose is that in C, the installation code remains resident, but it's usually only a few hundred bytes, so who cares. I'd be happy to talk with anybody on this subject, as well as any of a million other subjects (which I'll refrain from listing here). Send E-mail or Snail-Mail, or if you really need to, call me at the office. Dean Swan Korex Software Corporation Building 3, Unit 5 Seacomm Plaza PO Box 688 Potsdam, NY 13676 (315) 265-1203 dean@sun.soe.clarkson.edu