PAGE 75,128 TITLE CCBBS - Multi-tasking RBBS program PAGE INCLUDE CCBBS.MAC INCLUDE CCBBS.DEF ;----------------------------------------------- ;STACK SEGMENT ;----------------------------------------------- ASTACK SEGMENT PARA STACK 'STACK' DB 64 DUP ('STACK0 ') DB 64 DUP ('STACK1 ') DB 64 DUP ('STACK2 ') DB 64 DUP ('STACK3 ') DB 32 DUP ('STACK ') ASTACK ENDS ZZZZZZ SEGMENT PARA PUBLIC 'FREE' DB 'START OF AVAILABLE STORAGE' ZZZZZZ ENDS ;---------------------------------------------- ;PROGRAM PREFIX SEGMENT ;---------------------------------------------- PREFIX SEGMENT AT 0 ORG 80H CMDCNT DB ? ;LENGTH OF PASSED PARMS CMDLIN DB 80 DUP (?) ;COMMAND LINE BUFFER PREFIX ENDS ;----------------------------------------------- ;SYSTEM DATA SEGMENT ;----------------------------------------------- SYSDATA SEGMENT PARA PUBLIC 'DATA' PUBLIC ABORT,DEBUGF,TESTF,RETCODE PUBLIC MSSGH,CALLRN,SHUTFLG,LOGCNT PUBLIC USERH PUBLIC TIMEOUT,USRLOCK,KBDTSK PUBLIC MSSGN,USERN,USRCNT,CDTASK PUBLIC CDIP,CDSP,FDIRH,FDIRN,DIRCNT PUBLIC MSGSEG,SCRIPT1,DOSUSER public msgfiln,msgtfin,opnmsg ;------------------------------------------------ ;CONTROL VARIABLES ;------------------------------------------------ SYSZERO DW 0A5A5H ;DEBUG TARGET STKSIZ DW 512 ;TASK STACK SIZE APREFIX DW 0 ;PREFIX SEGMENT ADDRESS ADYNDAT DW 0 ;DYNAMIC DATA SEGMENT ADDRESS LDYNDAT DW 0 ;DYNAMIC DATA SEGMENT LENGTH INTMAP DW 3FH ;INTERRUPTS TO INSTALL ; 01 BRKADR ; 02 CERROR ; 04 TIMER ; 08 C1INT ; 10 C2INT ; 20 DOSINT ; 40 SYSWTP OLDBRKO DW 0 ;KEYBOARD BREAK OFFSET OLDBRKS DW 0 ;KEYBOARD BREAK SEGMENT OCOM1 DW 0 ;COM1 VECTOR OFFSET SCOM1 DW 0 ;COM1 VECTOR SEGMENT OCOM2 DW 0 ;COM2 VECTOR OFFSET SCOM2 DW 0 ;COM2 VECTOR SEGMENT IRQSTAT DB 0 ;INTERRUPT STATUS ABORT DB 0 ;ABORT FLAG SHUTFLG DB 0 ;NORMAL SHUTDOWN REQUEST LOGCNT DB 0 ;# OF LOGGED ON USERS DISPCX DW 0 ;DISPATCHER SAVE AREA DISPSI DW 0 ;DISPATCHER SAVE AREA CDTASK DW 0 ;CURRENTLY DISPATCHED TASK CDIP DW 0 ;LAST DISPATCH ADDRESS CDSP DW 0 ;LAST DISPATCH STACK POINTER KBDTSK DW 0 ;TASK WITH KEYBOARD FOCUS MSGSEG DW 0 ;MESSAGE SEGMENT ADDRESS DEBUGF DB 0 ;DEBUG FLAG TESTF DB 0 ;TEST FLAG STFLAG DB 0 ;SINGLE THREAD FLAG RETCODE DB 12 ;RETURN CODE TIMEOUT DW 5*60*18 ;KEYBOARD TIME OUT VALUE USRCNT DW 0 ;NUMBER OF LOGGED ON USERS USRLOCK DW 0 ;USER FILE LOCK WORD DW 0 DIRCNT DW 0 ;NUMBER OF DIRECTORY USERS DOSUSER DW 0 ;CURRENT USER OF INT 21H DW 0 ;WAIT LIST POINTER ;------------------------------------------------- ;INTERRUPT JUMP TABLE ;------------------------------------------------- INTTBL DW MODM ;MODEM STATUS DW TXRE ;TRANSMITTER EMPTY DW RXDA ;DATA AVAILABLE DW LINE ;LINE ERROR ;INTERRUPT STATISTICS ;MULTITASKING INTERRUPTS SYSWCNT DW 0 ;SYSTEM WAIT CALLS SYSPCNT DW 0 ;SYSTEM POST CALLS ;------------------------------------------------ ;SYSTEM FILE NAMES & HANDLES ;------------------------------------------------ USERN DB 'CCUSERS.FIL',0 ;USERS FILE USERH DW 0 ;FILE HANDLE MSSGN DB 'CCEMAIL.FIL',0 ;MESSAGE FILE MSSGH DW 0 ;FILE HANDLE CALLRN DB 'CCLOG.FIL',0 ;CALLERS LOG FILE FDIRN DB 'CCFILDIR.FIL',0 ;DOWNLOAD FILE DIRECTORY FDIRH DW 0 ;FILE HANDLE MSGFILN DB 'CCMSG.DAT',0 ;SYSTEM MESSAGE FILE MSGTFIN DB 'CCMSGTST.DAT',0 ;SYSTEM TEST MESSAGE FILE MSGFILH DW 0 ;SYSTEM MESSAGE FILE HANDLE SCRIPT1 DB 'CCQUEST.SPT',0 ;QUESTIONAIRE SCRIPT FILE SYSDATA ENDS ;------------------------------------------------ ;EXTRA SEGMENT FOR ACCESS TO SYSTEM VARIABLES ;----------------------------------------------- SYSTEM SEGMENT AT 40H ORG 10H EQUIP_FLAG DW ? ;INSTALLED HARDWARE SYSTEM ENDS ;----------------------------------------------- ;CODE SEGMENT ;----------------------------------------------- CSEG SEGMENT PARA PUBLIC 'CODE' EXTRN GETBUF:NEAR,FREBUF:NEAR,WRLF:NEAR,GPARM:NEAR EXTRN FILESS:NEAR,TERMNL:NEAR,TEIN00:NEAR EXTRN QUICKS:NEAR,READTM:NEAR,SCANM:NEAR,ENTCMT:NEAR EXTRN ENTMSG:NEAR,DELETE:NEAR,BUILDM:NEAR EXTRN READM:NEAR,QMSGNO:NEAR,GETSBF:NEAR EXTRN CKMSG:NEAR,DSPCLR:NEAR,FNKEY:NEAR,WMSGNO:NEAR EXTRN SETGID:NEAR,PACKMF:NEAR,RENMSG:NEAR,RECMSG:NEAR EXTRN LISTMH:NEAR,ARCLOG:NEAR,USERFM:NEAR EXTRN PACKUF:NEAR,ERROR:NEAR,READCM:NEAR EXTRN CLEAR:NEAR,SAVALL:NEAR,RSTALL:NEAR,BINASP:NEAR EXTRN BINASC:NEAR,ASCBIN:NEAR,WRMSG:NEAR EXTRN QUERY:NEAR,WPOST:NEAR,RPOST:NEAR,TPOST:NEAR EXTRN LININ:NEAR,CHTIOA:NEAR,DQCMD:NEAR,DQTIOA:NEAR EXTRN EXPBUF:NEAR,CONR:NEAR,CONW:NEAR,CONWRT:NEAR EXTRN CONT:NEAR,TIMRTN:NEAR,TIMASC:NEAR,TIMHM:NEAR EXTRN DATASC:NEAR,DOSTIM:NEAR,DOSDAT:NEAR,ELPASC:NEAR EXTRN ELPTIM:NEAR,TIMON:NEAR,CLRIBF:NEAR,PSMENU:NEAR EXTRN PUMENU:NEAR,TXPRT:NEAR,TSYSOP:NEAR,TAYSOP:NEAR EXTRN PTIME:NEAR,PUSTAT:NEAR,LOGDSK:NEAR,MOVSTR:NEAR EXTRN MOVSTL:NEAR,APPBYT:NEAR,CMPSTA:NEAR,CMPSTR:NEAR EXTRN FDIRFM:NEAR,ST2400:NEAR,WTBUFE:NEAR EXTRN ILINEB:NEAR,FRELBF:NEAR,BLANKF:NEAR,HAYIND:NEAR EXTRN PADB:NEAR,STRIP:NEAR,CKPTM:NEAR EXTRN SENDHF:NEAR,PKINX:NEAR EXTRN SENDF:NEAR,UNCMD:NEAR,FRETIO:NEAR EXTRN STM7B:NEAR,STM8B:NEAR,RESMDM:NEAR,ENMDI:NEAR EXTRN ST300:NEAR,ST1200:NEAR,PURG1:NEAR,HAYIN:NEAR EXTRN FEOF:NEAR,ANINIT:NEAR,FRECMD:NEAR EXTRN WELCO:NEAR,SIGNON:NEAR,PDIRFI:NEAR,STSYSP:NEAR EXTRN ENTREP:NEAR,ENTAPP:NEAR,LOCKWT:NEAR,UNLOCK:NEAR EXTRN EDITFM:NEAR,DISPFM:NEAR,ENTFM:NEAR,RUNFIL:NEAR EXTRN LOSTC:NEAR,INITLN:NEAR,MMENU1:NEAR,CHKPRM:NEAR EXTRN MOVMSG:NEAR,MXOPEN:NEAR,ERRINT:NEAR PUBLIC WAITRT,YIELD OLDTIMO DW 0 ;OLD TIMER OFFSET OLDTIMS DW 0 ;OLD TIMER SEGMENT OLDDOSO DW 0 ;OLD INT 21H OFFSET OLDDOSS DW 0 ;OLD INT 21H SEGMENT OLDWTPO DW 0 ;OLD INT 15H OFFSET OLDWTPS DW 0 ;OLD INT 15H SEGMENT START PROC FAR ASSUME CS:CSEG,DS:SYSDATA,ES:PREFIX,SS:ASTACK ;------------------------------------------------------ ;ESTABLISH LINKAGE FROM DOS ;------------------------------------------------------ ENTER: MOV AX,SYSDATA MOV DS,AX MOV APREFIX,ES ;SAVE PREFIX SEGMENT CLD ;AUTO INCREMENT STRINGS ;------------------------------------------------------- ;FREE STORAGE BEYOND OUR LOAD MODULE ;------------------------------------------------------- MOV BX,ZZZZZZ ;TOP OF MEMORY MOV AX,ES ;PSP SUB BX,AX ;TOTAL SIZE MOV AH,4AH ;SETBLOCK INT 21H ;DOS FUNCTION ;------------------------------------------------------- ;BUILD DYNAMIC DATA SEGMENT ;------------------------------------------------------- MOV AH,48H ;ALLOCATE MEMORY MOV BX,1000H ;TRY FOR FULL SEGMENT INT 21H ;DOS FUNCTION JNC ENTR10 ;GOT IT MOV AH,48H ;ALLOCATE MEMORY INT 21H ;TAKE WHAT WE CAN GET ENTR10: MOV ADYNDAT,AX ;DYNAMIC SEGMENT ADDRESS MOV LDYNDAT,BX ;SEGMENT SIZE - PARAGRAPHS MOV BX,DS ;SYSTEM DATA SEGMENT MOV DS,AX ;ADDRESS DYNAMIC SEGMENT MOV ES,BX ;ADDRESS SYSTEM DATA SEGMENT ASSUME DS:NOTHING,ES:SYSDATA MOV WORD PTR DS:[DYNZERO],0A5A5H ;SET GUARD BAND MOV WORD PTR DS:[MAXTSK],8 ;MAX TASK COUNT MOV WORD PTR DS:[TSKCNT],4 ;ACTIVE TASK COUNT MOV WORD PTR DS:[FAQEHD],BFRHD ;FREE QUEUE POINTER MOV WORD PTR DS:[BFRHD],0 ;ONLY QUEUE ELEMENT MOV AX,LDYNDAT ;DATA SEGMENT LENGTH MOV CX,4 ;SHIFT COUNT SHL AX,CL ;CONVERT TO BYTES MOV CX,AX ;ENDING ADDRESS+1 SUB CX,QEDTA ;BUFFER HEADER SIZE MOV WORD PTR DS:[BFRTL],CX ;END OF CONTROLLED AREA SUB AX,BFRHD ;FREE SPACE IN BYTES MOV WORD PTR DS:[BFRHD+2],AX ;SET FREE SPACE MOV DI,OFFSET TSKCNT+2 ;TCB LIST MOV CX,DS:TSKCNT ;TASK COUNT ENTR20: MOV AX,TCBSIZ ;TCB SIZE CALL GETSBF ;GET SYSTEM BUFFER MOV WORD PTR [DI],SI ;SAVE IN LIST ADD DI,2 ;NEXT TCB POINTER LOOP ENTR20 ;ALLOCATE REST OF TCBS ;------------------------------------------------------- ;INITIALIZE USER TASKS ;------------------------------------------------------- INIT: MOV CX,DS:TSKCNT ;NUMBER OF TASKS XOR DX,DX ;TASK/LINE NUMBER MOV DI,OFFSET TSKCNT+2 ;1ST TASK INIT10: MOV AX,OFFSET INITLN ;LINE INIT ROUTINE MOV BX,WORD PTR [DI] ;GET TCB ADDRESS MOV WORD PTR [BX+USRFL],0FFH ;MAKE NON-DISPATCHABLE MOV WORD PTR [BX+USRIP],AX ;POINT TO INIT RTN MOV WORD PTR [BX+USRBX],BX ;INIT TASK POINTER MOV WORD PTR [BX+USRDS],DS MOV WORD PTR [BX+USRES],ES MOV WORD PTR [BX+USRSS],SS MOV AX,DX ;TASK NUMBER INC AX ;FOR TOP OF STACK PUSH DX MUL STKSIZ ;STACK SIZE POP DX MOV WORD PTR [BX+USRSP],AX ;STACK ADDRESS MOV WORD PTR [BX+USRLN],DX ;TASK NUMBER MOV WORD PTR [BX+USRSF],0F202H ;FLAGS MOV WORD PTR [BX+CBWINLR],184FH ;WINDOW SIZE MOV WORD PTR [BX+CBCOLOR],7 ;WINDOW ATTRIBUTE MOV WORD PTR [BX+CBSTATE],OFFSET ANINIT CMP DX,1 ;COMMUNICATIONS TASK? JZ INIT20 ;YES CMP DX,2 ;COMMUNICATIONS TASK? JZ INIT20 ;YES ;CONSOLE TASK MOV AX,80 ;INPUT BUFFER SIZE CALL BLDBUF ;BUILD INPUT BUFFER MOV WORD PTR [BX+CBIBA],SI ;SAVE IN TCB MOV AX,80 ;INTER-TASK BUFFER SIZE CALL BLDBUF ;BUILD INTER-TASK BUFFER MOV WORD PTR [BX+CBTBA],SI ;SAVE IN TCB CMP DX,0 ;PRIMARY CONSOLE TASK? JNZ INIT15 ;NO MOV KBDTSK,BX ;SET KEYBOARD FOCUS CALL ERRINT ;INITIALIZE ERROR HANDLER INIT15: CMP DX,3 ;ALTERNATE CONSOLE TASK? JNZ INIT18 ;NO OR WORD PTR [BX+CBMDM],MDMTEST ;SET TEST FLAG INIT18: JMP INIT40 ;COMMUNICATIONS TASK INIT20: MOV AX,640 ;INPUT BUFFER SIZE CALL BLDBUF ;BUILD INPUT BUFFER MOV WORD PTR [BX+CBIBA],SI ;SAVE IN TCB MOV AX,512 ;OUTPUT BUFFER SIZE CALL BLDBUF ;BUILD OUTPUT BUFFER MOV WORD PTR [BX+CBOBA],SI ;SAVE IN TCB MOV AX,80 ;INTER-TASK BUFFER SIZE CALL BLDBUF ;BUILD INTER-TASK BUFFER MOV WORD PTR [BX+CBTBA],SI ;SAVE IN TCB INIT30: CMP STFLAG,0 ;SINGLE THREAD TESTING? JZ INIT40 ;NO PROBLEM OR WORD PTR [BX+CBMDM],MDMOS ;OUT OF SERVICE INIT40: ADD DI,2 ;NEXT TASK POINTER INC DX ;NEXT TASK NUMBER DEC CX ;REMAINING TASKS JCXZ INIT50 ;DONE JMP INIT10 ;USE CONSOLE TASK FOR INITIALIZATION INIT50: MOV BX,DS:TSKCNT+2 ;CONSOLE TASK MOV CDTASK,BX ;MARK AS CURRENT MOV WORD PTR [BX+USRFL],0 ;SET DISPATCHABLE CALL SAVALL ;INIT REG SAVE AREA ;CHECK PASSED PARAMETERS CALL ILINEB ;GET LINE BUFFER XOR CX,CX ;CLEAR COUNT REGISTER MOV AX,APREFIX ;PREFIX SEGMENT PUSH ES ;SYSTEM DATA MOV ES,AX ;PREFIX SEGMENT ASSUME ES:PREFIX MOV CL,CMDCNT ;PARAMETER COUNT CMP CL,0 ;ANYTHING? JNZ GETPRM ;YES - GO HANDLE POP ES ;RESTORE SYSDATA JMP ENDPRM ;NO PARAMETER LIST GETPRM: MOV WORD PTR [SI-2],CX ;SET LENGTH XOR DI,DI ;CLEAR INDEX REGISTER MOVPRM: MOV AL,ES:CMDLIN[DI] ;GET NEXT CHAR MOV BYTE PTR [SI],AL ;MOVE TO STRING INC SI INC DI LOOP MOVPRM ;MOVE ALL OF STRING POP ES ;RESTORE SYSDATA ASSUME ES:SYSDATA CALL CHKPRM ;HANDLE PASSED PARMS ENDPRM:MOV AX,SYSDATA MOV DS,AX ASSUME DS:SYSDATA,ES:NOTHING ;CLOSE FILE HANDLES 1-4 MOV CX,4 ;NUMBER OF HANDLES TO CLOSE CSLFH: MOV AH,3EH ;CLOSE FILE HANDLE MOV BX,CX ;NEXT HANDLE TO CLOSE INT 21H ;DOS REQUEST LOOP CSLFH ;NEXT HANDLE ;SET UP CTL-BRK VECTOR MOV AX,351BH ;GET VECTOR 1B INT 21H ;DOS FUNCTION CALL MOV OLDBRKO,BX ;SAVE OFFSET MOV OLDBRKS,ES ;SAVE SEGMENT TEST INTMAP,1 ;INSTALL THIS VECTOR? JZ SETCE ;NO MOV AX,251BH ;SET VECTOR 1B MOV DX,OFFSET BRKADR PUSH DS PUSH CS POP DS INT 21H POP DS ;SET UP CRITICAL ERROR HANDLER VECTOR SETCE: TEST INTMAP,2 ;INSTALL THIS VECTOR? JZ SETST ;NO MOV AX,2524H ;SET VECTOR 24 MOV DX,OFFSET CERROR PUSH DS PUSH CS POP DS INT 21H POP DS ;SET UP TIMER VECTOR SETST: MOV AX,351CH ;GET TIMER VECTOR INT 21H ;DOS FUNCTION CALL MOV OLDTIMO,BX ;SAVE OFFSET MOV OLDTIMS,ES ;SAVE SEGMENT TEST INTMAP,4 ;INSTALL THIS VECTOR? JZ SETCM ;NO MOV AX,251CH ;SET TIMER VECTOR MOV DX,OFFSET TIMER ;NEW TIMER OFFSET PUSH DS PUSH CS POP DS INT 21H ;DOS FUNCTION CALL POP DS ;SET UP COMMUNICATION INTERRUPT VECTORS SETCM: MOV AX,SYSDATA MOV ES,AX ASSUME DS:NOTHING,ES:SYSDATA MOV DS,ADYNDAT MOV DI,DS:TSKCNT+6 ;USER2 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;OK TO USE? JNZ ICOM10 ;NO MOV WORD PTR [DI+CBMBA],2F8H ;MODEM BASE ADDRESS MOV DX,2FCH ;MODEM CONTROL REG COM2 IN AL,DX ;READ REG TEST AL,0E0H ;SHOULD ALL BE ZEROS JZ ICOM20 ;OK OR WORD PTR [DI+CBMDM],MDMOS ;OUT OF SERVICE JMP ICOM10 ;CHECK COM1 ICOM20: MOV AX,350BH ;COM2 VECTOR PUSH ES INT 21H ;DOS FUNCTION CALL MOV AX,ES POP ES MOV OCOM2,BX ;SAVE OFFSET MOV SCOM2,AX ;SAVE SEGMENT TEST INTMAP,10H ;INSTALL THIS VECTOR? JZ ICOM10 ;NO MOV AX,250BH ;COM2 VECTOR MOV DX,OFFSET C2INT PUSH DS PUSH CS POP DS INT 21H ;DOS REQUEST POP DS ICOM10: MOV DI,DS:TSKCNT+4 ;USER1 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;OK TO USE? JNZ ICOM30 ;NO MOV WORD PTR [DI+CBMBA],3F8H ;MODEM BASE ADDRESS MOV DX,3FCH ;MODEM CONTROL REG COM1 IN AL,DX ;READ REGISTER TEST AL,0E0H ;SHOULD BE ZEROS JZ ICOM15 ;NO PROBLEM OR WORD PTR [DI+CBMDM],MDMOS ;OUT OF SERVICE JMP ICOM30 ;SKIP COM1 ICOM15: MOV AX,350CH ;COM1 VECTOR PUSH ES INT 21H ;DOS FUNCTION CALL MOV AX,ES POP ES MOV OCOM1,BX ;SAVE OFFSET MOV SCOM1,AX ;SAVE SEGMENT TEST INTMAP,8 ;INSTALL THIS VECTOR? JZ SETSS ;NO MOV AX,250CH ;COM1 VECTOR MOV DX,OFFSET C1INT PUSH DS PUSH CS POP DS INT 21H ;DOS REQUEST POP DS ;ENABLE IRQ3 & IRQ4 ICOM30: CLI ;NO INTERRUPTS NOW IN AL,21H ;INTERRUPT CONTROLLER MOV AH,AL MOV DI,DS:TSKCNT+4 ;USER1 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;EXIST? JNZ ICOM34 ;NO AND AL,0EFH ;ENABLE IRQ4 MOV DX,3F8H ;COM1 BASE ADDRESS CALL ENMDI ;ENABLE FOR INTERRUPTS ICOM34: MOV DI,DS:TSKCNT+6 ;USER2 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;EXIST? JNZ ICOM36 ;NO AND AL,0F7H ;ENABLE IRQ3 MOV DX,2F8H ;COM2 BASE ADDRESS CALL ENMDI ;ENABLE FOR INTERRUPTS ICOM36: OUT 21H,AL ;UPDATE CONTROLLER AND AH,18H ;ISOLATE IRQ STATUS MOV IRQSTAT,AH ;SAVE PREVIOUS STATUS ;ENABLE MODEM INTERRUPTS STI ;INTERRRUPTS OK ;SET UP DOS INTERRUPT VECTORS SETSS: MOV AX,3515H ;GET SYSTEM SERVICES VECTOR PUSH ES INT 21H ;DOS FUNCTION CALL MOV AX,ES POP ES MOV OLDWTPO,BX ;SAVE OFFSET MOV OLDWTPS,ES ;SAVE SEGMENT TEST INTMAP,40H ;INSTALL THIS VECTOR? JZ SETDR ;NO MOV AX,2515H ;SET SYSTEM SERVICES VECTOR MOV DX,OFFSET SYSWTP ;SYSTEM WAIT/POST HANDLER PUSH DS PUSH CS POP DS INT 21H ;DOS FUNCTION CALL POP DS MOV AX,3521H ;GET INT 21 VECTOR INT 21H ;DOS FUNCTION CALL MOV OLDDOSO,BX ;SAVE OFFSET MOV OLDDOSS,ES ;SAVE SEGMENT SETDR: TEST INTMAP,20H ;INSTALL THIS VECTOR? JZ SETXX ;NO ;---------------------------------------------------------------- ;REMOVE UNTIL CAN TEST BETTER ; MOV AX,0 ;ABSOLUTE SEGMENT ; PUSH ES ; MOV ES,AX ;POINT TO LOW MEMORY ; CLI ; MOV DI,84H ;DOS INT VECTOR ; MOV AX,OFFSET DOSINT ;NEW INT 21 OFFSET ; STOSW ; MOV AX,CS ; STOSW ; POP ES ;---------------------------------------------------------------- SETXX: STI GOMAIN: JMP MAIN ;MAIN ROUTINE ;RETURN TO DOS EXIT: CLI ;NO INTERRUPTS FOR A WHILE MOV DOSUSER,0 ;CLEAR LOCK WORD TEST INTMAP,20H ;DEINSTALL THIS VECTOR? JZ DESS00 ;NO ;------------------------------------------------------------------ ;TEMPORARILY REMOVED TO SEE IF IT IS CAUSING TASK STALLS ; MOV AX,2521H ;SET VECTOR 21H ; MOV DX,OLDDOSO ;ORIGINAL OFFSET ; PUSH DS ; MOV DS,OLDDOSS ;ORIGINAL SEGMENT ; INT 21H ;DOS FUNCTION CALL ; POP DS ;------------------------------------------------------------------ DESS00: TEST INTMAP,40H ;DEINSTALL THIS VECTOR? JZ DESS01 ;NO MOV AX,2515H ;SET VECTOR 15H MOV DX,OLDWTPO ;ORIGINAL OFFSET PUSH DS MOV DS,OLDWTPS ;ORIGINAL SEGMENT INT 21H ;DOS FUNCTION CALL POP DS DESS01: TEST INTMAP,1 ;DEINSTALL THIS VECTOR? JZ DESS02 ;NO MOV AX,251BH ;SET VECTOR 1B MOV DX,OLDBRKO ;OFFSET PUSH DS MOV DS,OLDBRKS ;SEGMENT INT 21H ;DOS FUNCTION CALL POP DS ;RESTORE OLD IRQ3 & IRQ4 STATUS AND DISABLE COM PORT IN AL,21H ;INTERRUPT CONTROLLER OR AL,IRQSTAT ;RESTORE PREVIOUS STATUS OUT 21H,AL ;UPDATE CONTROLLER MOV DI,DS:TSKCNT+6 ;USER2 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;EXIST? JNZ EXIT10 ;NO MOV DX,2FCH ;MODEM CONTROL REG - COM2 XOR AL,AL ;CLEAR ALL BITS OUT DX,AL ;UPDATE CONTROLLER DESS02: TEST INTMAP,10H ;DEINSTALL THIS VECTOR? JZ DESS03 ;NO MOV AX,250BH ;SET IRQ3 VECTOR MOV DX,OCOM2 ;OLD COM2 OFFSET PUSH DS MOV DS,SCOM2 ;OLD COM2 SEGMENT INT 21H ;DOS FUNCTION CALL POP DS EXIT10: MOV DI,DS:TSKCNT+4 ;USER1 TCB TEST WORD PTR [DI+CBMDM],MDMOS ;EXIST? JNZ EXIT20 ;NO MOV DX,3FCH ;MODEM CONTROL REGISTER XOR AL,AL ;CLEAR ALL BITS OUT DX,AL ;UPDATE CONTROLLER DESS03: TEST INTMAP,8 ;DEINSTALL THIS VECTOR? JZ DESS04 ;NO MOV AX,250CH ;SET IRQ4 VECTOR MOV DX,OCOM1 ;OLD COM1 OFFSET PUSH DS MOV DS,SCOM1 ;OLD COM1 SEGMENT INT 21H ;DOS FUNCTION CALL POP DS EXIT20: STI ;INTERRUPTS OK AGAIN ;RESTORE TIMER VECTOR DESS04: TEST INTMAP,4 ;DEINSTALL THIS VECTOR? JZ DESS05 ;NO MOV AX,251CH ;SET TIMER VECTOR MOV DX,OLDTIMO ;OFFSET PUSH DS MOV DS,OLDTIMS ;SEGMENT INT 21H ;DOS FUNCTION CALL POP DS ;FREE MESSAGE AREA DESS05: MOV AH,49H ;FREE ALLOCATED MEMORY PUSH ES MOV ES,MSGSEG ;ADDRESS OF BLOCK INT 21H ;DOS REQUEST POP ES MOV AL,RETCODE ;GET RETURN CODE MOV AH,4CH ;EXIT REQUEST INT 21H ;DOS FUNCTION CALL START ENDP MAIN PROC MOV AX,SYSDATA ;SYSTEM DATA SEGMENT MOV ES,AX ASSUME ES:SYSDATA MOV BX,CDTASK ;RESTORE TASK POINTER MOV WORD PTR [BX+USRIP],OFFSET OPEN ;OPEN SYSTEM FILES MOV WORD PTR [BX+USRFL],0 ;MAKE DISPATCHABLE CALL SAVALL ;INITIALIZE REG SAVE AREA ;------------------------------------------------------- ;TASK DISPATCHER ;------------------------------------------------------- DISP: MOV CX,DS:TSKCNT ;NUMBER OF TASKS TO SCAN MOV SI,OFFSET TSKCNT+2 ;1ST TASK DISP01: TEST ABORT,80H ;ABORT REQUESTED? JZ DISP02 ;NO - CONTINUE JMP EXIT ;RETURN TO DOS DISP02: MOV DISPCX,CX ;SAVE COUNT MOV DISPSI,SI ;SAVE TABLE LOC MOV BX,WORD PTR [SI] ;TASK CONTROL BLOCK CMP WORD PTR [BX+USRFL],0 ;DISPATCHABLE? JNZ DISP03 ;NO ;DISPATCH TASK MOV CDTASK,BX ;CURRENTLY DISPATCHED TASK CLI ;NO INTERRUPTS MOV AX,WORD PTR [BX+USRIP] ;INSTRUCTION POINTER MOV CDIP,AX MOV CX,WORD PTR [BX+USRCX] MOV DX,WORD PTR [BX+USRDX] MOV SI,WORD PTR [BX+USRSI] MOV DI,WORD PTR [BX+USRDI] MOV BP,WORD PTR [BX+USRBP] MOV ES,WORD PTR [BX+USRES] MOV SS,WORD PTR [BX+USRSS] MOV SP,WORD PTR [BX+USRSP] MOV CDSP,SP MOV AX,WORD PTR [BX+USRSF] ;STATUS FLAGS PUSH AX MOV AX,WORD PTR [BX+USRAX] MOV BX,WORD PTR [BX+USRBX] POPF ;FLAGS JMP CDIP ;DISPATCH TASK DISP03: MOV SI,DISPSI ;TABLE INDEX ADD SI,2 ;NEXT TASK MOV CX,DISPCX ;TASK COUNT LOOP DISP01 ;CHECK NEXT TASK JMP DISP ;CHECK 1ST TASK WAITRT: PUSH BX MOV BX,CDTASK ;TCB MOV WORD PTR [BX+USRFL],-1 ;MAKE NON-DISPATCHABLE POP BX YIELD: PUSHF ;SAVE FLAGS CLI ;NO INTERRUPTS PUSH BX MOV BX,CDTASK ;CURRENT TCB MOV WORD PTR [BX+USRAX],AX MOV WORD PTR [BX+USRCX],CX MOV WORD PTR [BX+USRDX],DX MOV WORD PTR [BX+USRSI],SI MOV WORD PTR [BX+USRDI],DI MOV WORD PTR [BX+USRBP],BP MOV WORD PTR [BX+USRES],ES MOV WORD PTR [BX+USRSS],SS POP AX ;ORIGINAL BX MOV WORD PTR [BX+USRBX],AX POP AX ;STATUS FLAGS MOV WORD PTR [BX+USRSF],AX POP AX ;RESUME ADDRESS MOV WORD PTR [BX+USRIP],AX MOV WORD PTR [BX+USRSP],SP STI ;ALLOW INTERRUPTS JMP DISP03 ;RETURN TO DISPATCHER ;----------------------------------------------------------------- ;ACQUIRE AND INITIALIZE COMMUNICATIONS BUFFER ; INPUT AX=REQUESTED LENGTH ; RETURNS SI -> BUFFER HEADER ; LOCAL BP-2 BUFFER DATA LENGTH ;----------------------------------------------------------------- BLDBUF: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;SET LOCAL FRAME SUB SP,2 ;ALLOCATE LOCAL STORAGE MOV [BP-2],AX ;REQUEST LENGTH ADD AX,BFRSD ;ALLOW FOR HEADER CALL GETBUF ;ALLOCATE BUFFER MOV AX,SI ;BUFFER HEADER ADD AX,BFRSD ;START OF DATA MOV [SI+BFRST],AX ;START OF BUFFER MOV [SI+BFRNI],AX ;NEXT INPUT MOV [SI+BFRNO],AX ;NEXT OUTPUT ADD AX,[BP-2] ;DATA LENGTH MOV [SI+BFRND],AX ;END OF DATA MOV AX,[BP-2] ;DATA LENGTH MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET MAIN ENDP ;------------------------------------------------ ;DISPATCHER INTERRUPT TASK ;------------------------------------------------ SYSWTP PROC FAR CMP AH,90H ;WAIT? JZ SYSW10 ;YES CMP AH,91H ;POST? JZ SYSW50 ;YES SYSW00: JMP DWORD PTR OLDWTPO ;PASS TO NEXT USER SYSW10: PUSH ES PUSH AX MOV AX,SYSDATA MOV ES,AX INC SYSWCNT ;COUNT INTERRUPT POP AX POP ES CLC STI ;ALLOW INTERRUPTS RET 2 ;DISCARD OLD FLAGS SYSW50: PUSH ES PUSH AX MOV AX,SYSDATA MOV ES,AX INC SYSPCNT ;COUNT INTERRUPT SYSW90: POP AX POP ES IRET SYSWTP ENDP ;------------------------------------------------ ;CONTROL BREAK INTERRUPT ROUTINE ;------------------------------------------------ BRKADR PROC PUSH ES PUSH AX MOV AX,SYSDATA MOV ES,AX TEST ABORT,80H ;CRITICAL? JNZ BRKA10 ;YES - LEAVE ALONE ADD ABORT,3*32 ;ONE ABORT REQUEST BRKA10: POP AX POP ES IRET BRKADR ENDP ;--------------------------------------------------------------------- ;CRITICAL ERROR HANDLER ;--------------------------------------------------------------------- CERROR PROC PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME OR WORD PTR [BP+1EH],1 ;SET CARRY IN CALLER'S REGS PUSH DI ;ERROR CODE AND DI,0FFH ;CLEAR MSB OR DI,8000H ;SHOW CRITICAL ERROR MOV [BP+8],DI ;SET AX TO ERROR CODE POP DI XOR AL,AL ;IGNORE ERROR POP BP ;RESTORE CALLER'S FRAME IRET ;RETURN TO DOS CERROR ENDP ;--------------------------------------------------------------------- ;TIMER INTERRUPT TASK ;--------------------------------------------------------------------- TIMER PROC PUSH DS ;SAVE DATA SEGMENT PUSH ES PUSH CX PUSH BX PUSH AX ;SAVE WORK REG PUSH SI ;SAVE INDEX REG PUSH DI ;SAVE INDEX REG MOV AX,SYSDATA MOV ES,AX ASSUME DS:NOTHING,ES:SYSDATA MOV DS,ADYNDAT ;ADDRESS DATA SEGMENT MOV AH,1 ;TEST KEYBOARD FLAG INT 16H ;BIOS CALL JNZ TIMEA0 ;READ KEYBOARD JMP TIME10 ;NO KEY PRESSED TIMEA0: XOR AH,AH ;READ KEYBOARD INT 16H ;BIOS CALL ;CHECK FOR KEYBOARD TASK SWITCH CMP AX,7800H ;ALT-1? JB TIMEC0 ;NO - BELOW RANGE CMP AX,8200H ;ABOVE RANGE? JNB TIMEC0 ;YES XCHG AH,AL SUB AL,77H ;CONVERT TO TASK NUMBER CMP AL,10 ;TASK 0? JNZ TIMEB0 ;NO PROBLEM XOR AX,AX ;10 -> 0 TIMEB0: CMP AX,DS:TSKCNT ;VALID RANGE? JNB TIMEBJ ;NO SHL AX,1 ;CONVERT TO OFFSET MOV DI,OFFSET TSKCNT+2 ;COM0 TCB ADD DI,AX ;INDEX INTO TABLE MOV DI,[DI] ;GET TCB ADDRESS TEST WORD PTR [DI+CBFLG],SFWINV ;VALID WINDOW? JZ TIMEB1 ;NO PUSH BX PUSH DX MOV DX,[DI+CBCURSE] ;CURSOR POSITION XOR BX,BX ;PAGE 0 MOV AH,2 ;SET CURSOR INT 10H ;VIDEO BIOS POP DX POP BX MOV KBDTSK,DI ;SET FOCUS TIMEBJ: JMP TIME10 ;DELETE KEYSTROKE TIMEB1: TEST WORD PTR [DI+CBMDM],MDMKBD ;LOCAL CONNECTION? JZ TIMEBJ MOV KBDTSK,DI ;SET FOCUS MOV AX,0DH ;CR TO FORCE WINDOW TIMEC0: MOV DI,KBDTSK ;CURRENT KEYBOARD TASK TEST WORD PTR [DI+CBFLG],SFDFC ;FLOW CONTROL ON? JNZ TIMEK0 ;NO - STORE IN BUFFER CMP AL,13H ;X-OFF? JNZ TIMED0 ;NO PROBLEM OR WORD PTR [DI+CBFLG],SFHLT ;SUSPEND OUTPUT JMP SHORT TIME10 ;DON'T POST TASK TIMED0: TEST WORD PTR [DI+CBFLG],SFHLT ;CURRENTLY SUSPENDED? JZ TIMEK0 ;NO - GO STORE TEST WORD PTR [DI+CBFLG],SFLCP ;LOST CARRIER PENDING? JZ TIMEE0 ;NO - CLEAR SUSPEND FLAG JMP TIME10 ;IGNORE INPUT TIMEE0: AND WORD PTR [DI+CBFLG],NOT SFHLT ;CLEAR SUSPEND FLAG MOV BX,WORD PTR [DI+CBWWT] ;TASK WAITING FOR WRITE JMP SHORT TIME00 ;SEE IF TASK NEEDS POSTING TIMEK0: MOV SI,WORD PTR [DI+CBIBA] ;INPUT BUFFER CONTROL BLOCK PUSH DI MOV DI,WORD PTR [SI+BFRNO] ;NEXT BUFFER POS CMP AX,4B00H ;LEFT ARROW? JNZ TIMEN0 ;NO MOV AL,8 ;CONVERT TO BACKSPACE TIMEN0: MOV [DI],AL ;STORE IN BUFFER INC DI CMP DI,WORD PTR [SI+BFRND] ;END OF BUFFER? JB TIMEL0 ;NO PROBLEM MOV DI,WORD PTR [SI+BFRST] ;START OF BUFFER TIMEL0: OR AL,AL ;EXTENDED CHAR? JNZ TIMEL1 ;NO PROBLEM OR AX,AX ;EXTENDED NULL? JZ TIMEL1 ;YES - STORE ONLY ONE BYTE MOV AL,AH ;SCAN CODE JMP TIMEN0 ;STORE IN BUFFER TIMEL1: MOV WORD PTR [SI+BFRNO],DI ;UPDATE POINTER POP DI TEST WORD PTR [DI+CBFLG],SFLEC ;ECHO ON? JZ TIMEQ0 ;NO TIMEP0: CALL CONWRT ;ECHO TO CONSOLE CMP AL,13 ;? JNZ TIMEQ0 ;NO MOV AL,10 ; JMP TIMEP0 ;ECHO TIMEQ0: MOV BX,WORD PTR [DI+CBWRD] ;TASK WAITING FOR READ TIME00: OR BX,BX ;ANY? JZ TIME10 ;NO MOV WORD PTR [BX+USRFL],0 ;POST TASK TIME10: CMP ABORT,0 ;ABORT REQEST? JZ TIME20 ;NO TEST ABORT,80H ;CRITICAL? JNZ TIME20 ;YES SUB ABORT,3 ;ERODE REQUEST ;--------------------------------------------------------------------- ;Check for tasks which have timed out or lost carrier ;--------------------------------------------------------------------- TIME20: MOV DI,OFFSET TSKCNT+2 ;CONSOLE TASK ADDRESS MOV CX,DS:TSKCNT ;ACTIVE TASKS TIME30: MOV BX,[DI] ;CURRENT TASK TEST WORD PTR [BX+CBFLG],SFSESS ;EXPECTING CARRIER? JZ TIME35 ;NO TEST BYTE PTR [BX+CBMSR],MSRCD ;HAVE CARRIER? JNZ TIME35 ;YES TEST WORD PTR [BX+CBFLG],SFLCP ;LOST CARRIER PENDING? JNZ TIME35 ;YES - LET IT BE MOV WORD PTR [BX+CBRTC],18 ;ABOUT ONE SECOND OR WORD PTR [BX+CBFLG],SFLCP+SFHLT ;HALT TRANSMISSION TIME35: DEC WORD PTR [BX+CBRTC] ;TIME-OUT COUNT JNZ TIMERX ;NO TIME-OUT OR WORD PTR [BX+CBFLG],SFTO ;MARK TIME-OUT MOV WORD PTR [BX+USRFL],0 ;POST TASK TEST WORD PTR [BX+CBFLG],SFLCP ;LOST CARRIER PENDING? JZ TIMERX ;NO TIME40: AND WORD PTR [BX+CBFLG],NOT (SFHLT+SFLCP) ;CLEAR SUSPEND AND PENDING FLAGS OR WORD PTR [BX+CBFLG],SFLC ;SET LOST CARRIER AND WORD PTR [BX+CBFLG],NOT SFSESS ;SESSION OFF LINE MOV WORD PTR [BX+USRFL],0 ;POST TASK TIMERX: ADD DI,2 ;NEXT TASK LOOP TIME30 POP DI POP SI POP AX POP BX POP CX POP ES POP DS JMP DWORD PTR OLDTIMO ;NEXT ON TIMER CHAIN TIMER ENDP ;----------------------------------------------- ;COMMUNICATIONS INTERRUPT TASKS ;----------------------------------------------- COMINT PROC C1INT: PUSH DS PUSH ES PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI MOV AX,SYSDATA MOV ES,AX ASSUME DS:NOTHING,ES:SYSDATA MOV DS,ADYNDAT MOV DI,DS:TSKCNT+4 ;COM1 TCB JMP COMI10 ;ENTER COMMON CODE C2INT: PUSH DS PUSH ES PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI MOV AX,SYSDATA MOV ES,AX MOV DS,ADYNDAT MOV DI,DS:TSKCNT+6 ;COM2 TCB COMI10: MOV DX,WORD PTR [DI+CBMBA] ;BASE ADDRESS ADD DX,2 ;INTERRUPT ID REG IN AL,DX ;GET INTERRUPT ID TEST AL,1 ;THIS CONTROLLER? JZ COMI30 ;YES JMP COMINX ;EXIT COMI30: AND AL,6 ;ISOLATE ID BITS JUST IN CASE CBW MOV BX,AX ;FOR INDEX REGISTER INC WORD PTR INTCT00[DI] ;COUNT INTERRUPT JMP INTTBL[BX] ;HANDLE INTERRUPT COMINX: MOV AL,20H ;GENERAL INTERRUPT ACK OUT 20H,AL POP DI POP SI POP DX POP CX POP BX POP AX POP ES POP DS IRET LINE: ADD DX,3 ;LINE STATUS REG IN AL,DX ;GET STATUS MOV BYTE PTR [DI+CBLSR],AL ;POST STATUS INC WORD PTR INTCT40[DI] ;COUNT INTERRUPT TEST AL,2 ;OVERRUN? JZ LINE10 ;NO INC WORD PTR INTCT41[DI] LINE10: TEST AL,4 ;PARITY? JZ LINE20 ;NO INC WORD PTR INTCT42[DI] LINE20: TEST AL,8 ;FRAMING? JZ LINE30 ;NO INC WORD PTR INTCT43[DI] LINE30: TEST AL,16 ;BREAK? JZ LINEX ;NO INC WORD PTR INTCT44[DI] LINEX: JMP COMI10 ;EXIT ;TRANSMITTER HOLDING REGISTER EMPTY TXRE: INC WORD PTR INTCT20[DI] ;COUNT INTERRUPT TXRE00: MOV DX,WORD PTR [DI+CBMBA] ;TRANSMITTER HOLDING REG ADD DX,5 ;LINE STATUS REG PUSH AX IN AL,DX ;GET STATUS TEST AL,20H ;TRANSMITTER AVAILABLE? POP AX JZ TXREX ;NO - EXIT W/O POSTING TEST BYTE PTR [DI+CBMSR],MSRCTS ;CTS? JZ TXREX ;NO - EXIT W/O POSTING TEST WORD PTR [DI+CBFLG],SFHLT ;SUSPEND XMISSION? JNZ TXREX ;YES - EXIT MOV SI,WORD PTR [DI+CBOBA] ;OUTPUT BUFFER CTL BLOCK MOV BX,WORD PTR [SI+BFRNI] ;NEXT CHAR TO SEND CMP BX,WORD PTR [SI+BFRNO] ;EMPTY? JZ TXREX ;YES - EXIT W/O POSTING MOV AL,BYTE PTR [BX] ;CHARACTER TO SEND INC BX ;NEXT POS CMP BX,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ TXRE10 ;NO PROBLEM MOV BX,WORD PTR [SI+BFRST] ;START OF BUFFER TXRE10: MOV WORD PTR [SI+BFRNI],BX ;NEXT CHAR TO SEND MOV DX,WORD PTR [DI+CBMBA] ;TRANSMITTER HOLDING REG OUT DX,AL ;WRITE TO LINE TXRE80: MOV BX,WORD PTR [DI+CBWWT] ;WAITING TASK TXRE90: OR BX,BX ;ANY? JZ TXRE98 ;NO MOV WORD PTR [BX+USRFL],0 ;POST TASK TXRE98: JMP TXRE00 ;CHECK TRANSMIT REG TXREX: JMP COMI10 ;CHARACTER AVAILABLE INTERRUPT RXDA: SUB DX,2 ;RECEIVER BUFFER REGISTER IN AL,DX ;GET CHAR TEST WORD PTR [DI+CBFLG],SFDFC ;FLOW CONTROL ON? JNZ RXDA07 ;NO CMP AL,13H ;X-OFF? JNZ RXDA03 ;NO OR WORD PTR [DI+CBFLG],SFHLT ;HALT TRANSMISSION JMP COMI10 ;EXIT RXDA03: TEST WORD PTR [DI+CBFLG],SFHLT ;TRANSMIT OFF? JZ RXDA07 ;NO AND WORD PTR [DI+CBFLG],NOT SFHLT ;CLEAR HALT FLAG JMP TXRE00 ;RESUME TRANSMISSION RXDA07: MOV SI,WORD PTR [DI+CBIBA] ;INPUT BUFFER CONTROL BLOCK PUSH DI MOV DI,WORD PTR [SI+BFRNO] ;NEXT POS IN BUFFER MOV [DI],AL INC DI CMP DI,WORD PTR [SI+BFRND] ;END OF BUFFER? JB RXDA10 ;NO PROBLEM MOV DI,WORD PTR [SI+BFRST] ;START OF BUFFER RXDA10: MOV WORD PTR [SI+BFRNO],DI POP DI ;HANDLE LOCAL ECHO IF ON TEST WORD PTR [DI+CBFLG],SFLEC ;LOCAL ECHO ON? JZ RXDA20 ;NO RXDA12: MOV SI,WORD PTR [DI+CBOBA] ;OUTPUT BUFFER CONTROL BLOCK PUSH DI MOV DI,WORD PTR [SI+BFRNO] ;NEXT OUTPUT POSITION MOV [DI],AL ;STORE IN BUFFER INC DI MOV CX,DI ;NEXT OUTPUT POSITION POP DI CMP CX,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ RXDA14 ;NO PROBLEM MOV CX,WORD PTR [SI+BFRST] ;START OF BUFFER RXDA14: CMP CX,WORD PTR [SI+BFRNI] ;BUFFER FULL? JZ RXDA16 ;YES - DON'T OVERRUN MOV WORD PTR [SI+BFRNO],CX ;UPDATE OUTPUT POINTER RXDA16: CMP AL,13 ;CARRIAGE RETURN? JNZ RXDA20 ;NO MOV AL,10 ;LINE FEED JMP RXDA12 ;ADD TO BUFFER RXDA20: MOV BX,WORD PTR [DI+CBWRD] ;TASK WAITING FOR READ OR BX,BX ;ANYTHING? JNZ RXDA30 ;YES - GO POST MOV BX,WORD PTR [DI+CBWIT] ;TASK WAITING FOR RING RXDA30: INC WORD PTR INTCT30[DI] ;COUNT INTERRUPT JMP TXRE90 ;POST TASK MODM: ADD DX,4 ;MODEM STATUS REGISTER INC WORD PTR INTCT10[DI] ;COUNT INTERRUPT IN AL,DX ;GET STATUS MOV BYTE PTR [DI+CBMSR],AL ;POST STATUS TEST AL,44H ;RING INDICATOR + TERI JZ MODM20 ;NO MOV BX,WORD PTR [DI+CBWIT] ;TASK WAITING FOR RING INC WORD PTR INTCT13[DI] ;COUNT RING INTERRUPT JMP TXRE90 ;POST TASK MODM20: TEST AL,8 ;CARRIER CHANGE? JNZ MODM23 ;YES TEST AL,2 ;DSR CHANGE? JZ MODM21 ;NO INC WORD PTR INTCT12[DI] ;COUNT DSR INTERRUPT JMP COMI10 ;EXIT MODM21: TEST AL,1 ;CTS CHANGE? JZ MODM90 ;NO INC WORD PTR INTCT11[DI] ;COUNT CTS INTERRUPT TEST AL,MSRCTS ;NOW ON? JNZ MDM21A ;YES JMP COMI10 ;EXIT MDM21A: JMP TXRE00 ;RESUME TRANSMISSION MODM23: INC WORD PTR INTCT14[DI] ;COUNT CD INTERRUPT AND AL,MSRCD ;CARRIER ON? JZ MODM25 ;NO - GO HANDLE TEST WORD PTR [DI+CBFLG],SFLCP ;LOST CARRIER PENDING? JZ MODM24 ;NO - GO UPDATE STATUS MOV CX,WORD PTR [DI+CBRTV] ;TIME OUT VALUE MOV WORD PTR [DI+CBRTC],CX ;TIME OUT COUNT MODM24: AND WORD PTR [DI+CBFLG],NOT (SFLC+SFLCP) ;CLEAR LOST CARRIER FLAGS OR WORD PTR [DI+CBFLG],SFSESS ;SHOW TASK IN SESSION JMP SHORT MODM90 ;EXIT MODM25: TEST WORD PTR [DI+CBFLG],SFDCD ;CHECKING DISABLED? JZ MODM27 ;DON'T POST LOST CARRIER YET OR WORD PTR [DI+CBFLG],SFLC ;SHOW LOST CARRIER JMP SHORT MODM90 MODM27: MOV WORD PTR [DI+CBRTC],18 ;ABOUT ONE SECOND OR WORD PTR [DI+CBFLG],SFLCP+SFHLT ;HALT TRANSMISSION MODM90: JMP COMI10 COMINT ENDP ;----------------------------------------------------------- ;DOS REQUEST INTERRUPT HANDLER ;----------------------------------------------------------- DOSINT PROC PUSHF ;FOR IRET FROM DOS PUSH DS PUSH ES PUSH SI MOV SI,SYSDATA MOV ES,SI ;SET SYSTEM DATA SEGMENT MOV DS,ADYNDAT ;SET DYNAMIC DATA SEGMENT MOV SI,DOSUSER ;LOCK WORD CMP SI,CDTASK ;RECURSIVE DOS CALL? MOV SI,OFFSET DOSUSER ;LOCK WORD JNZ DOSI10 ;NO POP SI POP ES POP DS POPF JMP DWORD PTR OLDDOSO ;LET DOS DO IT DOSI10: CALL LOCKWT ;WAIT FOR RESOURCE POP SI POP ES POP DS CALL DWORD PTR OLDDOSO ;INVOKE DOS PUSH BP MOV BP,SP PUSH SI PUSHF ;RETURNED STATUS POP SI MOV WORD PTR [BP+6],SI ;SET STATUS IN STACK PUSH DS PUSH ES MOV SI,SYSDATA MOV ES,SI ;SYSTEM DS MOV DS,ADYNDAT ;DYNAMIC DS MOV SI,OFFSET DOSUSER ;LOCK WORD CALL UNLOCK ;UNLOCK RESOURCE POP ES POP DS POP SI POP BP IRET DOSINT ENDP ;-------------------------------------------------------- ;INITIAL PROCESSING LOGIC ;-------------------------------------------------------- OPEN_FILES proc ;OPEN SYSTEM FILES OPEN: CALL OPNMSG ;LOAD MESSAGE FILE MOV AX,3D02H ;OPEN REQUEST MOV DX,OFFSET USERN ;USER FILE PUSH DS PUSH ES POP DS INT 21H ;DOS CALL POP DS JNC OPEN01 ;OPEN OK ERR 1 OPEN01: MOV USERH,AX ;FILE HANDLE MOV AX,3D02H ;OPEN REQUEST MOV DX,OFFSET MSSGN ;EMAIL FILE PUSH DS PUSH ES POP DS INT 21H ;DOS CALL POP DS JNC OPEN02 ;OPEN OK ERR 2 OPEN02: MOV MSSGH,AX ;FILE HANDLE MOV AX,3D02H ;OPEN REQUEST MOV DX,OFFSET FDIRN ;DIRECTORY FILE PUSH DS PUSH ES POP DS INT 21H ;DOS CALL POP DS JNC OPEN03 ;OPEN OK ERR 13 ;SHOW DIRECTORY ERROR OPEN03: MOV FDIRH,AX ;FILE HANDLE CALL BUILDM ;BUILD MESSAGE INDEX ARRAYS CALL MXOPEN ;OPEN EMAIL INDEX FILE CMP STFLAG,0 ;SINGLE THREAD TESTING? JNZ LOGRDY ;YES - CONSOLE TASK ONLY ;ALLOW OTHER TASKS TO BE DISPATCHED PUSH BX ;SAVE TCB MOV CX,DS:TSKCNT ;NUMBER OF TASKS MOV SI,OFFSET TSKCNT+2 ;FIRST TASK SDISP: MOV BX,WORD PTR [SI] ;GET TCB ADDRESS MOV WORD PTR [BX+USRFL],0 ;MAKE DISPATCHABLE ADD SI,2 ;NEXT TASK LOOP SDISP POP BX ;LOG READY STATE LOGRDY: CALL ILINEB ;FORMAT BUFFER MOV AX,206 ;READY CALL MOVMSG ;MOVE TO BUFFER CALL LOGDSK ;WAIT FOR LOCAL SIGN-ON JMP INITLN ;LINE INIT ROUTINE ;-------------------------------------------------------------------- ;LOAD SYSTEM MESSAGES ; BP-2 PARAGRAPHS TO ALLOCATE ; BP-4 PARAGRAPHS TO FREE FROM DS ;-------------------------------------------------------------------- opnmsg: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;CREATE LOCAL FRAME SUB SP,4 ;ALLOCATE LOCAL VARIABLES cmp msgseg,0 ;memory allocated? jz opnm10 ;no push es mov es,msgseg ;old message area mov ah,49h ;free memory int 21h ;dos request pop es opnm10: MOV AX,3D00H ;OPEN FOR READ MOV DX,OFFSET MSGFILN ;SYSTEM MESSAGE FILE CMP TESTF,0 ;TEST FLAG ON? JZ OPNM20 ;NO MOV DX,OFFSET MSGTFIN ;USE TEST MESSAGE FILE OPNM20: PUSH DS PUSH ES POP DS INT 21H ;DOS REQUEST POP DS JNC OPNM40 ;OPEN OK OPNM30: ERR 11H ;CAN'T OPEN FILE OPNM40: MOV MSGFILH,AX ;FILE HANDLE push bx MOV BX,AX ;FILE HANDLE MOV AX,4202H ;LSEEK EOF XOR CX,CX MOV DX,CX ;OFFSET INT 21H ;DOS FUNCTION CALL POP BX cmp ax,15 ;minimum file size jb OPNM30 ;invalid add ax,15 ;round up MOV CL,4 ;SHIFT FACTOR SHR AX,CL ;CONVERT TO PARAGRAPHS MOV [BP-2],AX ;REMEMBER REQUEST SIZE OPNM50: PUSH BX MOV BX,[BP-2] ;PARAGRAPHS TO ALLOCATE MOV AH,48H ;ALLOCATE MEMORY INT 21H ;DOS REQUEST JNC OPNM70 ;ALLOCATION OK MOV AX,[BP-2] ;REQUEST SIZE SUB AX,BX ;SHORTAGE POP BX MOV [BP-4],AX ;SAVE MOV CL,4 ;SHIFT FACTOR SHL AX,CL ;CONVERT TO BYTES ;FIND LAST FAQE MOV SI,DS:FAQEHD ;1ST FREE ELEMENT OPNM52: CMP WORD PTR [SI+QENXT],0 ;LAST ELEMENT? JZ OPNM54 ;YES MOV SI,[SI+QENXT] ;NEXT ELEMENT JMP OPNM52 ;CHECK IT ;TAKE SPACE FROM END OPNM54: SUB [SI+QELEN],AX ;REDUCE SPACE JNB OPNM56 ;OK ERR 11H ;NO MEMORY OPNM56: MOV AX,[SI+QELEN] ;NEW LENGTH ADD AX,SI ;END OF DYNAMIC SEGMENT MOV DS:BFRTL,AX ;END OF FREE SPACE ;SHRINK DOS ALLOCATION PUSH BX MOV BX,LDYNDAT ;CURRENT SEGMENT SIZE SUB BX,[BP-4] ;PARAGRAPHS NEEDED MOV LDYNDAT,BX ;NEW SEGMENT SIZE PUSH ES MOV ES,ADYNDAT ;DYNAMIC DATA SEGMENT MOV AH,4AH ;SETBLOCK REQUEST INT 21H ;DOS CALL POP ES POP BX JNB OPNM60 ;OK SO FAR ERR 11H ;SOMETHING WRONG OPNM60: JMP OPNM50 ;TRY ALLOCATION AGAIN OPNM70: POP BX MOV MSGSEG,AX ;SEGMENT ADDRESS FOR MESSAGES MOV AX,4200H ;SEEK TO START OF FILE XOR CX,CX MOV DX,CX ;OFFSET PUSH BX MOV BX,MSGFILH ;MESSAGE FILE HANDLE INT 21H ;DOS REQUEST MOV AH,3FH ;READ FILE MOV CX,-1 ;MAXIMUM LENGTH READ XOR DX,DX ;BUFFER OFFSET PUSH DS MOV DS,MSGSEG ;BUFFER SEGMENT INT 21H ;READ FILE POP DS POP BX JNC OPNM80 ;READ OK ERR 11H ;FILE READ ERROR OPNM80: MOV AH,3EH ;CLOSE FILE PUSH BX MOV BX,MSGFILH ;MESSAGE FILE HANDLE INT 21H ;DOS REQUEST pop bx MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME ret OPEN_FILES endp CSEG ENDS END START