PAGE 60,132 TITLE "NETIO" -- NETWORK I/O DRIVER CSEG SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CSEG,SS:STACK ;------------------------------------------------; ; DRIVER HEADER ; ;------------------------------------------------; DD -1 ; Ptr to next device driver DW 1100000000000000B ; Attribute byte, char dev. DW OFFSET STRATEGY ; OFFSET to STRATEGY routine DW OFFSET IRPT ; OFFSET to INTERRUPT routine DB 'NETIO ' ; Character device name RH_PTR LABEL DWORD ; Storage of PTR to request header RH_PTRO DW 0 ; OFFSET (filled by strat. rout) RH_PTRS DW 0 ; SEGMENT " ;------------------------------------------------; ; REQUEST HEADER, COMMON PORTION ; ;------------------------------------------------; RH EQU DS:[BX] RHC STRUC RHC_LEN DB ? ; Length of request header + data DB ? ; unit code (Ignored) RHC_CMD DB ? ; Command code RHC_STA DW ? ; Status word DQ ? ; Reserved for DOS RHC ENDS ;------------------------------------------------; ; REQUEST HEADER FOR INIT COMMAND ; ;------------------------------------------------; RH0 STRUC DB (TYPE RHC) DUP (?) ;Common portion RH0_NUM DB ? ; Number of units (Ignored) RH0_ENDO DW ? ; OFFSET of ending address of res. code RH0_ENDS DW ? ; SEGMENT of ending address of res. code RH0_BPB DD ? ; Address of BPB (Ignored) RH0_DRIV DB ? ; Drive code (Ignored) RH0 ENDS ;------------------------------------------------; ; REQUEST HEADER FOR I/O ; ;------------------------------------------------; RH1 STRUC DB (TYPE RHC) DUP (?) ;Common portion DB ? ; Media descriptor byte (Ignored) RH1_BUFO DW ? ; OFFSET to buffer address RH1_BUFS DW ? ; SEGMENT of buffer address RH1_CNT DB ? ; Bytes transferred count RH1 ENDS RH1_BUF EQU DWORD PTR RH1_BUFO ; OFFSET/SEG of buffer ;------------------------------------------------; ; REQUEST HEADER FOR INPUT NO WAIT ; ;------------------------------------------------; RH2 STRUC DB (TYPE RHC) DUP (?) ;Common portion RH2_DATA DB ? ; Data from driver service routine RH2 ENDS ;------------------------------------------------; ; FLAGS FOR REQUEST HEADER STATUS WORD ; ;------------------------------------------------; STAT_DONE EQU 01H ; Done flag STAT_CMDERR EQU 8003H ; Command error flag STAT_BUSY EQU 0200H ; Busy -- I/O in progress CTRL_C EQU 03H BELL EQU 07H CR EQU 0DH LF EQU 0AH ;------------------------------------------------; ; NETWORK CONTROL BLOCK ( GENERIC ) ; ;------------------------------------------------; NCB EQU $ NCB_COMMAND DB 00H ; NCB Command field NCB_RETCODE DB 00H ; NCB Return code NCB_LSN DB 00H ; NCB Local session number NCB_NUM DB 00H ; NCB Number of your name NCB_BUFFER@ DW OFFSET CHAR ; NCB Ptr to message buffer DW CSEG NCB_LENGTH DW 0001H ; NCB Message buffer length NCB_CALLNAME DB 'HUNTER THOMPSON '; NCB Name on remote adapter NCB_NAME DB 'RAOUL DUKE '; NCB Name on local adapter NCB_RTO DB 00H ; NCB Receive timeout NCB_STO DB 00H ; NCB Send timeout NCB_POST@ DD 00000000H ; NCB Ptr to POST routine NCB_LANA_NUM DB 00H ; NCB Adapter number (00H = 1st Adapter) NCB_CMD_CPLT DB 00H ; NCB Command status NCB_RESERVE DB 14 DUP (0) ; Reserved CHAR DB 0 ; Our 1 Character 'BUFFER' INSTALLED DB 0 ; Network session started flag BUFF DB 16 DUP(0) BUFF_STAT DB 0 NEXT_TO_READ DW 0 NEXT_TO_ADD DW 0 BUFF_PTR DW 0 OUT_BUFF DB 64 DUP(0) ;------------------------------------------------; ; STRATEGY ROUTINE, STORES HEADER ADDRESS ; ;------------------------------------------------; STRATEGY PROC FAR MOV CS:RH_PTRS,ES MOV CS:RH_PTRO,BX RET STRATEGY ENDP ;------------------------------------------------; ; JUMP TABLE FOR PROCESSING DRIVER COMMANDS; ;------------------------------------------------; CMD_TABLE LABEL WORD DW OFFSET INIT ; 0 - Initialization DW OFFSET MEDIA_CHECK ; 1 - Media Check DW OFFSET BLD_BPB ; 2 - Build BPB DW OFFSET INPUT_IOCTL ; 3 - IOCTL Input DW OFFSET INPUT ; 4 - Input DW OFFSET INPUT_NDINW ; 5 - Non-Destr. Input DW OFFSET INPUT_STATUS ; 6 - Input Status DW OFFSET INPUT_FLUSH ; 7 - Input Flush DW OFFSET OUTPUT ; 8 - Output DW OFFSET OUTPUT_VER ; 9 - Output w/Verify DW OFFSET OUTPUT_STATUS ;10 - Output Status DW OFFSET OUTPUT_FLUSH ;11 - Output Flush DW OFFSET OUTPUT_IOCTL ;12 - IOCTL Output DW OFFSET DEVICE_OPEN ;13 - Device OPEN DW OFFSET DEVICE_CLOSE ;14 - Device CLOSE MAX_CMD EQU ($ - CMD_TABLE)/2 ;Highest Valid Command DW OFFSET REMOVABLE_MED ;15 - Removeable Media ;------------------------------------------------; ; DEVICE INTERRUPT ENTRY POINT ; ;------------------------------------------------; IRPT PROC FAR PUSH DS ; Save registers PUSH ES PUSH AX PUSH BX PUSH CX PUSH DX PUSH DI PUSH SI CLD ; All moves forward LDS BX,CS:RH_PTR ; Get req header address MOV AL,RH.RHC_CMD ; Command code from request header CBW CMP AL,MAX_CMD ; Valid command? JA IRPT_CMD_HIGH ; Jump to error routine MOV DI,OFFSET IRPT_CMD_EXIT ; Return addr from cmd proc. PUSH DI ; Save it ADD AX,AX ; Double command for jump table MOV DI,AX ; Move into index register XOR AX,AX JMP CS:CMD_TABLE[DI] ; Go to proper processing rout. IRPT_CMD_ERROR: ; Called for unsupported commands MEDIA_CHECK: BLD_BPB: DEVICE_OPEN: DEVICE_CLOSE: REMOVABLE_MED: POP AX ; POP Off return address IRPT_CMD_HIGH: MOV AX,STAT_CMDERR ; Set Command error flag in status IRPT_CMD_EXIT: LDS BX,CS:RH_PTR ; Restore DS:BX as req head. ptr OR AH,STAT_DONE ; Set DONE flag MOV RH.RHC_STA,AX ; Store STATUS in header POP SI ; Restore Registers POP DI POP DX POP CX POP BX POP AX POP ES POP DS RET IRPT ENDP ;------------------------------------------------; ; COMMAND HANDLER ROUTINES ; ;------------------------------------------------; INPUT PROC PUSH ES PUSH BX ; Store OFFSET of header CMP INSTALLED,00H ; Is NET session started? JNE INPUT0 CALL INSTALL INPUT0: CMP BUFF_STAT,0 JE INPUT0 MOV DI,NEXT_TO_READ MOV AL,BUFF[DI] INC DI CMP DI,0FH JLE INPUT1 XOR DI,DI INPUT1: MOV NEXT_TO_READ,DI DEC BUFF_STAT POP BX POP ES MOV DI,RH.RH1_BUFO MOV ES,RH.RH1_BUFS MOV ES:[DI],AL MOV RH.RH1_CNT,01H XOR AX,AX RET INPUT ENDP INPUT_STATUS PROC CMP BUFF_STAT,0H JE BUFF_EMPTY XOR AX,AX RET BUFF_EMPTY: MOV AX,STAT_BUSY RET INPUT_STATUS ENDP INPUT_NDINW PROC PUSH ES PUSH BX ; Store OFFSET of header CMP INSTALLED,00H ; Is NET session started? JNE NDINW0 CALL INSTALL NDINW0: POP BX POP ES CMP BUFF_PTR,00H ; Is output buffer empty? JE NDINW1 MOV DI,BUFF_PTR ; if not, empty it... MOV NCB_BUFFER@+2,CS MOV NCB_BUFFER@,OFFSET OUT_BUFF MOV NCB_COMMAND,014H MOV NCB_LENGTH,DI MOV BX,CS MOV ES,BX MOV BX,OFFSET NCB INT 5CH MOV BUFF_PTR,00H ; now buffer is empty CMP NCB_RETCODE,00H JE NDINW1 JMP IRPT_CMD_ERROR ; if anything went wrong, abort NDINW1: MOV DI,NEXT_TO_READ ; get next char in buffer MOV AL,BUFF[DI] MOV RH.RH2_DATA,AL ; return it via req header CMP BUFF_STAT,0H JE NWBUFF_EMPTY NDINW_LOOP: CMP AL,CTRL_C ; scan active buffer for ^C JNE NDINW2 MOV BUFF_PTR,04H ; got one! MOV OUT_BUFF,'^' ; print ^C on remote MOV OUT_BUFF+1,'C' MOV OUT_BUFF+2,CR MOV OUT_BUFF+3,LF CALL INPUT_FLUSH ; flush input buffer INT 23H ; tell DOS NDINW2: INC DI ; get next char in active buffer CMP DI,0FH ; check buffer rollover JLE NDINW3 XOR DI,DI NDINW3: CMP DI,NEXT_TO_ADD ; check end of active buffer JE NDINW_EXIT MOV AL,BUFF[DI] JMP NDINW_LOOP NDINW_EXIT: XOR AX,AX ; clear error flag for return RET NWBUFF_EMPTY: MOV AX,STAT_BUSY ; set buffer empty flag RET INPUT_NDINW ENDP INPUT_FLUSH PROC MOV BUFF_STAT,0H ; 0 chars in buffer MOV NEXT_TO_READ,0H ; offset for reading buffer MOV NEXT_TO_ADD,0H ; offset for adding to buffer RET INPUT_FLUSH ENDP INPUT_IOCTL PROC RET INPUT_IOCTL ENDP OUTPUT_IOCTL PROC RET OUTPUT_IOCTL ENDP OUTPUT PROC OUTPUT_VER: MOV RH.RH1_CNT,01H MOV DI,RH.RH1_BUFO ; Load DTA OFFSET MOV ES,RH.RH1_BUFS ; Load DTA SEGMENT CMP INSTALLED,0H ; Is NETWORK session on? JNE NET_OUT CALL INSTALL ; If not, wait for CALL NET_OUT: MOV AL,ES:[DI] ; Get char to send MOV DI,BUFF_PTR ; Put into output buffer MOV OUT_BUFF[DI],AL INC DI ; Update output buffer pointer CMP DI,040H ; check for output buffer full JNE OUT_EXIT MOV DI,00H ; it's full, send it on its way MOV NCB_BUFFER@+2,CS MOV NCB_BUFFER@,OFFSET OUT_BUFF MOV NCB_LENGTH,040H MOV NCB_COMMAND,014H MOV AX,CS MOV ES,AX MOV BX,OFFSET NCB INT 5CH CMP NCB_RETCODE,00H JE OUT_EXIT JMP IRPT_CMD_ERROR OUT_EXIT: XOR AX,AX ; Clear error code MOV BUFF_PTR,DI RET OUTPUT ENDP OUTPUT_STATUS PROC RET OUTPUT_STATUS ENDP OUTPUT_FLUSH PROC RET OUTPUT_FLUSH ENDP ;------------------------------------------------; ; DO A NETBIOS "ADD NAME" ; ;------------------------------------------------; INSTALL PROC MOV BX,CS MOV ES,BX MOV NCB_COMMAND,030H ; ADDNAME Command code MOV BX,OFFSET NCB ; ES:BX points to NCB INT 5CH ; NETWORK function call ;------------------------------------------------; ; DO A NETBIOS "LISTEN" ; ;------------------------------------------------; LISTEN: MOV NCB_COMMAND,011H ; LISTEN Command code INT 5CH ; NETWORK function call MOV INSTALLED,01H POST_REC: MOV NCB_COMMAND,095H MOV NCB_POST@,OFFSET POST MOV NCB_POST@+2,CS INT 5CH JMP INST_EXIT INST_ERR_EXIT: POP AX INST_EXIT: RET INSTALL ENDP INIT PROC MOV RH.RH0_ENDS,CS MOV RH.RH0_ENDO,OFFSET HELLO RET INIT ENDP POST PROC FAR PUSH DI PUSH AX PUSH BX PUSH CX PUSH DX CLI CMP CHAR,0FFH ; Is session over? JNE NORMAL_POST MOV CHAR,00H ; Yes, so reset everything MOV NCB_COMMAND,012H MOV BX,CS MOV ES,BX MOV BX,OFFSET NCB INT 5CH ; RESET adapter MOV INSTALLED,00H POP DX POP CX POP BX POP AX POP DI IRET NORMAL_POST: CMP BUFF_STAT,0FH ; Is input buffer full? JL XFER STI JMP XEXIT XFER: MOV DL,CHAR ; transfer char to input buffer MOV DI,NEXT_TO_ADD MOV BUFF[DI],DL INC DI ; update next_to_add pointer CMP DI,0FH ; check for buffer rollover JLE XFER2 XOR DI,DI XFER2: MOV NEXT_TO_ADD,DI ; restore pointer INC BUFF_STAT ; increment # of chars in buffer MOV AX,CS ; POST another receive... MOV ES,AX MOV BX,OFFSET NCB MOV NCB_BUFFER@,OFFSET CHAR MOV NCB_BUFFER@+2,AX MOV NCB_COMMAND,095H MOV NCB_POST@,OFFSET POST MOV NCB_POST@+2,AX STI INT 5CH XEXIT: POP DX POP CX POP BX POP AX POP DI IRET POST ENDP HELLO EQU $ CSEG ENDS STACK SEGMENT PARA STACK 'STACK' DB 64 DUP('STACK ') STACK ENDS END ; Eric W. DeSilva Nov 1985 .