home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / PEN / PENTKT / PENBASE / SERIAL.ASM < prev    next >
Assembly Source File  |  1995-04-14  |  14KB  |  521 lines

  1. ;*DDK*************************************************************************/
  2. ;
  3. ; COPYRIGHT    Copyright (C) 1995 IBM Corporation
  4. ;
  5. ;    The following IBM OS/2 WARP source code is provided to you solely for
  6. ;    the purpose of assisting you in your development of OS/2 WARP device
  7. ;    drivers. You may use this code in accordance with the IBM License
  8. ;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
  9. ;    Copyright statement may not be removed.;
  10. ;*****************************************************************************/
  11. ;      /*****************************************************************/
  12. ;      /*                                                               */
  13. ;      /*                                                               */
  14. ;      /*****************************************************************/
  15. ;      /******************* START OF SPECIFICATIONS *********************/
  16. ;      /*                                                               */
  17. ;      /*  SOURCE FILE NAME: SERIAL.ASM                                 */
  18. ;      /*                                                               */
  19. ;      /*  DESCRIPTIVE NAME: Serial IO routine                          */
  20. ;      /*                                                               */
  21. ;      /*                                                               */
  22. ;      /*  STATUS:  Version 1.0                                         */
  23. ;      /*                                                               */
  24. ;      /*  NOTES: This module contains routines to manage a COM port.   */
  25. ;      /*                                                               */
  26. ;      /*  ENTRY POINTS:                                                */
  27. ;      /*      See public statements                                    */
  28. ;      /*  EXTERNAL REFERENCES:                                         */
  29. ;      /*      See extrn statements                                     */
  30. ;      /*                                                               */
  31. ;      /******************* END  OF  SPECIFICATIONS *********************/
  32. .xlist
  33.   include pensegs.inc
  34.   include pen.inc
  35.   include serial.inc
  36.   include devhlp.inc
  37.   include struc.inc
  38. .list
  39.  
  40. ;------- ABIOS ERRORs --------------------
  41. MSG_MEMORY_ALLOCATION_FAILED    EQU     0
  42. ERROR_LID_ALREADY_OWNED         EQU     1
  43. ERROR_LID_DOES_NOT_EXIST        EQU     2
  44. ERROR_ABIOS_NOT_PRESENT         EQU     3
  45. ERROR_NOT_YOUR_LID              EQU     4
  46. ERROR_INVALID_ENTRY_POINT       EQU     5
  47.  
  48. ;------- LOCAL EQUATES -------------------
  49. INTERRUPT_TEST         EQU 1000b
  50. INTERRUPT_INIT_MASK    EQU 07h
  51.  
  52. .286p
  53.  
  54. ;------------------------------------------------------------------------------
  55. ;declare external variables
  56. ;------------------------------------------------------------------------------
  57.  
  58. extrn Device_Help    : dword
  59. extrn Dev_ErrorCount : dword
  60.  
  61. ;------------------------------------------------------------------------------
  62. ;declare external routines
  63. ;------------------------------------------------------------------------------
  64.  
  65. extrn Trc_INT : near
  66. extrn Trc_DD  : near
  67.  
  68. CSEG     SEGMENT
  69.          ASSUME    CS:CGROUP, SS:nothing, ES:nothing, DS:DGROUP
  70.  
  71. ;---- SERVICE ROUTINES --------------------------------------------------------
  72. ;
  73. ;------------------------------------------------------------------------------
  74.  
  75. ;------------------------------------------------------------------------------
  76. ; Change the baud rate
  77. ; bx = dcb
  78. ; si = serial struc
  79. ; al = baud rate
  80. ;------------------------------------------------------------------------------
  81. public Ser_ChangeBaud
  82. Ser_ChangeBaud proc near
  83.  
  84.   ; disable interrupts for the device at the PIC
  85.  
  86.   push ax
  87.   call Ser_DisableInts
  88.   pop  ax
  89.  
  90.   mov  [si].comdivisor, al
  91.  
  92. ; Reset DLAB in order to set baud rate
  93.  
  94.   mov  ah, LCR
  95.   mov  al, 80H
  96.   call Ser_DoOut
  97.  
  98. ; Set  Baud
  99.  
  100.   sub  al, al
  101.   mov  ah, LATMSB
  102.   call Ser_DoOut
  103.   mov  al, [si].comdivisor
  104.   mov  ah, LATLSB
  105.   call Ser_DoOut
  106.  
  107. ; Reset DLAB, set LCR
  108.  
  109.   mov  ah, LCR
  110.   mov  al, [si].comLCR
  111.   call Ser_DoOut
  112.  
  113. ; Enable device at the PIC
  114.  
  115.   call Ser_EnableInts
  116.  
  117.   ret
  118. Ser_ChangeBaud endp
  119.  
  120. ;------------------------------------------------------------------------------
  121. ; set state of FIFO
  122. ;  bx = dcb
  123. ;  si = serial struc
  124. ;------------------------------------------------------------------------------
  125. public Ser_FIFO
  126. Ser_FIFO          Proc  Near
  127.  .if <[si].fcomFIFO ne 0>
  128.     mov  ah, FCR
  129.     mov  al, [si].comFCR
  130.     call Ser_DoOut
  131.  .endif
  132.  ret
  133. Ser_FIFO endp
  134.  
  135. ;------------------------------------------------------------------------------
  136. ; resume interrupt driven events
  137. ;  bx = dcb
  138. ;  si = serial struc
  139. ;------------------------------------------------------------------------------
  140. public Ser_EnableInts
  141. Ser_EnableInts    Proc  Near
  142.   pushf                           ; save state of IF
  143.   DISABLE                         ; Hold interrupts for 8259 Update
  144.  
  145. ; begin defect 69804
  146.  
  147. ; if interrupt level is < 8 process the master PIC
  148.   test [si].interruptLevel, INTERRUPT_TEST
  149.   jz   enable_master
  150.  
  151. ; process slave PIC
  152.   in   al, 0A1h
  153.   and  al, [si].enable_8259
  154.   out  0A1h, al
  155.   popf
  156.   ret
  157.  
  158. ; process master PIC
  159. enable_master:
  160.  
  161. ; end defect 69804
  162.  
  163.   in   al, 21h                    ; Get current Interrupt Mask
  164.   and  al, [si].enable_8259       ; Set serial Interrupt IRQ Bit - OFF
  165.   out  21h, al                    ; set innterrupt mask
  166.   popf                            ; restore interrupt flag state
  167.   ret
  168. Ser_EnableInts    EndP
  169.  
  170. ;------------------------------------------------------------------------------
  171. ; suspend interrupt driven events
  172. ;  bx = dcb
  173. ;  si = serial struc
  174. ;------------------------------------------------------------------------------
  175. public Ser_DisableInts
  176. Ser_DisableInts    Proc  Near
  177.   pushf                              ; save state of IF
  178.   DISABLE                         ; Hold interrupts for 8259 Update
  179.  
  180. ; begin defect 69804
  181.  
  182. ; if interrupt level is < 8 process the master PIC
  183.   test [si].interruptLevel, INTERRUPT_TEST
  184.   jz   disable_master
  185.  
  186. ; process slave PIC
  187.   in   al, 0A1h
  188.   or   al, [si].disable_8259
  189.   out  0A1h, al
  190.   popf
  191.   ret
  192.  
  193. ; process master PIC
  194. disable_master:
  195.  
  196. ; end defect 69804
  197.  
  198.   in   al, 21h                    ; Get current Interrupt Mask
  199.   or   al, [si].disable_8259      ; Set Mouse Interrupt IRQ Bit - ON
  200.   out  21h, al                    ; Reset 8259 holding Mouse ints
  201.   popf                            ; restore interrupt flag
  202.   ret
  203. Ser_DisableInts    EndP
  204.  
  205. ;------------------------------------------------------------------------------
  206. ; output a byte
  207. ;  ah = register offset from base
  208. ;  al = byte to write
  209. ;  si = serial struc
  210. ;------------------------------------------------------------------------------
  211. public  Ser_DoOut
  212. Ser_DoOut   proc
  213.   mov  dx, [si].port
  214.   add  dl, ah
  215.   out  dx, al
  216.   ;MyIODelay
  217.   ret
  218. Ser_DoOut   endp
  219.  
  220. ;------------------------------------------------------------------------------
  221. ; write a byte, check that port is ready for it
  222. ;  al = byte to write
  223. ;  si = serial struc
  224. ;------------------------------------------------------------------------------
  225. public  Ser_DoPut
  226. Ser_DoPut   proc
  227.   push  ax
  228.   .repeat
  229.     mov   ah,LSR
  230.     call  Ser_DoIn
  231.     test  al, 020h
  232.   .until  nz
  233.   pop   ax
  234.   mov   ah,TXB
  235.   call  Ser_DoOut
  236.   ret
  237. Ser_DoPut   endp
  238.  
  239. ;------------------------------------------------------------------------------
  240. ; get a byte
  241. ;  ah = register offset from base
  242. ;  si = serial struc
  243. ; returns
  244. ;  al = byte from port
  245. ;------------------------------------------------------------------------------
  246. public  Ser_DoIn
  247. Ser_DoIn    proc
  248.   mov  dx, [si].port
  249.   add  dl, ah
  250.   in   al, dx
  251.   ;MyIODelay
  252.   ret
  253. Ser_DoIn    endp
  254.  
  255.  
  256. ;---- PROCESS BYTES -----------------------------------------------------------
  257. ;
  258. ;------------------------------------------------------------------------------
  259.  
  260. ;------------------------------------------------------------------------------
  261. ; interrupt handler
  262. ;  bx = dcb
  263. ;  si = serial struc
  264. ;------------------------------------------------------------------------------
  265. public Ser_InterruptHandler
  266. Ser_InterruptHandler proc far
  267.   DISABLE
  268.  
  269.   TraceInt
  270.  
  271. ; issue the EOI and disable the IRQ
  272.  
  273.   call Ser_DisableInts
  274.  
  275. ; mov  al, [si].interruptLevel
  276. ; mov  dl, DevHlp_EOI
  277. ; call Device_Help
  278.  
  279.   ENABLE
  280.  
  281. ; process bytes
  282.  
  283.   .repeat
  284.  
  285.      call readByte                   ; returns al = interrupt data
  286.  
  287.      push si
  288.      call [si].@processByte          ; bx = dcb
  289.      pop  si                         ; al = byte
  290.  
  291.      mov  dx, [si].port               ; Setup Mouse Input Port Number
  292.      add  dx, LSR                     ; Check Line Status Reg
  293.      in   al, dx                      ; Read Line Status Data
  294.  
  295.   .until <bit AL z 01H> near           ; check for more data
  296.  
  297.   call Ser_EnableInts                ; make sure IRQ enabled
  298.  
  299.   mov  al, [si].interruptLevel
  300.   mov  dl, DevHlp_EOI
  301.   call Device_Help
  302.  
  303.   clc                            ; clear carry for our int
  304.  
  305.   ret                            ; return to intr hndlr
  306. Ser_InterruptHandler endp
  307.  
  308. ;------------------------------------------------------------------------------
  309. ; read a byte for the serial port
  310. ;  si = serial struc
  311. ;------------------------------------------------------------------------------
  312. Public   readByte
  313. readByte Proc  Near
  314.  
  315.   DISABLE
  316.  
  317.   MOV  DX, [si].port               ; Setup Mouse Input Port Number
  318.   IN   AL, DX                      ; Read incoming Interrupt data Byte
  319.   PUSH AX                          ; Save Data Byte
  320.   ADD  DX, LSR                     ; Check Line Status Reg
  321.   IN   AL, DX                      ; Read Line Status Data
  322.   MOV  cl, AL                      ; Get Error Code in cl
  323.   POP AX                           ; Restore Data Byte
  324.  
  325.   .IF <bit cl nz LS_PERR+LS_FERR>                 ; If an Error occured then
  326.      .386p
  327.      inc Dev_ErrorCount
  328.      .286p
  329.      push bx
  330.      call [si].@errorRtn           ; bx = dcb
  331.      call Ser_Error
  332.      pop  bx
  333.      xor  ax,ax                    ; this won't match sync bits
  334.   .ENDIF                           ; Data Error Tests
  335.  
  336.  ENABLE
  337.  
  338.   ret
  339. readByte EndP
  340.  
  341. ;---- INITIALIZATION ROUTINES -------------------------------------------------
  342. ; note: Must be in resident code incase of IO error
  343. ;------------------------------------------------------------------------------
  344.  
  345. ;------------------------------------------------------------------------------
  346. ; Initialize the port.
  347. ;  si = serial data
  348. ;------------------------------------------------------------------------------
  349. public Ser_Init
  350. Ser_Init Proc
  351.  
  352. ; claim ASYNC port to keep COM.SYS's hands off
  353.  
  354.   mov  al, 06h                   ; Async Device ID
  355.   mov  bl, [si].comPort          ; Get the LID
  356.   xor  dh, dh
  357.   mov  dl, DevHlp_GetLIDEntry
  358.   call Device_Help
  359.   .if <c>
  360.      .if <ax ne ERROR_ABIOS_NOT_PRESENT>
  361.         PANIC PANIC_SERNOLID
  362.      .endif
  363.   .else
  364.      or   [si].serialStatus,ABIOSLID
  365.   .endif
  366.  
  367. ; Zero out BIOS data area for the Communications Line Port Base address.
  368. ;                     40:0 for Com Port 1
  369. ;                     40:2 for Com Port 2
  370. ;                     40:4 for Com Port 3
  371. ;                     40:6 for Com Port 4
  372.   push es
  373.   mov  bl, [si].comPort
  374.   dec  bl
  375.   xor  bh, bh
  376.   shl  bx, 1
  377.   push 40h
  378.   pop  es
  379.   mov  word ptr es:[bx], 0
  380.   pop  es
  381.  
  382.  
  383. ; Build 8259 IC Mask from returned IRQ #
  384.  
  385.   mov  cl, [si].interruptLevel
  386.  
  387. ; begin defect 69804
  388.  
  389. ; map interrupt levels 8-15 to 0-7 for assigning disable_8259 and enable_8259
  390.  
  391.   and  cl, INTERRUPT_INIT_MASK
  392.  
  393. ; end defect 69804
  394.  
  395.   mov  ax, 0001h
  396.   shl  ax, cl
  397.   mov  [si].disable_8259, al       ; Save Disable 8259 Mask
  398.   not  al                          ; Invert Mask for Enable Bits
  399.   mov  [si].enable_8259, al        ; Save Enable 8259 Mask
  400.  
  401. ; check FIFO level
  402.   mov  ah, FCR
  403.   mov  al, FIFO_ENABLE
  404.   call Ser_DoOut
  405.   mov  ah, IIR
  406.   call Ser_DoIn
  407.  
  408.   .if < bit al nz FIFOMASK >
  409.      mov  [si].fcomFIFO, FIFO_ENABLE
  410.   .else
  411.      mov  [si].fcomFIFO, FIFO_DISABLE
  412.   .endif
  413.  
  414. ; Disable FIFO
  415.   mov  ah, FCR
  416.   mov  al, 0
  417.   call Ser_DoOut
  418.  
  419. ; Check to see if port exists.
  420.  
  421.   mov  ah, IIR
  422.   call Ser_DoIn
  423.   test al, IIRMASK            ; Check reg permanent bits
  424.   .if <nz>                    ; if port does not exist
  425.      PANIC PANIC_SERNOPORT
  426.   .else
  427.      or   [si].serialStatus,COMEXIST
  428.   .endif
  429.  
  430. ; Now go claim the IRQ level.
  431.  
  432.   push bx
  433.   mov  ax, [si].@IntHandler           ; offset of interrupt routine
  434.   xor  bh, bh                         ; clear upper byte
  435.   mov  bl, [si].interruptLevel                      ; get IRQ needed
  436.   xor  dh, dh                         ; IRQ level as unshared
  437.   mov  dl, DevHlp_SetIRQ              ; function number
  438.   call Device_Help                    ; go do it
  439.   pop  bx                             ; restore dcb
  440.  
  441.   .if <c>                             ; if error
  442.      PANIC PANIC_SERNOIRQ             ; (returns with cary set)
  443.   .else
  444.      or  [si].serialStatus,SETIRQ_DONE
  445.   .endif
  446.  
  447. public Ser_Error
  448. Ser_Error:
  449.  
  450. ; Disable device from interrupting at the PIC
  451.  
  452.   call Ser_DisableInts
  453.  
  454. ; Disable interrupts at the device
  455.  
  456.   mov  ah, IER
  457.   xor  al, al
  458.   call Ser_DoOut
  459.  
  460. ; Reset DLAB in order to set baud rate
  461.  
  462.   mov  ah, LCR
  463.   mov  al, 80H
  464.   call Ser_DoOut
  465.  
  466. ; Set  Baud
  467.  
  468.   sub  al, al
  469.   mov  ah, LATMSB
  470.   call Ser_DoOut
  471.   mov  al, [si].comdivisor
  472.   mov  ah, LATLSB
  473.   call Ser_DoOut
  474.  
  475. ; Reset DLAB, set LCR
  476.  
  477.   mov  ah, LCR
  478.   mov  al, [si].comLCR
  479.   call Ser_DoOut
  480.  
  481. ; Set Modem Control Reg
  482.  
  483.   mov  ah, MCR
  484.   mov  al, [si].comMCR
  485.   call Ser_DoOut
  486.  
  487. ; Read stray data
  488.  
  489.   mov  ah, RXB
  490.   mov  cx, 0FFFFH
  491.   .repeat
  492.     call Ser_DoIn
  493.   .loop
  494.  
  495. ; call back to device dependent routine to do its intialization
  496.  
  497.   mov  bx,[si].@DCB
  498.   CALL_NZ_OK [si].@InitRtn
  499.  
  500. ; set FIFO
  501.  
  502.   call Ser_FIFO
  503.  
  504. ; Enable interrupts at device
  505.  
  506.   mov  ah, IER
  507.   mov  al, IERMASK
  508.   call Ser_DoOut
  509.  
  510. ; Enable device at the PIC
  511.  
  512.   call Ser_EnableInts
  513.  
  514.   ret
  515. Ser_Init    endp
  516.  
  517. CSEG ends
  518.  
  519.  
  520. end
  521.