home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 884.PRMBIO.98T / COMBIOS.ASM < prev    next >
Assembly Source File  |  1987-01-04  |  30KB  |  889 lines

  1.         PAGE    60,132
  2.         TITLE   COMBIOS - Serial interface for COM1 & COM2
  3.  
  4. ;--------------------------------------------------------------------------;
  5. ;                                                                          ;
  6. ;Interupt driven RS232 serial port routines.                               ;
  7. ; these routines replace the BIOS rs232 calls with a version that has      ;
  8. ; interupt driven character receive, and can thus operate at considerably  ;
  9. ;  higher speeds than the standard bios calls (int 14h).                   ;
  10. ;                                                                          ;
  11. ;--------------------------------------------------------------------------;
  12.  
  13. ;--------------------------------------------------------------------------;
  14. ; Set up the works                                                         ;
  15. ;--------------------------------------------------------------------------;
  16.  
  17. everything SEGMENT PUBLIC
  18.       ASSUME CS: everything           ; These assumptions are for the
  19.       ASSUME DS: everything           ; assembler's benefit.  The code
  20.       ASSUME ES: nothing              ; jerks things around as it pleases
  21.       ASSUME SS: nothing              ;
  22.  
  23. ;--------------------------------------------------------------------------;
  24. ; Program start and buffer declares                                        ;
  25. ;--------------------------------------------------------------------------;
  26.  
  27.           ORG     100H
  28. foo:      JMP     start               ; Entry point
  29.  
  30.           ORG     0                   ; Back up so we can use this all as
  31.                                       ; buffer space
  32.  
  33. ;--------------------------------------------------------------------------;
  34. ; Area where things are declared                                           ;
  35. ;--------------------------------------------------------------------------;
  36.  
  37. buffer_size EQU 1024                  ; Bytes in each buffer
  38. buffer_full EQU  950                  ; Max count before handshaking
  39.  
  40. dummy:                                ; Dummy labels to provide a structure
  41.  
  42. buffer    DB      buffer_size dup(?)  ; Buffer (1 per com card)
  43. buffer_e:                             ; End of buffer
  44. comnumber DB      ?                   ; Comm number - 1
  45. flags     DB      ?                   ; Flag byte
  46. last_rs   DB      ?                   ; Last receive status
  47. hiv       DB      ?              ; Hardware interrupt vector
  48. int_mask  DB      ?              ; Mask for 8259
  49. baseaddr  DW      ?                   ; Base port address
  50. count     DW      ?                   ; # of chars in buffer
  51. buffer_in DW      ?                   ; Buffer in pointer
  52. buffer_out DW     ?                   ; Buffer out pointer
  53. dummy_end:
  54.  
  55.           ORG     dummy               ; Back up over this
  56. ;--------------------------------------------------------------------------;
  57. ; These are the things to work with                                        ;
  58. ;--------------------------------------------------------------------------;
  59.  
  60.  
  61.           DB      buffer_size dup(?)  ; Buffer (1 per com card)
  62.           DB      0                   ; Com number
  63.           DB      0                   ; Flags
  64.           DB      0                   ; Last receive status
  65.           DB      0CH              ; Hardware interrupt vector
  66.           DB      0EFH              ; Mask
  67.           DW      03F8H                  ; Base port address
  68.           DW      0                   ; # of chars in buffer
  69.           DW      ?                   ; Buffer in pointer
  70.           DW      ?                   ; Buffer out pointer
  71.  
  72.           DB      buffer_size dup(?)  ; Buffer (1 per com card)
  73.           DB      1                   ; Com number
  74.           DB      0                   ; Flags
  75.           DB      0                   ; Last receive status
  76.           DB      0BH              ; Hardware interrupt vector
  77.           DB      0F7H              ; Mask
  78.           DW      02F8H                  ; Base port address
  79.           DW      0                   ; # of chars in buffer
  80.           DW      ?                   ; Buffer in pointer
  81.           DW      ?                   ; Buffer out pointer
  82.  
  83.  
  84. comend:                               ; Marker for last com port
  85.  
  86. ;--------------------------------------------------------------------------;
  87. ; Hardware constants                                                       ;
  88. ;--------------------------------------------------------------------------;
  89.  
  90. pic_cmd_port     EQU       020H   ; 8259 interrupt controller command address
  91. pic_mask_port    EQU       021H   ; 8259 interrupt controller mask address
  92.  
  93. ;--------------------------------------------------------------------------;
  94. ; 8250 hardware constants                                                  ;
  95. ;--------------------------------------------------------------------------;
  96.  
  97. rbr_8250         EQU 00H   ;       xF8   Receive Buffer Register
  98. thr_8250         EQU 00H   ;       xF8   Transmitter Holding Register
  99. ier_8250         EQU 01H   ;       xF9   Interrupt Enable Register
  100. iir_8250         EQU 02H   ;       xFA   Interrupt Identification Register
  101. lcr_8250         EQU 03H   ;       xFB   Line Control Register
  102. mcr_8250         EQU 04H   ;       xFC   Modem Control Register
  103. lsr_8250         EQU 05H   ;       xFD   Line Status Register
  104. msr_8250         EQU 06H   ;       xFE   Modem Status Register
  105. dll_8250         EQU 00H   ;       xF8   Divisor Latch Least Significant
  106. dlm_8250         EQU 01H   ;       xF9   Divisor Latch Most  Significant
  107.  
  108. ;--------------------------------------------------------------------------;
  109. ; Communications constants                                                 ;
  110. ;--------------------------------------------------------------------------;
  111.  
  112. CR    EQU 0DH                           ; Carriage Return
  113. LF    EQU 0AH                           ; Line Feed
  114.  
  115. ;--------------------------------------------------------------------------;
  116. ; Static variables                                                         ;
  117. ;--------------------------------------------------------------------------;
  118.  
  119. old_bios_vector   DW  ?            ; Save previous interrupt vector
  120.                   DW  ?            ;
  121.  
  122. int_8250       LABEL        WORD
  123.           DW  OFFSET serint_1_8250
  124.           DW  OFFSET serint_2_8250
  125.  
  126. divisor_table LABEL WORD            ;
  127.         DW      1047                ; 110
  128.         DW      768                 ; 150
  129.         DW      384                 ; 300
  130.         DW      192                 ; 600
  131.         DW      96                  ; 1200
  132.         DW      48                  ; 2400
  133.         DW      24                  ; 4800
  134.         DW      12                  ; 9600
  135.  
  136. ;--------------------------------------------------------------------------;
  137. ; Our BIOS handler                                                         ;
  138. ;--------------------------------------------------------------------------;
  139.  
  140. rsint:
  141.  
  142.         ASSUME DS: NOTHING         ; Don't use DS
  143.         ASSUME ES: NOTHING         ; Don't use ES
  144.         ASSUME SS: NOTHING         ; Don't use SS
  145.  
  146. ;--------------------------------------------------------------------------;
  147. ; Not disabled please                                                      ;
  148. ;--------------------------------------------------------------------------;
  149.  
  150.         STI                         ;
  151.  
  152. ;--------------------------------------------------------------------------;
  153. ; See if this is our vector?                                               ;
  154. ;--------------------------------------------------------------------------;
  155.  
  156.         PUSH    BP                  ; Save BP over our loop
  157.         XOR     BP,BP               ;
  158.  
  159. com_srch_loop:                      ;
  160.  
  161.         CMP     DL,CS:comnumber[BP] ; Is this our port?
  162.         JE      rsint_ours          ; Yes...
  163.  
  164.         ADD     BP,OFFSET dummy_end ; Increment to next com port block
  165.  
  166.         CMP     BP,OFFSET comend    ; Anything left to be checked?
  167.         JL      com_srch_loop       ; Yep....
  168.  
  169. ;--------------------------------------------------------------------------;
  170. ; Not us.. Pop things out and call regular handler                         ;
  171. ;--------------------------------------------------------------------------;
  172.  
  173. not_us:
  174.  
  175.         POP     BP                  ; Pop BP
  176.         JMP     CS:DWORD PTR old_bios_vector
  177.  
  178. ;--------------------------------------------------------------------------;
  179. ; BP now contains the pointer to the com block...  See what                ;
  180. ; the user has requested and we may or may not do it.......                ;
  181. ;--------------------------------------------------------------------------;
  182.  
  183. rsint_ours:
  184.  
  185.         PUSH    DX                  ; We need the DX register
  186.         PUSH    CX                  ; We need the CX register
  187.         PUSH    BX                  ; We need the BX register
  188.  
  189.         MOV     CX,baseaddr[BP]     ; Get base address for chip
  190.  
  191.         OR      AH,AH               ; Initialize
  192.         JE      rsint_init          ; Yes...
  193.  
  194.         DEC     AH                  ; 1 = Send character
  195.         JZ      rsint_send
  196.  
  197.         DEC     AH                  ; 2 = Receive character
  198.         JZ      rsint_recv_jmp
  199.  
  200.         DEC     AH                  ; 3 = Status request
  201.         JZ      rsint_status_jmp
  202.  
  203.         DEC     AH                  ; 4 = Inquiry         
  204.         JZ      rsint_inquiry_jmp
  205.  
  206.         DEC     AH                  ; 5 = Drop RTS         
  207.         JZ      rsint_RTS_off_jmp
  208.  
  209.         DEC     AH                  ; 6 = Raise RTS         
  210.         JZ      rsint_RTS_on_jmp
  211.  
  212.         DEC     AH                  ; 7 = Send break
  213.         JZ      rsint_break_jmp
  214.  
  215.         DEC     AH                  ; 8 = Non-destructive read
  216.         JNZ     rsint_exit          ;      Nope..
  217.         JMP     rsint_nd_recv       ;      Yep..
  218.  
  219. rsint_recv_jmp:
  220.     JMP     rsint_recv
  221. rsint_status_jmp:
  222.     JMP     rsint_status
  223. rsint_inquiry_jmp:
  224.     JMP     rsint_inquiry
  225. rsint_RTS_off_jmp:
  226.     JMP     rsint_RTS_off
  227. rsint_RTS_on_jmp:
  228.     JMP     rsint_RTS_on
  229. rsint_break_jmp:
  230.         JMP     rsint_break
  231.  
  232. ;--------------------------------------------------------------------------;
  233. ; Interrupt exit                                                           ;
  234. ;--------------------------------------------------------------------------;
  235.  
  236. rsint_exit:
  237.  
  238.         POP     BX                  ; Restore registers
  239.         POP     CX                  ;
  240.         POP     DX                  ;
  241.         POP     BP                  ;
  242.         IRET                        ;      and leave
  243.  
  244. ;--------------------------------------------------------------------------;
  245. ; Init..                                                                   ;
  246. ;--------------------------------------------------------------------------;
  247.  
  248. rsint_init:
  249.  
  250.  
  251.         MOV     AH,AL               ; Save the parms for later
  252.  
  253.         MOV     BL,AH               ; Look up the baud rate
  254.         MOV     CL,4                ; parameter
  255.         ROL     BL,CL               ;
  256.         AND     BX,0EH              ;
  257.         MOV     BX,divisor_table[BX] ;
  258.  
  259.         MOV     CX,baseaddr[BP]     ; Get base address for chip
  260.         MOV     DX,CX               ; Address of LCR
  261.         ADD     DX,lcr_8250         ;
  262.         MOV     AL,10000000B        ; Enable access to divisor
  263.         OUT     DX,AL               ;
  264.  
  265.         MOV     DX,CX               ; Address of lower divisior half
  266.         ADD     DX,dll_8250         ;
  267.         MOV     AL,BL               ; Put lower half
  268.         OUT     DX,AL               ;
  269.  
  270.         MOV     DX,CX               ; Address of upper divisior half
  271.         ADD     DX,dlm_8250         ;
  272.         MOV     AL,BH               ; Put upper half
  273.         OUT     DX,AL               ;
  274.  
  275.         MOV     AL,AH               ; Get parms back
  276.         AND     AL,01FH             ; Throw away baud rate
  277.         MOV     DX,CX               ; Address of LCR
  278.         ADD     DX,lcr_8250         ;
  279.         OUT     DX,AL               ; Output the parms
  280.  
  281.         JMP     rsint_status        ; Now just status please
  282.  
  283. ;--------------------------------------------------------------------------;
  284. ; Send a character                                                         ;
  285. ;--------------------------------------------------------------------------;
  286.  
  287. rsint_send:
  288.  
  289.         MOV     AH,AL               ; Save the character to send
  290.  
  291. rsint_send_loop:                    ; Loop here until we can send
  292.  
  293.         MOV     DX,CX               ; Compute port address for the MSR
  294.         ADD     DX,msr_8250         ;      and then
  295.         IN      AL,DX               ;      get it into AX
  296.         AND     AL,00110000B        ; CTS & DSR?
  297.         CMP     AL,00110000B        ; 
  298.     JNE    rsint_send_loop
  299.  
  300.         MOV     DX,CX               ; Compute port address for the LSR
  301.         ADD     DX,lsr_8250         ;      and then
  302.         IN      AL,DX               ;      get itinto AX
  303.         TEST    AL,00100000B        ; THR empty?
  304.         JZ      rsint_send_loop     ;      No.. Loop back
  305.  
  306.         MOV     AL,AH               ; Get ready to out character
  307.  
  308.         MOV     DX,CX               ; Compute port address for the THR
  309. ;       ADD     DX,thr_8250         ;      and then
  310.         OUT     DX,AL               ;      out the character
  311.  
  312.         JMP     rsint_status        ; Do a status
  313.  
  314. ;--------------------------------------------------------------------------;
  315. ; Receive a character                                                      ;
  316. ;--------------------------------------------------------------------------;
  317.  
  318. rsint_recv:
  319.  
  320.         MOV     BX,buffer_out[BP]   ; Get buffer output pointer
  321.  
  322. rsint_recv_loop:
  323.  
  324.         CMP     count[BP],0         ; See in anything in buffer
  325.         JE      rsint_recv_loop     ; Wait for it
  326.  
  327. rsint_get_char:
  328.         MOV     AL,CS:[BX]          ; Get character from buffer
  329.         PUSH    AX                  ; Save char
  330.         INC     BX                  ; Bump pointer
  331.         DEC     count[BP]           ; Dec char count
  332.         MOV     DX,OFFSET buffer_e  ; Compute end of buffer
  333.         ADD     DX,BP               ;
  334.         CMP     BX,DX               ; Have we wrapped the buffer?
  335.         JL      test_handshake      ;      No.. All done
  336.         MOV     BX,OFFSET buffer    ;      Yes.. Reset pointer
  337.         ADD     BX,BP               ;
  338. test_handshake:
  339.         cmp     count[BP],80H
  340.         jnb     test_full
  341.         mov     ah,flags[BP]
  342.         test    ah,1
  343.         jz      test_full
  344. roll_hands:
  345.         mov     DX,CX
  346.         add     DX,mcr_8250
  347.         in      AL,DX
  348.           or    AL,00001011B      ; Raise DTR, RTS  & OUT2 
  349.         out     DX,AL
  350.         and     AH,0FEH
  351.         mov     flags[BP],AH
  352.  
  353. test_full:
  354.     POP    AX                  ; Restore Char
  355.  
  356.         MOV     buffer_out[BP],BX   ; Save pointer
  357.         MOV     AH,last_rs[BP]      ; Get last LSR from receive
  358.         AND     AH,11111110B        ; Remove data ready bit
  359.         CMP     count[BP],0         ; Anything left in buffer?
  360.         JE      short_exit          ;      Nope so leave
  361.         OR      AH,00000001B        ; Turn on data ready
  362. short_exit:
  363.         JMP     rsint_exit          ;      and go leave
  364.  
  365. ;--------------------------------------------------------------------------;
  366. ; Non-destructive Receive character                                        ;
  367. ;   (get next character, no pointer updates, no check for character ready) ;
  368. ;--------------------------------------------------------------------------;
  369.  
  370. rsint_nd_recv:
  371.  
  372.         MOV     BX,buffer_out[BP]   ; Get buffer output pointer
  373.         MOV     AL,CS:[BX]          ; Get character from buffer
  374.         JMP     rsint_exit          ;      and go leave
  375.  
  376. ;--------------------------------------------------------------------------;
  377. ; Status..                                                                 ;
  378. ;--------------------------------------------------------------------------;
  379.  
  380. rsint_status:
  381.  
  382.         MOV     DX,CX               ; Compute port address for the LSR
  383.         ADD     DX,lsr_8250         ;      and then
  384.         IN      AL,DX               ;      get it
  385.  
  386.         AND     AL,11111110B        ; Remove data ready bit
  387.  
  388.         CMP     count[BP],0         ; Anything left in buffer?
  389.         JE      rsint_status_nodr   ;      Nope so leave
  390.         OR      AL,00000001B        ; Turn on data ready
  391. rsint_status_nodr:
  392.         MOV     AH,AL               ; Save LSR
  393.  
  394.         MOV     DX,CX               ; Compute port address for the MSR
  395.         ADD     DX,msr_8250         ;      and then
  396.         IN      AL,DX               ;      get it
  397.  
  398.         JMP     rsint_exit          ; All done
  399.  
  400. ;--------------------------------------------------------------------------;
  401. ; Inquiry                                                                  ;
  402. ; (Return AA55H in AX - Just an identification scheme to tell              ;
  403. ;  if this silly driver has been loaded)                                   ;
  404. ;--------------------------------------------------------------------------;
  405.  
  406. rsint_inquiry:
  407.  
  408.         MOV    AX,0AA55H
  409.         JMP     rsint_exit          ;      and go leave
  410.  
  411.  
  412.  
  413. ;--------------------------------------------------------------------------;
  414. ; RTS off                                                                  ;
  415. ; (Drop RTS)                                                               ;
  416. ;--------------------------------------------------------------------------;
  417.  
  418. rsint_RTS_off:
  419.  
  420.         MOV    DX,CX
  421.         add    DX,mcr_8250
  422.         in    AL,DX
  423.           and    AL,0FCH
  424.           out    DX,AL
  425.         JMP     rsint_exit          ;      and go leave
  426.  
  427. ;--------------------------------------------------------------------------;
  428. ; RTS on                                                                   ;
  429. ; (Raise RTS)                                                              ;
  430. ;--------------------------------------------------------------------------;
  431.  
  432. rsint_RTS_on:
  433.  
  434.         MOV    DX,CX
  435.         add    DX,mcr_8250
  436.         in    AL,DX
  437.           or    AL,00001011B      ; Raise DTR, RTS  & OUT2 
  438.           out    DX,AL
  439.  
  440. ;make sure the interrupt is still turned on
  441.  
  442.         CLI                       ; Disable interrupts
  443.         MOV     DX,CX             ; Compute port address for the IER
  444.         ADD     DX,ier_8250       ;
  445.         MOV     AL,00000001B      ; Enable data interrupt only
  446.         OUT     DX,AL             ;
  447.  
  448. ;while we are at it, lets make sure the 8259 didnt get turned off!
  449.  
  450.         IN      AL,pic_mask_port  ; Set up 8259 interupt controller
  451.         AND     AL,int_mask[BP]   ; Enable the interrupts for this device
  452.         OUT     pic_mask_port,AL  ;
  453.         STI
  454.  
  455.         JMP     rsint_exit          ;      and go leave
  456.  
  457.  
  458.  
  459. ;--------------------------------------------------------------------------;
  460. ; Send break                                                               ;
  461. ;                                                                          ;
  462. ;--------------------------------------------------------------------------;
  463.  
  464. rsint_break:
  465.  
  466.         MOV    DX,CX
  467.         add    DX,lcr_8250
  468.         in    AL,DX
  469.           mov    bl,al        ;save old LCR
  470.  
  471.     or      al,40H       ; set break condition
  472.     out    dx,al
  473.      
  474.     mov     cx,0        ; wait a while
  475. bkwait: loop    bkwait
  476.      
  477.     mov     al,bl           ; restore LCR
  478.     out    dx,al
  479.         JMP     rsint_exit      ;      and exit
  480.  
  481.  
  482. ;--------------------------------------------------------------------------;
  483. ; 8250 interrupt handler                                                   ;
  484. ;--------------------------------------------------------------------------;
  485.  
  486. serint_1_8250:
  487.  
  488.         PUSH    BP
  489.         MOV    BP,int_8250+0
  490.         JMP    SHORT serint_8250
  491.  
  492. serint_2_8250:
  493.  
  494.         PUSH    BP
  495.         MOV    BP,int_8250+2
  496.  
  497. serint_8250:
  498.  
  499.         PUSH    DX
  500.         PUSH    AX
  501.         PUSH    CX                  ; Save some registers
  502.         PUSH    DI                  ;
  503.  
  504.         MOV     CX,baseaddr[BP]     ; Get base address for chip
  505.  
  506.         MOV     DX,CX               ; Get the IIR
  507.         ADD     DX,iir_8250         ;
  508.         IN      AL,DX               ;
  509.  
  510.         TEST    AL,00000001B        ; Interrupt pending?
  511.         JZ      service
  512.         JMP     serint_8250_exit    ;     No leave...
  513.  
  514. service:
  515.         MOV     DX,CX               ; Get the LSR
  516.         ADD     DX,lsr_8250         ;
  517.         IN      AL,DX               ;
  518.         MOV     last_rs[BP],AL      ; And tuck it away
  519.  
  520.         MOV     DX,CX               ; Get the RBR
  521. ;       ADD     DX,rbr_8250         ;
  522.         IN      AL,DX               ;
  523.         MOV     DI,buffer_in[BP]    ; Get the buffer pointer
  524.         MOV     CS:[DI],AL          ; Save the character
  525.         INC     DI                  ; Bump pointer and handle wrap
  526.         inc     count[BP]           ; inc char count
  527.         MOV     AX,OFFSET buffer_e  ;
  528.         ADD     AX,BP               ;
  529.         CMP     DI,AX               ;
  530.         JL      serint_8250_nowrap  ;
  531.         MOV     DI,OFFSET buffer    ;
  532.         ADD     DI,BP               ;
  533.  
  534. serint_8250_nowrap:
  535.  
  536.         cmp    count[BP],buffer_full
  537.         jb     hand_done
  538.         mov    DX,CX
  539.         add    DX,mcr_8250
  540.         in     al,DX
  541.           and    AL,11111100B        ; Drop DTR & RTS
  542.         out    DX,AL
  543.         mov    ah,flags[BP]
  544.         or     AH,1
  545.         mov    flags[BP],AH 
  546.  
  547. hand_done:
  548.      
  549.         CMP     DI,buffer_out[BP]   ; Overflow of buffer?
  550.         JNE     serint_8250_noover  ;
  551.         OR      last_rs[BP],02H     ; Overrun indicate
  552.         JMP     SHORT serint_8250_exit ;  Don't save the updated pointer
  553. serint_8250_noover:
  554.         MOV     buffer_in[BP],DI    ; Save the updated pointer
  555.  
  556. serint_8250_exit:
  557.  
  558.         MOV     AL,020H             ; Tell 8259 we are done
  559.         OUT     pic_cmd_port,AL     ;
  560.         POP     DI                  ; Restore registers
  561.         POP     CX                  ;
  562.         POP     AX                  ;
  563.         POP     DX                  ;
  564.         POP     BP                  ;
  565.  
  566.         IRET                        ; Exit
  567.  
  568. program_end:
  569.  
  570.  
  571. ;--------------------------------------------------------------------------;
  572. ; Main line to initialize. 
  573. ;--------------------------------------------------------------------------;
  574.  
  575.       ASSUME DS: everything          
  576.  
  577. ;--------------------------------------------------------------------------;
  578. ; Constants only needed by initialization                                  ;
  579. ;--------------------------------------------------------------------------;
  580.  
  581. inter_count    DW    0
  582.  
  583. P3F8     DB    0    ;1 IF CARD AT 3F8
  584. P2F8     DB    0    ;1 IF CARD AT 2F8
  585. PCNT     DB    0    ;Total # ports found
  586.  
  587. HELLO    DB    CR,LF
  588.     DB    'COMBIOS Driver v1.6',CR,LF
  589.     DB    'Dec 31, 1986 '
  590.     DB    CR,LF,'$'
  591.  
  592. BYE      DB    CR,LF
  593.     DB    'Driver Installed OK!'
  594.     DB    CR,LF,'$'
  595.  
  596. LOADED     DB    CR,LF
  597.     DB    'COMBIOS already loaded!'
  598.     DB    CR,LF,'$'
  599.  
  600. COM1F    DB    CR,LF
  601.     DB    'COM1: board found at 03F8',CR,LF
  602.     DB    '$'
  603.  
  604. COM2F    DB    CR,LF
  605.     DB    'COM2: board found at 02F8',CR,LF
  606.     DB    '$'
  607.  
  608. NOCOM     DB    CR,LF
  609.     DB    'Only found 1 serial board.'
  610.     DB    CR,LF
  611.     DB    'Driver NOT installed!',CR,LF
  612.     DB    '$'
  613.  
  614. ; INITIALIZE ROUTINE
  615.  
  616. start:  MOV     AX,CS                 ; Point DS in the right place
  617.         MOV     DS,AX                
  618.     CALL    SINON    ;PRINT SIGN ON
  619.  
  620.     MOV    DX,00    ;Check to see if support already loaded
  621.     MOV    AH,04
  622.     INT    14H
  623.     CMP    AX,0AA55H
  624.     JZ    EXIT    ;Must be loaded
  625.  
  626.     MOV    DX,01    ;Check to see if support already loaded
  627.     MOV    AH,04
  628.     INT    14H
  629.     CMP    AX,0AA55H
  630.     JZ    EXIT    ;Must be loaded
  631.  
  632.     CALL    CNFIG    ;CHECK CONFIGURATION
  633.     OR    AX,AX
  634.     JNZ    EREXIT    ;JMP IF ERRORS
  635.  
  636.     CALL    init_vectors    ;SET INTERRUPT VECTORS
  637.  
  638.     CALL    SINOFF        ;PRINT SIGN OFF
  639.     MOV    AL,0        ;set exit code
  640.         MOV     DX,OFFSET program_end
  641.         MOV    CL,4
  642.         SHR    DX,CL
  643.         INC    DX
  644.     MOV    AH,31H
  645.     INT    21H             ; Terminate but stay resident
  646.  
  647. EREXIT:    MOV    AL,1        ;set exit code = Error
  648.     MOV    AH,4CH
  649.     INT    21H             ; Terminate and return
  650.  
  651. EXIT:    LEA    DX,LOADED
  652.     MOV    AH,9
  653.     INT    21H
  654.          MOV    AL,0        ;set exit code = Ok
  655.     MOV    AH,4CH
  656.     INT    21H             ; Terminate and return
  657.  
  658.  
  659. ;---------
  660. CNFIG:  CALL    FNDPT        ;Find Ports
  661.     CMP    P3F8,1
  662.     JNE    CNF1
  663.     INC    PCNT
  664.           LEA    DX,COM1F    ;Say COM1 Found
  665.     MOV    AH,9
  666.     INT    21H
  667.  
  668. CNF1:    CMP    P2F8,1
  669.     JNE    CNF2
  670.           LEA    DX,COM2F    ;Say COM2 Found
  671.     INC    PCNT
  672.     MOV    AH,9
  673.     INT    21H
  674.  
  675. CNF2:    CMP    PCNT,2
  676.     JE    CNF3
  677.           LEA    DX,NOCOM     ;Say OOPS
  678.     MOV    AH,9
  679.     INT    21H
  680.  
  681. CNFERR:    MOV    AX,0FFFFH    ;Set Error
  682.     RET
  683.  
  684. CNF3:    SUB    AX,AX
  685.     RET
  686.  
  687. ;------------
  688.  
  689. FNDPT:    MOV    DX,03F8H
  690.     CALL    CKPORT
  691.     CMP    BP,0
  692.     JZ    PT2
  693.  
  694.     INC    P3F8
  695.  
  696. PT2:    MOV    DX,02F8H
  697.     CALL    CKPORT
  698.     CMP    BP,0
  699.     JZ    PT3
  700.  
  701.     INC    P2F8
  702.  
  703. PT3:    RET
  704.  
  705.  
  706. ;----------------------
  707. ;Check for valid Port
  708. ;Enter with DX containing Port address
  709. ;Exit with BP=Port address if port found  BP=0 if not found
  710.  
  711.  
  712. CKPORT: MOV     BP,DX        ;For return
  713.     MOV    CL,DL        ;Keep DL Handy
  714.  
  715.     ADD    DX,3
  716.     IN    AL,DX        ;Save old LCR in CH
  717.     MOV    CH,AL
  718.  
  719.           MOV    AL,80H        ;Address Divisor Latch
  720.     OUT    DX,AL
  721.     CALL    WAIT
  722.  
  723.     MOV    DL,CL
  724.     IN    AL,DX        
  725.     MOV    AH,AL        ;Save old Divisor
  726.     CALL    WAIT
  727.  
  728.     INC    DX
  729.     IN    AL,DX        ;Save old Divisor
  730.     MOV    BX,AX
  731.     CALL    WAIT
  732.  
  733.     MOV    DL,CL
  734.     MOV    AL,55H            ;OUTPUT 55
  735.     OUT    DX,AL
  736.     CALL    WAIT
  737.  
  738.     INC    DX
  739.     MOV    AL,0AAH
  740.     OUT    DX,AL        ;OUTPUT AA
  741.     CALL    WAIT
  742.  
  743.     MOV    DL,CL
  744.     IN    AL,DX        ;Read New Divisor
  745.     MOV    AH,AL
  746.     CALL    WAIT
  747.  
  748.     INC    DX
  749.     IN    AL,DX
  750.     CMP    AX,55AAH    ;DO THEY MATCH?
  751.     JZ     Match
  752.  
  753.     XOR    BP,BP        ;Zero - no match
  754.  
  755. Match:    MOV    DL,CL
  756.     MOV    AL,BH        ;Restore old Divisor
  757.     OUT    DX,AL
  758.     CALL    WAIT
  759.  
  760.     INC    DX
  761.     MOV     AL,BL
  762.     OUT    DX,AL
  763.     CALL    WAIT
  764.  
  765.     INC    DX
  766.     INC    DX        ;and old LCR
  767.     MOV    AL,CH
  768.     OUT    DX,AL
  769.     CALL    WAIT
  770.  
  771. WAIT:    RET
  772.  
  773. ;---------
  774. ;PRINT SIGNON 
  775. SINON:    LEA    DX,HELLO
  776.     MOV    AH,9
  777.     INT    21H
  778.     RET
  779.  
  780. ;PRINT SIGNOFF
  781. SINOFF:    LEA    DX,BYE
  782.     MOV    AH,9
  783.     INT    21H
  784.     RET
  785.  
  786.  
  787.  
  788. ;--------------------------------------------------------------------------;
  789. ; Now snatch the BIOS comm vector  (Int 14)                                ;
  790. ;--------------------------------------------------------------------------;
  791.  
  792. init_vectors:
  793.     MOV    AL,14H
  794.     MOV    AH,35H
  795.     INT    21H
  796.         MOV     old_bios_vector,BX     ;      save old vector
  797.         MOV     old_bios_vector+2,ES   ;
  798.  
  799.         MOV     DX,OFFSET rsint     ; Replace with our vector
  800.     MOV    AL,14H
  801.     MOV    AH,25H
  802.     INT    21H
  803.  
  804. ;--------------------------------------------------------------------------;
  805. ; Loop initializing each COM port                                          ;
  806. ;--------------------------------------------------------------------------;
  807.  
  808.         XOR     AX,AX                 ; Get a zero
  809.         MOV     BP,AX                 ; Place to start the comm loop is  0
  810.  
  811. init_loop:
  812.  
  813.  
  814. ;--------------------------------------------------------------------------;
  815. ; Set the hardware interrupt vector                                        ;
  816. ;--------------------------------------------------------------------------;
  817.  
  818.     MOV    DI,inter_count        ;Get next ptr
  819.  
  820.         MOV     DX,int_8250[DI]        ; Get our address
  821.     MOV    AL,hiv[BP]
  822.            MOV    AH,25H
  823.     INT    21H
  824.  
  825.         MOV     int_8250[DI],BP        ; save com block address
  826.  
  827.     INC    DI
  828.     INC    DI
  829.     MOV    inter_count,DI        ;Save next ptr
  830.  
  831. ;--------------------------------------------------------------------------;
  832. ; Initialize the buffer ring pointers                                      ;
  833. ;--------------------------------------------------------------------------;
  834.  
  835.         MOV     AX,OFFSET buffer  ; Get start of buffer address
  836.         ADD     AX,BP             ; include our offset
  837.         MOV     buffer_in[BP],AX  ; Put in the buffer pointers
  838.         MOV     buffer_out[BP],AX ; Put in the buffer pointers
  839.  
  840. ;--------------------------------------------------------------------------;
  841. ; Set the interrupt registers in the UART and clean things up              ;
  842. ;--------------------------------------------------------------------------;
  843.  
  844.         CLI                       ; Disable interrupts
  845.  
  846.         IN      AL,pic_mask_port  ; Set up 8259 interupt controller
  847.         AND     AL,int_mask[BP]   ; Enable the interrupts for this device
  848.         OUT     pic_mask_port,AL  ;
  849.  
  850.         MOV     CX,baseaddr[BP]     ; Get base address for chip
  851.  
  852.         MOV     DX,CX             ; Compute port address for the IER
  853.         ADD     DX,ier_8250       ;
  854.         MOV     AL,00000001B      ; Enable data interrupt only
  855.         OUT     DX,AL             ;
  856.  
  857.         MOV     DX,CX             ; Compute port address for the MCR
  858.         ADD     DX,mcr_8250       ;
  859.         MOV     AL,00001000B      ; Raise OUT2. OUT2 turns
  860.                                   ; on interrupts
  861.         OUT     DX,AL             ;
  862.  
  863.         MOV     DX,CX             ; Compute port address for the MCR
  864.         ADD     DX,rbr_8250       ;
  865.         IN      AL,DX             ; Read the input buffer and throw it away
  866.  
  867. ;--------------------------------------------------------------------------;
  868. ; Loop thru the next comm port                                             ;
  869. ;--------------------------------------------------------------------------;
  870.  
  871.     ADD    BP,OFFSET dummy_end
  872.  
  873.     CMP    BP,OFFSET comend    ;done yet?
  874.     JGE    com_done
  875.     JMP    init_loop
  876.  
  877. com_done:
  878.  
  879. ;--------------------------------------------------------------------------;
  880. ; Enable interrupts                                                        ;
  881. ;--------------------------------------------------------------------------;
  882.  
  883.         STI                        ; Enable CPU to receive interupts
  884.         RET
  885.  
  886. everything ENDS
  887.  
  888.         END foo
  889.