;************************************************
;*      Prog5_4.asm                             *
;*      Practical Character Driver CON3         *
;*      Author: YU.I.Petrenko                   *
;************************************************
.286
code    segment byte
assume          CS:code,DS:code,ES:code,SS:nothing
;====================================================
; CON3 - true character device driver
;====================================================
Con2header:                             ; CON3 device header
;====================================================
Link            DW      -1,-1
Attributes      DW      8013h           ;Bits 15,4,1 and 0 are set
Strategy        DW      Stratgy
Interrupt       DW      Intrpt
DrvName         DB      'CON',5 dup (' ')
;====================================================
Stratgy:                                        ;Strategy Routine
;====================================================
                MOV     WORD PTR CS:[ReqHdr],BX
                MOV     WORD PTR CS:[ReqHdr+2],ES
                RETF
;----------------------------------------------------
ReqHdr          DD       0
;====================================================
Intrpt:                                 ;Interrupt Routine
;====================================================
                PUSHF                   ;Register savings
                PUSHA
                PUSH    DS
                PUSH    ES
;----------------------------------------------------
                CLD
                LES     DI,CS:[ReqHdr]          ;RequESt header in ES:DI
                MOV     BL,BYTE PTR ES:[DI+2]   ;Command code
                XOR     BH,BH                   ;now is
                SHL     BL,1                    ;in AX
                CMP     BL,22                   ;Is command valid?
                JNA     Valid                   ;Yes, valid
                JMP     ErrCom                  ;No, erroneous
Valid:
                JMP     WORD PTR CS:[BX+Comtable]
                                                ;Yes, valid -> execute it
;----------------------------------------------------
ComTable:
;----------------------------------------------------
                DW      Init            ;00h - Init
                DW      OutFrom         ;01h - Illegal Request = Media Check
                DW      OutFrom         ;02h - Illegal Request = Build BPB
                DW      ErrCom          ;03h - Erroneous Command
                DW      Read            ;04h - Read
                DW      NndRead         ;05h - Nondestructive Read
                DW      InpStatus       ;06h - Input Status
                DW      InpFlush        ;07h - Input Flush
                DW      Write           ;08h - Write
                DW      WriteVer        ;09h - Write with Verify
                DW      OutptStatus     ;0AH - Output Status
                DW      OutptFlush      ;0BH - Output Flush

;----------------------------------------------------
MakeIt:
;----------------------------------------------------
                CALL    Beg
                PUSH    CS
                POP     DS
                LES     BX,ReqHdr
                CALL    DWORD PTR[ConStrategy]
                PUSH    CS
                POP     DS
                LES     BX,ReqHdr
                CALL    DWORD PTR[ConInterrupt]
                JMP     done
;----------------------------------------------------
Message1        DB      0Dh,0Ah
                DB      ' Message 1',0dh,0AH,'$'
OldSymbol       DB      0
;----------------------------------------------------
Read:                                           ;Command 04h - Read

;----------------------------------------------------
;JMP MakeIt
                CALL    Beg                     
                LES     BX,CS:ReqHdr            
                MOV     CX,ES:[BX+12h]          
                TEST    CX,CX
                JZ      JmpOut
                LES     DI,DWORD PTR ES:[BX+0Eh]
      ;----------------------------------------------------
Reading:
                PUSH    CX
                CALL    InputChar
                POP     CX
                STOSB
                LOOP    Reading
JmpOut:
                JMP     OutFrom
InputChar:
                MOV     AX,0
                XCHG    AL,OldSymbol
                TEST    AL,AL
                JNZ     Rt                      ;Return
InChr:
                MOV     AH,0
                INT     16h
                TEST    AX,AX
                JZ      InChr ;
                TEST    AL,AL
                JNZ     Rt
                MOV     OldSymbol,AH
Rt:             RET
;----------------------------------------------------
NndRead:                                        ;Command 05h -
                                                ;NondEStructive Read
;----------------------------------------------------
;JMP MakeIt
                CALL    Beg                     ;
RdOld:
                MOV     AL,CS:[OlDSymbol]       ;Read old symbol
                TEST    AL,AL
                JNZ     SblOut                  ;Old symbol in AL
                MOV     AH,1
                INT     16h
                JNZ     Got
                MOV     AH,3
                JMP     Out1
Got:
                TEST    AX,AX                   ;Symbol has been got
                JNZ     SblOut
                MOV     AH,0
                INT     16h
                JMP     RdOld
SblOut:                                         ;Symbol's  out
                LDS     BX,CS:[ReqHdr]
                MOV     [BX+13],AL
                MOV     AH,01h
                JMP     Out1
;----------------------------------------------------
InpStatus:
;----------------------------------------------------
                JMP     MakeIt
;----------------------------------------------------
InpFlush:
;----------------------------------------------------
;JMP MakeIt
                CALL    beg                     ;Before the command
                MOV     CS:[OlDSymbol],0
                XOR     AX,AX
                MOV     ES,AX
                MOV     BYTE PTR ES:[41AH],20h
                MOV     BYTE PTR ES:[41Ch],20h
                JMP     Done
;----------------------------------------------------
Write:
;----------------------------------------------------
                JMP     MakeIt
;----------------------------------------------------
WriteVer:
;----------------------------------------------------
                JMP     MakeIt
;----------------------------------------------------
OutptStatus:
;----------------------------------------------------
                JMP     MakeIt
;----------------------------------------------------
OutptFlush:
;----------------------------------------------------
                JMP     MakeIt
;====================================================
; Various Exits
;====================================================
ErrCom:                                 ;Erroneous command
                MOV     AX,8103h                ;AL=03h - Unknown
                                                ;command Error value
                                                ;AH=81h - errOR+done bits
                JMP     outfrom
;----------------------------------------------------
ErrUnnwn:                                       ;Unknown error
                MOV     AX,8100h                ;AH=81h - error+done bits
                JMP     Outfrom
DrvBusy:
                MOV     AX,0300h                ;Driver busy
                JMP     OutFrom
Done:
                MOV     AX,0
OutFrom:
                MOV     AH,1                    ;Bit done
Out1:
                LES     BX,DWORD PTR CS:[ReqHdr]        ;Request header in DS:BX
                MOV     WORD PTR ES:[BX+3],AX   ;Status word now = AX
                POP     ES
                POP     DS
                POPA
                POPF
                RETF                            ;Exit from driver
;====================================================
Message         DB      0dh,0AH
                DB      '  Now CON3 is resident'
                DB      0dh,0AH,'$'
;----------------------------------------------------
DoMessage:
                PUSH    CS
                POP     DS
                MOV     DX,offset Message
                MOV     AH,9
                INT     21h
                RET
Init:
                CALL    DoMessage
                LES     DI,DWORD PTR CS:[ReqHdr]
                                                ;Request header in DS:BX
                MOV     WORD PTR ES:[DI+0Eh],offset Endd
                                                ;End of driver's memory
                MOV     ES:[DI+10h],CS
                JMP     Done
;----------------------------------------------------
ConAdr          DD      0
ConStrategy     DD      0
ConInterrupt    DD      0
;----------------------------------------------------
Beg:
;----------------------------------------------------
;At first this subroutine checks if it is the first
;search. If not, it returns. Else this subroutine
;gets the current driver Header address and extracts
; the driver Name. Later this name is compared
;with its own  name (CON), byte after byte. If name differs,
;it reads addresses of next driver, if it exists, and
;saves them. Then the driver search is repeated.
;When the driver with identical name is found,
;the search is finished.
;----------------------------------------------------
                PUSH    CS
                POP     DS
                TEST    WORD PTR [ConAdr+2],0ffffh
;First search? If first, the word contents 0. If not,
;it contents nonzero address segment.
                JZ      D                       ;Yes
                RET;No,return
D:                                              ;Driver search
                LES     BX,DWORD PTR [Link]
                CMP     BX,0FFFFh               ;Is the driver the last
                                                ;in the System?
                JNZ     DrvrSearch
                RET                             ;Yes, return
DrvrSearch:                                     ;No, try to meet the twin
                MOV     CX,8
                MOV     DI,offset DrvName
                MOV     SI,0Ah
L:                                              ;Comparing of driver
                                                ;name with the own
                MOV     AL,ES:[BX+SI]
                CMP     BYTE PTR [DI],AL        ;Identical?
                JZ Go                           ;One character more
                                                ;coincides yet
                JMP     Next                    ;No, that one differs
Go:                                             ;Hope exists yet,
                                                ;let's continue
                INC     DI
                INC     SI
                LOOP    L                       ;This driver is identical
                MOV     WORD PTR [ConAdr],BX
                MOV     WORD PTR [ConAdr+2],ES  ;[ConAdr+2] is a flag!
                MOV     AX,WORD PTR ES:[BX+6]   ;Storing the twin driver's
                                                      ;personal data
                                                      ;for the future using
                MOV     WORD PTR[ConStrategy],AX
                MOV     WORD PTR[ConStrategy+2],ES
                MOV     AX,WORD PTR ES:[BX+8]
                MOV     WORD PTR[ConInterrupt+2],ES
                MOV     WORD PTR[ConInterrupt],AX
                RET
Next:                                           ;Try if is the driver last
                CMP     ES:[BX],0ffffh
                JZ      Last                    ;Yes, last driver, return
                LES     BX,DWORD PTR ES:[BX]   ;Not last, try to find the twin
                                                ;Now the ES:BX points to the
                                                ;next Driver Header
                JMP     DrvrSearch
Last:
                RET
;----------------------------------------------------
Endd:
;----------------------------------------------------
                NOP                             ;These NOP's marks
                NOP                             ;the end of the
CODE ENDS                                       ;program (in debugger)
END
;====================================================
;****************************************************
