Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4155 lines
151 KiB

  1. page,132
  2. ;---------------------------Module-Header-------------------------------;
  3. ; Module Name: IBMSETUP.ASM
  4. ;
  5. ; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved.
  6. ;
  7. ; General Description:
  8. ;
  9. ; History:
  10. ; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping
  11. ; FCLI/FSTI macros
  12. ;
  13. ;-----------------------------------------------------------------------;
  14. title IBMSetup - IBM PC, PC-XT, PC-AT, PS/2 Communications Interface
  15. .xlist
  16. include cmacros.inc
  17. include comdev.inc
  18. include ins8250.inc
  19. include ibmcom.inc
  20. include BIMODINT.INC
  21. include vint.inc
  22. .list
  23. EBIS_Sel1 equ SIZE Bimodal_Int_Struc
  24. EBIS_Sel2 equ EBIS_Sel1 + (SIZE EBIS_Sel_Struc)
  25. externA __WinFlags
  26. externFP GetSystemMsecCount
  27. externFP CreateSystemTimer
  28. externFP AllocCStoDSAlias
  29. externFP LockSegment
  30. externFP UnlockSegment
  31. externFP FreeSelector
  32. externFP GetSelectorBase
  33. externFP GetModuleHandle
  34. externFP GetProcAddress
  35. externFP GetPrivateProfileInt
  36. externFP GetPrivateProfileString
  37. externFP GetAppCompatFlags
  38. ifdef NEC_98
  39. externFP KillSystemTimer ; (ins 92.xx.xx) |
  40. externFP TickEntry1 ; (ins 92.09.25) |
  41. externFP TickEntry2 ; (ins 92.09.25) |
  42. externFP TickEntry3 ; (ins 92.09.25) |
  43. externNP INT_1AH_call ; (ins 92.xx.xx) |
  44. externNP INT_1AH_Close ; (ins 93.10.13) |
  45. externFP MSR_READ_Call ; (ins 92.xx.xx) |
  46. else ; NEC_98
  47. externFP WowCloseComPort
  48. endif ; NEC_98
  49. externNP $RECCOM
  50. externA __0040H
  51. externA __F000h
  52. externB IRQhooks
  53. IF 0
  54. externD OldIntVecIntB
  55. externD OldIntVecIntC
  56. externD OurIntVecIntB
  57. externD OurIntVecIntC
  58. ENDIF
  59. externB szMessage
  60. externB pLPTByte
  61. externB szCOMMessage
  62. externB pCOMByte
  63. externB _szTitle
  64. MULTIPLEX equ 2Fh ; multiplex interrupt number
  65. GET386API equ 1684h ; Get API entry point from VxD
  66. VPD equ 000Fh ; device ID of VPD device
  67. VPD_GETPORT equ 0004h ; function: assign port to current VM
  68. VPD_RELPORT equ 0005h ; function: release port
  69. ifdef NEC_98
  70. VPD_GETVER equ 0000h ; get version API (ins 94.02.24) |
  71. endif ; NEC_98
  72. VCD equ 000Eh ; device ID of VCD device
  73. VCD_GETVER equ 0000h ; get version API
  74. VCD_GETPORT equ 0004h ; function: assign port to current VM
  75. VCD_RELPORT equ 0005h ; function: release port
  76. VCD_STEALPORT equ 0006h
  77. VPICD equ 0003h ; device ID of VPICD device
  78. POSTMESSAGE equ 110 ; export ordinal of PostMessage()
  79. MESSAGEBOX equ 1 ; export ordinal of MessageBox()
  80. MB_TASKMODAL equ 2000h
  81. MB_YESNO equ 0004h ; messagebox flags
  82. MB_ICONEXCLAMATION equ 0030h
  83. IDYES equ 6
  84. ifdef NEC_98
  85. NULL equ 00h ; [QN] (INS 92.08.05) |
  86. BIOS_FLAG5 equ 58h ; [QN] (ins 92.11.06) |
  87. BIOS_FLAG7 equ 5bh ; [QN] (ins 92.11.06) |
  88. endif ; NEC_98
  89. createSeg _INTERRUPT,IntCode,word,public,CODE
  90. sBegin IntCode
  91. assumes cs,IntCode
  92. externFP FakeCOMIntFar
  93. externFP TimerProc
  94. externFP Control
  95. externFP COMHandler
  96. externFP APIHandler
  97. IFDEF No_DOSX_Bimodal_Services
  98. externW RM_IntDataSeg
  99. externFP RM_APIHandler
  100. externFP Entry_From_RM
  101. externD RM_CallBack
  102. ENDIF
  103. sEnd IntCode
  104. page
  105. sBegin Data
  106. externB lpCommBase
  107. externB CommBaseX
  108. externB lpCommIrq
  109. externB CommIrqX
  110. externB lpCommFifo
  111. externB CommFifoX
  112. externB lpCommDSR
  113. externB CommDSRx
  114. externB lpCommSection
  115. externB lpSYSTEMINI
  116. ;------------------------------------------------------------------------------
  117. ;
  118. ; Reserve data space for COM ports
  119. ;
  120. DefineCommX MACRO num
  121. public Comm&num
  122. Comm&num label byte
  123. db num-1
  124. .errnz DCB_Id
  125. db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; ComDCB
  126. dw 0 ; ComErr
  127. dw 0 ; Port
  128. dw 0 ; NotifyHandle
  129. dw 0 ; NotifyFlags
  130. dw -1 ; RecvTrigger
  131. dw 0 ; SendTrigger
  132. .errnz IRQhook - SendTrigger - 2
  133. db (SIZE ComDEB) - IRQhook DUP(0)
  134. .errnz $ - Comm&num - (SIZE ComDEB)
  135. Declare_PM_BIS 0,Control,COMHandler,APIHandler,_INTERRUPT,_DATA
  136. db (SIZE EBIS_Sel_Struc) * 2 DUP(0) ; res space for 2 selectors
  137. ENDM
  138. DW_OFFSET_CommX MACRO num
  139. dw DataOFFSET Comm&num
  140. ENDM
  141. ??portnum = 1
  142. REPT MAXCOM+1
  143. DefineCommX %??portnum
  144. ??portnum = ??portnum+1
  145. ENDM
  146. PUBLIC COMptrs ; table of offsets to CommX's declared above
  147. COMptrs label word
  148. ??portnum = 1
  149. REPT MAXCOM+1
  150. DW_OFFSET_CommX %??portnum
  151. ??portnum = ??portnum+1
  152. ENDM
  153. PURGE DefineCommX
  154. PURGE DW_OFFSET_CommX
  155. ;------------------------------------------------------------------------------
  156. ;
  157. ; Reserve data space for LPT ports
  158. ;
  159. DefineLPTx MACRO num
  160. public LPT&num
  161. LPT&num label byte
  162. db num-1+LPTx
  163. .errnz DCB_Id
  164. db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; xComDCB
  165. dw 0 ; xComErr
  166. dw 0 ; xPort
  167. dw 0 ; xNotifyHandle
  168. dw 0 ; xNotifyFlags
  169. dw -1 ; xRecvTrigger
  170. dw 0 ; xSendTrigger
  171. IF num LE 3
  172. dw LPTB + (num-1)*2
  173. ELSE
  174. dw 0 ; BIOSPortLoc
  175. ENDIF
  176. .errnz $-LPT&num - SIZE LptDEB
  177. ENDM
  178. ??portnum = 1
  179. REPT MAXLPT+1
  180. DefineLPTx %??portnum
  181. ??portnum = ??portnum+1
  182. ENDM
  183. PURGE DefineLPTx
  184. page
  185. PUBLIC $MachineID, Using_DPMI
  186. $MachineID db 0 ;IBM Machine ID
  187. Using_DPMI db 0 ; 0FFh, if TRUE
  188. ALIGN 2
  189. PUBLIC activeCOMs
  190. activeCOMs dw 0
  191. PUBLIC lpPostMessage, lpfnMessageBox, lpfnVPD, fVPD
  192. lpPostMessage dd 0
  193. lpfnMessageBox dd 0
  194. lpfnVPD dd 0 ; far pointer to win 386 VPD entry point
  195. lpfnVCD dd 0 ; far pointer to win 386 VCD entry point
  196. lpfnVPICD dd 0 ; far pointer to win 386 VPICD entry point
  197. ifdef NEC_98
  198. lpfnWPSVPD dd 0 ; far pointer to win 386 VPICD entry point(ins 94.02.24)|
  199. endif ; NEC_98
  200. PUBLIC VCD_int_callback
  201. VCD_int_callback df 0 ; VCD returns the address for this callback
  202. ; on every call to acquire a COM port, but
  203. ; it is always the same address, so we will
  204. ; just maintain it globally.
  205. fVPD db 0 ; 0-not checked, 1 vpd present, -1 no vpd
  206. fVCD db 0 ; 0-not checked, 1 vcd present, -1 no vcd
  207. fVPICD db 0 ; 0-not checked, 1 vpicd present, -1 no vpicd
  208. ifdef NEC_98
  209. fWPSVPD db 0 ; 0-not checked, 1 WPS present, -1 no WPS (ins 94.02.24) |
  210. endif
  211. szUser db 'USER',0
  212. default_table db 4, 3, 4, 3, 0 ; Default IRQ's (COM3 default is changed to
  213. ; 3 for PS/2's during LoadLib)
  214. IFDEF No_DOSX_Bimodal_Services
  215. RM_Call_Struc Real_Mode_Call_Struc <>
  216. ENDIF
  217. IFDEF DEBUG_TimeOut
  218. %OUT including code to display MsgBox, if closing comm with data in buffer
  219. szSendTO db 'TimedOut CloseComm with data in buffer. Retry?', 0
  220. ENDIF
  221. ifdef NEC_98
  222. ;;;;;;;************ DEB Value of Each Port ************ |
  223. ;;;;;;; |
  224. ;;;;;;; +---------------------------------------ComDCB |
  225. ;;;;;;; |+--------------------------------------ComErr |
  226. ;;;;;;; ||+-------------------------------------Port |
  227. ;;;;;;; |||+------------------------------------NotifyHandle |
  228. ;;;;;;; ||||+-----------------------------------NotifyFlag |
  229. ;;;;;;; |||||+----------------------------------RecvTrigger |
  230. ;;;;;;; ||||||+---------------------------------SendTrigger |
  231. ;;;;;;; ||||||| +----------------------------TimerProcAdr |
  232. ;;;;;;; ||||||| | +-------------------MaskFFPort |
  233. ;;;;;;; ||||||| | | +--------------ReadSigPort |
  234. ;;;;;;; ||||||| | | | +---------DataPort |
  235. ;;;;;;; ||||||| | | | | +----CommandPort |
  236. ;;;;;;; ||||||| | | | | | +--StatusPort |
  237. ;;;;;;; ||||||| | | | | | | |
  238. ;;;;;;Comm1 ComDEB <,,,,,,,TickEntry1,035h,033h,030h,032h,032h,> ;Com1 |
  239. ;;;;;;Comm2 ComDEB <,,,,,,,TickEntry2,0B0h,0B0h,0B1h,0B3h,0B3h,> ;Com2 |
  240. ;;;;;;Comm3 ComDEB <,,,,,,,TickEntry3,0B2h,0B2h,0B9h,0BBh,0BBh,> ;Com3 |
  241. ; |
  242. public Port_TBL,Port_EOI,Vect_TBL,Mask_TBL,PRN_CHAR ; |
  243. public Board_66L,Board_59,FindCOMPort ; |
  244. ; |
  245. ;************************** Data Table ************************** |
  246. ; using IRQ as 'index'.
  247. Port_TBL dw 00h,00h,00h,02h,00h,02h,02h,00h
  248. dw 00h,0ah,0ah,00h,0ah,0ah,00h,00h
  249. Port_EOI dw 00h,00h,00h,0bh,00h,0dh,0eh,00h
  250. dw 00h,11h,13h,00h,14h,15h,00h,00h
  251. Vect_TBL db 00h,00h,00h,00h,00h,00h,00h,00h
  252. db 00h,08h,08h,00h,08h,08h,00h,00h
  253. Mask_TBL db 00h,00h,00h,08h,00h,20h,40h,00h
  254. db 00h,02h,08h,00h,10h,20h,00h,00h
  255. PRN_CHAR db 0 ;Lpt Output Char Buffer |
  256. ; |
  257. Board_66L dw 0BAh ;PC-980166/L board |
  258. Board_59 dw 0BFh ;PC-980159 board |
  259. ; |
  260. out5f_flag db 0 ; ins 93.03.24 (IOrecovery) |
  261. public RECLoopCounter ; ins 93.03.31 |
  262. RECLoopCounter dw 0 ; ins 93.03.31 |
  263. endif ; NEC_98
  264. sEnd Data
  265. ROMBios segment at 0F000h
  266. org 0FFFEh
  267. MachineID label byte
  268. RomBios Ends
  269. sBegin Code
  270. assumes cs,Code
  271. assumes ds,Data
  272. page
  273. IFDEF No_DOSX_Bimodal_Services
  274. ;----------------------------Private-Routine----------------------------;
  275. ; SegmentFromSelector
  276. ;
  277. ; Converts a selector to a segment...note that this routine assumes
  278. ; the memory pointed to by the selector is below the 1Meg line!
  279. ;
  280. ; Params:
  281. ; AX = selector to convert to segment
  282. ;
  283. ; Returns:
  284. ; AX = segment of selector given
  285. ;
  286. ; Error Returns:
  287. ; None
  288. ;
  289. ; Registers Destroyed:
  290. ; CX
  291. ;
  292. ;-----------------------------------------------------------------------;
  293. assumes ds,Data
  294. assumes es,nothing
  295. public SegmentFromSelector
  296. SegmentFromSelector proc far
  297. .286
  298. push dx
  299. cCall GetSelectorBase,<ax> ;DX:AX = segment of selector
  300. shr ax, 4
  301. shl dl, 4
  302. or ah, dl ;AX now points to interrupt *segment*
  303. pop dx
  304. ret
  305. .8086
  306. SegmentFromSelector endp
  307. ENDIF
  308. page
  309. ;------------------------------------------------------------------------------
  310. ;
  311. ; Get_API_Entry
  312. ;
  313. ; entry - BX = device id
  314. ; DS:DI -> DWORD for proc address
  315. ; exit - Z flag set, if failed
  316. ;
  317. Get_API_Entry proc near
  318. push di
  319. xor di, di
  320. mov es, di
  321. mov ax, GET386API
  322. int MULTIPLEX
  323. mov ax, di
  324. pop di
  325. mov [di], ax
  326. mov [di+2], es
  327. or ax, [di+2]
  328. ret
  329. Get_API_Entry endp
  330. ;----------------------------Private-Routine----------------------------;
  331. ;
  332. ; Contention_Dlg
  333. ;
  334. ; If running under Win386, this routine can be called to ask the user to
  335. ; resolve contention for a COM or LPT port.
  336. ;
  337. ; entry - CX is offset of message string for dialog box
  338. ;
  339. ; exit - Z flag set, if user specified that Windows should steal the port
  340. Contention_Dlg proc near
  341. PUBLIC Contention_Dlg
  342. xor ax,ax
  343. push ax ; hwndOwner
  344. push ds
  345. push cx ; message ptr
  346. cmp wo lpfnMessageBox[2], 0 ;Q: ptr to MessageBox proc valid?
  347. jne short gmbp_done ; Y: we can call it
  348. push ds ; N: get module handle of USER
  349. lea ax, szUser
  350. push ax
  351. cCall GetModuleHandle
  352. push ax ; module handle
  353. mov ax, MESSAGEBOX
  354. cwd
  355. push dx
  356. push ax
  357. cCall GetProcAddress
  358. mov wo lpfnMessageBox[0], ax ; save received proc address
  359. mov wo lpfnMessageBox[2], dx
  360. gmbp_done:
  361. push ds
  362. lea ax, _szTitle
  363. push ax
  364. mov ax, MB_ICONEXCLAMATION or MB_YESNO or MB_TASKMODAL
  365. push ax
  366. cCall lpfnMessageBox
  367. cmp ax, IDYES ; user allows us to take the port?
  368. ret
  369. Contention_Dlg endp
  370. ifdef NEC_98
  371. ;---------------------------------------------------------------(ins 94.02.24) |
  372. ; WPS386 (ins 94.02.24) |
  373. ; Request ON/OFF of port trap to WPSVPD (ins 94.02.24) |
  374. ; (The function is toggled by calling WPSVPD) (ins 94.02.24) |
  375. ; (ins 94.02.24) |
  376. ; entry - DI contains offset in ROM area of port... (ins 94.02.24) |
  377. ; 8 - LPT1, A - LPT2, etc (ins 94.02.24) |
  378. ;---------------------------------------------------------------(ins 94.02.24) |
  379. WPS386 proc near ; (ins 94.02.24) |
  380. .286 ; (ins 94.02.24) |
  381. pusha ; (ins 94.02.24) |
  382. .8086 ; (ins 94.02.24) |
  383. mov di, [si.BIOSPortLoc] ; (ins 94.02.24) |
  384. sub di, LPTB ; (ins 94.02.24) |
  385. shr di, 1 ; DI into port number (ins 94.02.24) |
  386. cmp fWPSVPD, 1 ; Is there WPSVPD ? (ins 94.02.24) |
  387. je short beWPSVPD ; Y: Go Next (ins 94.02.24) |
  388. ; (ins 94.02.24) |
  389. push di ; (ins 94.02.24) |
  390. mov bx, VPD ; (ins 94.02.24) |
  391. mov di, DataOFFSET lpfnWPSVPD ; (ins 94.02.24) |
  392. call Get_API_Entry ;Is there VPD ? (ins 94.02.24) |
  393. pop di ; (ins 94.02.24) |
  394. jnz short chkWPSVPD ; Y: Go Next (ins 94.02.24) |
  395. mov fWPSVPD, -1 ; (ins 94.02.24) |
  396. jmp short WPSVPD_exit ; (ins 94.02.24) |
  397. chkWPSVPD: ; (ins 94.02.24) |
  398. push di ; (ins 94.02.24) |
  399. mov dx, VPD_GETVER ; Get VPD version (ins 94.02.24) |
  400. call [lpfnWPSVPD] ; (ins 94.02.24) |
  401. pop di ; (ins 94.02.24) |
  402. cmp ax, 030bh ; WPSVPD(=30bh)�H (ins 94.02.24) |
  403. je short insWPSVPD ; Y: Next(IS WPSVPD) (ins 94.02.24) |
  404. mov fWPSVPD, -1 ; ) (ins 94.02.24) |
  405. jne short WPSVPD_exit ; (ins 94.02.24) |
  406. insWPSVPD: ; (ins 94.02.24) |
  407. mov fWPSVPD, 1 ; There is WPSVPD (ins 94.02.24) |
  408. beWPSVPD: ; (ins 94.02.24) |
  409. xor ax, ax ; (ins 94.02.24) |
  410. mov cx, di ; Set LPT ID (ins 94.02.24) |
  411. mov dx, VPD_GETPORT ; (ins 94.02.24) |
  412. call [lpfnWPSVPD] ; Call VPD_PM_Aquire_Port(ins 94.02.24) |
  413. WPSVPD_exit: ; (ins 94.02.24) |
  414. .286 ; (ins 94.02.24) |
  415. popa ; (ins 94.02.24) |
  416. ret ; (ins 94.02.24) |
  417. .8086 ; (ins 94.02.24) |
  418. WPS386 endp ; (ins 94.02.24) |
  419. endif ; NEC_98
  420. ;----------------------------Private-Routine----------------------------;
  421. ;
  422. ; GetPort386
  423. ;
  424. ; If running under Win386, tell the VPD to assign an LPT port to us.
  425. ; The comm driver will handle contention.
  426. ;
  427. ; entry - DI contains offset in ROM area of port...
  428. ; 8 - LPT1, A - LPT2, etc
  429. ;
  430. ; exit - registers saved, carry = clear if OK to proceed, set if
  431. ; user won't allow assignment of port or Win386 error
  432. ;
  433. GetPort386 proc near
  434. public GetPort386
  435. cmp fVPD, 0
  436. jl getport_VPDNotInstalled
  437. jnz short getport_CallVPD
  438. push di
  439. mov bx, VPD
  440. mov di, DataOFFSET lpfnVPD
  441. call Get_API_Entry
  442. pop di
  443. jnz short getport_CallVPD
  444. mov fVPD, -1
  445. getport_VPDNotInstalled:
  446. clc
  447. jmp short getport_exit
  448. getport_CallVPD:
  449. mov fVPD, 1
  450. push di
  451. sub di, LPTB
  452. shr di, 1 ; turn DI into port number
  453. xor ax, ax
  454. mov dx, VPD_GETPORT
  455. mov cx, di
  456. call [lpfnVPD]
  457. jnc getport_gotit
  458. ; port owned by another VM... ask the user for it
  459. add cl, '1' ; fix up the port name...
  460. mov pLPTByte, cl ; HACK HACK HACK
  461. lea cx, szMessage
  462. call Contention_Dlg
  463. jnz getport_userwontallow
  464. mov ax, 1 ; tell win386 we really do want it
  465. mov cx, di ;
  466. mov dx, VPD_GETPORT ;
  467. call [lpfnVPD] ; return with C set or clear...
  468. jmp short getport_gotit
  469. getport_userwontallow:
  470. stc
  471. getport_gotit:
  472. pop di
  473. getport_exit:
  474. ret
  475. GetPort386 endp
  476. ;----------------------------Private-Routine----------------------------;
  477. ;
  478. ; ReleasePort386
  479. ;
  480. ; If running under Win386, tell the VPD to deassign an LPT port.
  481. ;
  482. ; entry - DS:SI -> COMDEB
  483. ;
  484. ReleasePort386 proc near
  485. cmp fVPD, 1
  486. jne release_noVPD
  487. xor cx, cx
  488. mov cl, [si.DCB_id]
  489. and cl, NOT LPTx ; clear high bit
  490. mov dx, VPD_RELPORT
  491. call [lpfnVPD]
  492. release_noVPD:
  493. ret
  494. ReleasePort386 endp
  495. ;----------------------------Private-Routine----------------------------;
  496. ;
  497. ; GetCOMport386
  498. ;
  499. ; If running under Win386, tell the VCD to assign a COM port to us.
  500. ; The comm driver will handle contention.
  501. ;
  502. ; entry - DS:SI -> COMDEB
  503. ;
  504. ; exit - registers saved, carry = clear if OK to proceed, set if
  505. ; user won't allow assignment of port or Win386 error
  506. ;
  507. .386
  508. GetCOMport386 proc near
  509. public GetCOMport386
  510. push es
  511. pushad
  512. cmp fVCD, 0
  513. jl short getcomport_VCDNotInstalled
  514. jnz short getcomport_CallVCD
  515. mov bx, VCD
  516. mov di, DataOFFSET lpfnVCD
  517. call Get_API_Entry
  518. jz short getcomport_checknoVCD
  519. mov dx, VCD_GETVER
  520. call [lpfnVCD]
  521. cmp ax, 30Ah ;Q: 3.1 or greater?
  522. jae short getcomport_CallVCD ; Y:
  523. getcomport_checknoVCD:
  524. mov fVCD, -1
  525. getcomport_VCDNotInstalled:
  526. clc
  527. jmp short getcomport_exit
  528. getcomport_CallVCD:
  529. mov fVCD, 1
  530. mov ax, 10b ; flag ring0 int handler
  531. call VCD_GetPort_API
  532. jnc short getcomport_success ; jump if acquire worked
  533. jnz short getcomport_noport ; jump if port doesn't exist
  534. ; port owned by another VM... ask the user for it
  535. mov cl, [si.DCB_id]
  536. add cl, '1' ; fix up the port name...
  537. mov pCOMByte, cl
  538. lea cx, szCOMMessage
  539. call Contention_Dlg
  540. stc
  541. jnz short getcomport_exit
  542. mov ax, 11b ; tell win386 we really do want it
  543. call VCD_GetPort_API
  544. jc short getcomport_exit
  545. getcomport_success:
  546. mov dword ptr [VCD_int_callback], edi
  547. mov word ptr [VCD_int_callback+4], cx
  548. mov [si.VCD_data], ebx
  549. xchg ax, [si.Port]
  550. or ax, ax ;Q: already had port base?
  551. jnz short getcomport_exit ; Y: don't update vector #, or FIFO
  552. mov [si.IntVecNum], dl
  553. call GetPortFlags
  554. clc
  555. getcomport_exit:
  556. popad
  557. pop es
  558. ret
  559. getcomport_noport:
  560. mov [si.Port], -1
  561. jmp getcomport_exit
  562. GetCOMport386 endp
  563. VCD_GetPort_API proc near
  564. mov dx, VCD_GETPORT
  565. xor cx, cx
  566. mov cl, [si.DCB_Id] ; cx = port #
  567. mov di, VCDflags ; offset from start of DEB
  568. call [lpfnVCD]
  569. ret
  570. VCD_GetPort_API endp
  571. .8086
  572. ;----------------------------Private-Routine----------------------------;
  573. ;
  574. ; ReleaseCOMport386
  575. ;
  576. ; If running under Win386, tell the VCD to deassign a COM port.
  577. ;
  578. ; entry - DS:SI -> COMDEB
  579. ;
  580. ReleaseCOMport386 proc near
  581. ifdef NEC_98
  582. cmp fVCD, 1
  583. jne release_noVCD
  584. xor cx, cx
  585. mov cl, [si.DCB_id]
  586. mov dx, VCD_RELPORT
  587. call [lpfnVCD]
  588. else ; NEC_98
  589. ifndef WOW
  590. cmp fVCD, 1
  591. jne release_noVCD
  592. xor cx, cx
  593. mov cl, [si.DCB_id]
  594. mov dx, VCD_RELPORT
  595. call [lpfnVCD]
  596. else
  597. xor cx, cx
  598. mov cl, [si.DCB_id]
  599. push cx
  600. call WowCloseComPort
  601. endif
  602. endif ; NEC_98
  603. release_noVCD:
  604. ret
  605. ReleaseCOMport386 endp
  606. PUBLIC StealPort
  607. StealPort proc near
  608. cmp fVCD, 1
  609. jne sp_yes
  610. mov dx, VCD_STEALPORT
  611. xor cx, cx
  612. mov cl, [si.DCB_id]
  613. call [lpfnVCD]
  614. or al, al
  615. jnz sp_yes
  616. sp_no:
  617. stc
  618. ret
  619. sp_yes:
  620. clc
  621. mov [si.VCDflags], 0
  622. ret
  623. StealPort endp
  624. page
  625. ;------------------------------------------------------------------------------
  626. ;
  627. ; ENTER: DS:SI -> ComDEB
  628. ; EXIT: AL = 0, if IRQ was unmasked, else -1, if IRQ was already masked
  629. ;
  630. MaskIRQ proc near
  631. push es
  632. push di
  633. mov di, ds
  634. mov es, di
  635. lea di, [si+SIZE ComDEB]
  636. mov ax, BIH_API_Get_Mask
  637. call APIHandler ; returns Carry Set, if masked
  638. jc short already_masked
  639. pushf
  640. mov ax, BIH_API_Mask
  641. call APIHandler ; mask IRQ
  642. xor ax, ax
  643. popf
  644. jnc short mask_exit
  645. already_masked:
  646. or al, -1
  647. mask_exit:
  648. pop di
  649. pop es
  650. ret
  651. MaskIRQ endp
  652. ;------------------------------------------------------------------------------
  653. ;
  654. ; ENTER: DS:SI -> ComDEB
  655. ;
  656. UnmaskIRQ proc near
  657. push es
  658. push di
  659. mov di, ds
  660. mov es, di
  661. lea di, [si+SIZE ComDEB]
  662. mov ax, BIH_API_Unmask
  663. call APIHandler
  664. pop di
  665. pop es
  666. ret
  667. UnmaskIRQ endp
  668. page
  669. ;----------------------------Public Routine-----------------------------;
  670. ;
  671. ; $INICOM - Initialize A Port
  672. ;
  673. ; Initalizes the requested port if present, and sets
  674. ; up the port with the given attributes when they are valid.
  675. ; This routine also initializes communications buffer control
  676. ; variables. This routine is passed the address of a device
  677. ; control block.
  678. ;
  679. ; The RLSD, CTS, and DSR signals should be ignored by all COM
  680. ; routines if the corresponding timeout values are 0.
  681. ;
  682. ; For the LPT ports, a check is performed to see if the hardware
  683. ; is present (via the LPT port addresses based at 40:8h. If the
  684. ; port is unavailable, an error is returned. If the port is
  685. ; available, then the DEB is set up for the port. $SETCOM will
  686. ; be called to set up the DEB so that there will be something
  687. ; valid to pass back to the caller when he inquires the DEB.
  688. ;
  689. ; No hardware initialization will be performed to prevent the
  690. ; RESET line from being asserted and resetting the printer every
  691. ; time this routine is called.
  692. ;
  693. ; Entry:
  694. ; EX:BX --> Device Control Block with all fields set.
  695. ; Returns:
  696. ; AX = 0 if no errors occured
  697. ; Error Returns:
  698. ; AX = initialization error code otherwise
  699. ; Registers Preserved:
  700. ; None
  701. ; Registers Destroyed:
  702. ; AX,BX,CX,DX,ES,FLAGS
  703. ; History:
  704. ;-----------------------------------------------------------------------;
  705. ;------------------------------Pseudo-Code------------------------------;
  706. ; {
  707. ; }
  708. ;-----------------------------------------------------------------------;
  709. assumes ds,Data
  710. assumes es,nothing
  711. public $INICOM
  712. $INICOM proc near
  713. push si ;As usual, save register variables
  714. push di
  715. mov ah,es:[bx.DCB_Id] ;Get device i.d.
  716. call GetDEB ;--> DEB for this device
  717. mov ax, IE_BADID ; call it a bad id (spooler uses DOS)
  718. jc InitCom15 ;Invalid device
  719. jns InitCom20 ; jmp if COM port
  720. ifndef NEC_98
  721. push ds
  722. mov di, [si.BIOSPortLoc]
  723. cmp di, LPTB
  724. jb short InitLPT_Installed
  725. mov cx,__0040H ;[rkh] ...
  726. mov ds,cx ;Point DS: at ROM Save Area.
  727. assumes ds,nothing
  728. mov ax, IE_HARDWARE
  729. mov cx, wo [di]
  730. jcxz InitCom10 ; if zero, no hardware
  731. mov ax,IE_BadID ;Show bad device
  732. cmp ch, 0 ; zero hibyte -> not valid (redir)
  733. jz InitCom10 ; call it a bad id (spooler uses DOS)
  734. cmp di, LPTB ; LPT1?
  735. jz InitLPT_Installed ; yes, must be installed
  736. cmp cx, wo [di-2] ;Q: duplicate of previous port
  737. je InitCom10 ; Y: (redirected port)
  738. InitLPT_Installed:
  739. pop ds
  740. mov [si.Port], cx
  741. endif ; NEC_98
  742. call $SETCOM
  743. ifdef NEC_98
  744. mov di, [si.BIOSPortLoc] ; (ins 93.12.19) |
  745. endif ; NEC_98
  746. call GetPort386 ; tell win386 we're using the port
  747. mov ax, IE_OPEN ; port already open (by another VM)
  748. jc InitCom15 ; error
  749. ifdef NEC_98
  750. call WPS386 ; WPS386 I/O trap ON (ins 94.02.24) |
  751. mov ah, 1 ; Check H/W environment (ins 93.10.29) |
  752. call int_1ah_call ; and set to [si.Port](ins 93.10.29) |
  753. call WPS386 ; WPS386 I/O trap OFF (ins 94.02.24) |
  754. cmp wo [si.Port], -1 ; Port = -1 ? (ins 93.12.19) |
  755. mov ax, IE_HARDWARE ; (no H/W?) (ins 93.12.19) |
  756. jne @f ; N: success (ins 93.12.19) |
  757. call ReleasePort386 ; Y: release port (ins 93.12.19) |
  758. jmp InitCom100 ; (ins 93.12.19) |
  759. @@: ; (ins 93.12.19) |
  760. endif ; NEC_98
  761. jmp InitCom90 ;That's all
  762. InitCom10:
  763. pop ds ; get DS back
  764. InitCom15:
  765. jmp InitCom100
  766. assumes ds,Data
  767. InitCom17:
  768. ifdef NEC_98
  769. mov ax, IE_OPEN ; (ins 92.08.xx) |
  770. mov dx,StatusPort[si] ;dx = StatusPort[si] (ins 92.08.xx) |
  771. NEWIODELAY 5 ;<OUT 5F,AL> (ins 94.05.11) |
  772. in al,dx ; (ins 92.08.xx) |
  773. cmp al,-1 ; (ins 92.08.xx) |
  774. jne InitCom15 ; N:return IE_OPEN (ins 92.08.xx) |
  775. jmp InitCom27 ; Y:return IE_HARDWARE(ins 92.08.xx) |
  776. else ; NEC_98
  777. mov ax, IE_OPEN
  778. cmp [si.Port], -1 ;Q: determined that port didn't exist?
  779. jne InitCom15 ; N: return IE_OPEN
  780. jmp short InitCom27 ; Y: return IE_HARDWARE
  781. endif ; NEC_98
  782. ; *** Set up serial port ***
  783. ;
  784. InitCom20:
  785. ifdef NEC_98
  786. push cx ; |
  787. push ax ; |
  788. ; |
  789. call OUT5FCheck ; (ins 93.03.24) |
  790. ; |
  791. mov cx,500 ; |
  792. mov ax, __WinFlags ; [QN][BA](ins 93.03.30) |
  793. and ax, WF_ENHANCED ; [QN][BA](ins 93.03.30) |
  794. jnz Go_EnhSET ; [QN][BA](ins 93.03.30) |
  795. ; |
  796. cmp [out5f_flag],1 ;out 5f ok ?? (ins 93.03.24) |
  797. je @f ;yes (ins 93.03.24) |
  798. mov cx,5000 ; |
  799. @@: ; |
  800. jmp short OUT5FSetEND ; |
  801. ; |
  802. Go_EnhSET: ; |
  803. cmp [out5f_flag],1 ;out 5f ok ?? (ins 93.03.24) |
  804. jne @f ;No (ins 93.03.24) |
  805. mov cx,1 ; |
  806. @@: ; |
  807. ; |
  808. OUT5FSetEND: ; |
  809. mov [RECLoopCounter] , cx ; |
  810. pop ax ; |
  811. pop cx ; |
  812. ; |
  813. mov ah,es:[bx.DCB_Id] ;Get device i.d. (ins 92.08.xx) |
  814. cmp ah,ID_COM1 ;COM1? (ins 92.08.xx) |
  815. je InitCom22 ;Yes, InitCom22 �ɔ��ԁB(ins 92.08.xx) |
  816. InitCom21: ; (ins 94.04.15) |
  817. or EFlags[si], fNoFIFO ; (ins 94.04.21) |
  818. mov dx,[Board_66L] ; (ins 92.08.xx) |
  819. in al,dx ;PC-980166/L�{�[�h (ins 92.08.xx) |
  820. cmp al,0FFH ;�ʐM�����A�_�v�^�� (ins 92.08.xx) |
  821. je @f ; (ins 94.05.19) |
  822. jmp InitCom27 ; (ins 94.05.19) |
  823. @@: ; (ins 94.05.19) |
  824. mov dx,[Board_59] ; (ins 92.08.xx) |
  825. in al,dx ;PC-980159�{�[�h (ins 92.08.xx) |
  826. cmp al,0FFH ;���������A�_�v�^�� (ins 92.08.xx) |
  827. je @f
  828. jmp InitCom27
  829. @@:
  830. mov dx,StatusPort[si] ;dx = StatusPort[si] (ins 92.08.xx) |
  831. in al,dx ; (ins 92.08.xx) |
  832. cmp al,-1 ; (ins 92.08.xx) |
  833. jne @f
  834. jmp InitCom27
  835. @@:
  836. ; |
  837. InitCom22: ; (ins 92.08.xx) |
  838. else ; NEC_98
  839. cmp [si.Port], -1 ;Q: port exists?
  840. je InitCom27 ; N: report not found
  841. endif ; NEC_98
  842. mov ax, __WinFlags
  843. test ax, WF_ENHANCED
  844. jz short @F
  845. call GetCOMport386
  846. ifdef NEC_98
  847. jc InitCom23 ; (ins 94.04.18) |
  848. jmp short @F ; (ins 94.04.18) |
  849. InitCom23: ; (ins 94.04.18) |
  850. jmp InitCom17 ; (ins 94.04.18) |
  851. @@: ; (ins 94.04.18) |
  852. mov ah,es:[bx.DCB_Id] ;Get device i.d. (mov 94.05.19) |
  853. or EFlags[si], fNoFIFO ;no AOBA on board (ins 94.05.31) |
  854. cmp ah,ID_COM1 ;COM1? (mov 94.05.19) |
  855. jne InitCom24_1 ;No, (mov 94.05.19) |
  856. mov Port[si],0 ; (mov 94.05.19) |
  857. call AOBACheck ;Check AOBA (mov 94.05.19) |
  858. FCLI ; (mov 94.05.19) |
  859. test EFlags[si], fNoFIFO ;AOBA on board ? (mov 94.05.19) |
  860. jnz InitCom24_2 ; (mov 94.05.19) |
  861. mov Port[si],130H ; (mov 94.05.19) |
  862. mov dx,Port[si] ;AOBA BASE PORT (mov 94.05.19) |
  863. add dx,ACE_FCR ; (mov 94.05.19) |
  864. in al,dx ; (mov 94.05.19) |
  865. mov preFCRShadow[si],al ;Save FCR when WIN start(ins 94.06.06) |
  866. test al,ACE_EFIFO ;FIFO mode ? (mov 94.05.19) |
  867. jz short @F ;No, 8251 mode (mov 94.05.19) |
  868. call Set8251mode ;Set 8251 mode (mov 94.05.19) |
  869. @@: ; (mov 94.05.19) |
  870. jmp short InitCom24_2 ; (mov 94.05.19) |
  871. InitCom24_1: ; (mov 94.05.19) |
  872. InitCom24_2: ; (mov 94.05.19) |
  873. ; Entry: ;(ins 92.08.xx) |
  874. ; DS:SI --> DEB ;(ins 92.08.xx) |
  875. ; CX = Port base address ;(ins 92.08.xx) |
  876. ; DS = Data ;(ins 92.08.xx) |
  877. ;(ins 92.08.xx) |
  878. call Get_PortAddr_and_INTVect ;���荞�݃x�N�^�𓾂� ;(ins 92.08.xx) |
  879. ;(ins 92.08.xx) |
  880. ; Returns: ;(ins 92.08.xx) |
  881. ; AH = IRQ number ;(ins 92.08.xx) |
  882. ; AL = 8259 Mask ;(ins 92.08.xx) |
  883. ; DI:DX --> interrupt handler ;(ins 92.08.xx) |
  884. ;(ins 92.08.xx) |
  885. inc IntVecIntCount[si] ; USE Rotate_Pic() (ins 92.08.xx) |
  886. call FindCOMPort ; (MOVE 93.03.20) |
  887. else ; NEC_98
  888. jc InitCom17
  889. @@:
  890. cmp [si.Port], 0 ;Q: already got info?
  891. jnz @F
  892. call FindCOMPort
  893. jc InitCom27 ; report not found, if error
  894. mov [si.Port], ax
  895. mov [si.IntVecNum], dl
  896. @@:
  897. endif ; NEC_98
  898. push es ;Save these registers
  899. push di
  900. push cx ;needed later for $SETCOM etc
  901. push bx
  902. mov al, [si.IntVecNum]
  903. xor ah, ah
  904. lea di, [si+SIZE ComDEB]
  905. mov [di.BIS_IRQ_Number], ax
  906. mov di, DataOFFSET IRQhooks
  907. ifdef NEC_98
  908. xor cx,cx ; [QN] (ins 92.09.xx) |
  909. mov cl, [si.DCB_Id] ; [QN] (ins 92.09.xx) |
  910. jcxz InitCom30 ; [QN] (ins 92.09.xx) |
  911. else ; NEC_98
  912. mov cx, MAXCOM+1
  913. endif ; NEC_98
  914. InitCom25:
  915. ifndef NEC_98
  916. cmp al, [di.IRQn] ;Q: hooked IRQ matches ours?
  917. je short InitCom30 ; Y:
  918. cmp [di.IRQn], 0 ;Q: end of hooked IRQ list?
  919. je short InitCom35 ; Y:
  920. endif ; NEC_98
  921. add di, SIZE IRQ_Hook_Struc ; N: check next hook
  922. loop InitCom25
  923. ifdef NEC_98
  924. jmp short InitCom30 ; [QN] (ins 92.09.xx) |
  925. endif ; NEC_98
  926. int 3 ; data structures corrupt if we
  927. ; get here, because no hook table
  928. ; entries exist and there is suppose
  929. ; to be at least 1 for each DEB
  930. InitCom26:
  931. call ReleaseCOMport386 ; give port back to 386...
  932. pop bx
  933. pop cx
  934. pop di
  935. pop es
  936. InitCom27:
  937. mov ax, IE_HARDWARE ; jump if port not available
  938. jmp InitCom100
  939. InitCom30:
  940. cmp [di.HookCnt], 0 ;Q: IRQ still hooked?
  941. je short InitCom35 ; N: rehook
  942. inc [di.HookCnt] ; Y: inc hook count
  943. mov [si.IRQhook], di ; & link DEB into list
  944. mov ax, [di.First_DEB]
  945. mov [si.NextDEB], ax
  946. mov [di.First_DEB], si
  947. jmp short InitCom40
  948. InitCom35:
  949. mov [di.IRQn], al ; hook IRQ for first time, or rehook
  950. mov [si.IRQhook], di
  951. mov [di.First_DEB], si
  952. mov [di.HookCnt], 1
  953. call MaskIRQ
  954. mov [di.OldMask], al
  955. InitCom40: ; di -> IRQ_Hook_Struc
  956. cmp [fVPICD], 0 ;Q: VPICD bimodel services available?
  957. jl short InitCom415 ; N:
  958. mov ax, ds ; Y: use them
  959. mov es, ax
  960. lea di, [si+SIZE ComDEB]
  961. mov [di.BIS_Descriptor_Count], 2
  962. mov ax, word ptr [si.QInAddr+2] ; get selector of in queue
  963. mov [di.EBIS_Sel1.EBIS_User_Mode_Sel], ax
  964. mov ax, word ptr [si.QOutAddr+2] ; get selector of out queue
  965. mov [di.EBIS_Sel2.EBIS_User_Mode_Sel], ax
  966. mov ax, VPICD_Install_Handler
  967. call [lpfnVPICD]
  968. jnc InitCom42
  969. cmp [di.OldMask], 0
  970. jne InitCom26
  971. call UnmaskIRQ
  972. jmp InitCom26
  973. InitCom42:
  974. ;
  975. ; save newly allocated selectors/segments into "Alt" queue pointers
  976. ;
  977. mov ax, [di.EBIS_Sel1.EBIS_Super_Mode_Sel]
  978. mov word ptr [si.AltQInAddr+2], ax
  979. mov ax, [di.EBIS_Sel2.EBIS_Super_Mode_Sel]
  980. mov word ptr [si.AltQOutAddr+2], ax
  981. InitCom414:
  982. jmp InitCom59
  983. InitCom415:
  984. cmp [di.VecN], 0FFh ;Q: int already hooked?
  985. IFDEF No_DOSX_Bimodal_Services
  986. jnz short InitCom52 ; Y: init RMode ptrs in BIS
  987. ELSE
  988. jnz InitCom414 ; Y:
  989. ENDIF
  990. mov al, [si.IntVecNum]
  991. add al, 8 ; 1st PIC starts at vector 8h
  992. ifndef NEC_98
  993. cmp al, 16 ;Q: 2nd PIC?
  994. jb short InitCom418 ; N:
  995. add al, 70h-16 ; Y: 2nd PIC starts at vector 70h
  996. endif ; NEC_98
  997. InitCom418:
  998. mov [di.VecN], al
  999. ; *** Set interrupt vectors ***
  1000. ;
  1001. mov ah,35h ;Get the DOS vector
  1002. int 21h ;DOS Get Vector Function
  1003. mov wo [di.OldIntVec][0], bx
  1004. mov wo [di.OldIntVec][2], es
  1005. InitCom50:
  1006. push ds ;Save original DS
  1007. mov dx, [di.HandlerOff]
  1008. mov bx, _INTERRUPT
  1009. mov ds, bx ;Interrupt handler address in ds:dx
  1010. assumes ds,nothing
  1011. mov ah, 25h ;DOS Set Vector Function
  1012. int 21h ;Set the DOS vector
  1013. pop ds ;Original DS
  1014. assumes ds,Data
  1015. IFDEF No_DOSX_Bimodal_Services
  1016. InitCom52:
  1017. cmp [Using_DPMI], 0
  1018. jz short InitCom57
  1019. mov ax, Int31_Get_Version SHL 8
  1020. int 31h
  1021. mov bl, [si.IntVecNum]
  1022. mov bh, bl
  1023. add bl, dh ; assume master PIC
  1024. sub bh, 8 ;Q: IRQ in master?
  1025. jb @f ; Y: add master's base vec
  1026. add bh, dl ; N: add slave's base vec
  1027. mov bl, bh
  1028. @@:
  1029. mov ax, Get_RM_IntVector
  1030. int 31h
  1031. mov wo [di.RM_OldIntVec][0], dx
  1032. mov wo [di.RM_OldIntVec][2], cx
  1033. mov dx, [di.RM_HandlerOff]
  1034. mov ax, _INTERRUPT
  1035. call SegmentFromSelector
  1036. mov cx, ax
  1037. push cx
  1038. mov ax, Set_RM_IntVector
  1039. int 31h
  1040. lea di, [si+SIZE ComDEB]
  1041. mov wo [di.BIS_Super_Mode_API], IntCodeOFFSET RM_APIHandler
  1042. pop cx
  1043. mov wo [di.BIS_Super_Mode_API+2], cx
  1044. ;
  1045. ; Get segment addresses for the Q's and set AltQInAddr and AltQOutAddr
  1046. ;
  1047. mov ax, wo [si.AltQInAddr+2]
  1048. call SegmentFromSelector
  1049. mov wo [si.AltQInAddr+2], ax
  1050. mov ax, wo [si.AltQOutAddr+2]
  1051. call SegmentFromSelector
  1052. mov wo [si.AltQOutAddr+2], ax
  1053. InitCom57:
  1054. ENDIF
  1055. mov ax, __WinFlags ;In Standard mode, the PIC IRQ
  1056. test al, WF_STANDARD ; priorities get rotated to favor
  1057. jz InitCom59 ; the comm ports.
  1058. call Rotate_PIC
  1059. ; *** Interrupt handler set : jump here if handler is already installed ***
  1060. ;
  1061. InitCom59:
  1062. pop bx
  1063. pop cx
  1064. pop di
  1065. pop es
  1066. ifdef NEC_98
  1067. cmp es:[bx.DCB_Id],ID_Com1 ;Is this ID Com1 ? (ins 92.08.xx)|
  1068. jne InitCom60 ;No, jump InitCom60 (ins 92.08.xx)|
  1069. mov dx,MaskFFPort[si] ;F/F Port Mask Bit (ins 92.08.xx)|
  1070. in al,dx ; (ins 92.08.xx)|
  1071. mov MaskFFShadow[si],al ;Save Old Mask bit (ins 92.08.xx)|
  1072. ; |
  1073. InitCom60: ; |
  1074. mov al,MaskFFShadow[si] ;Get 8251 INT Mask bit (ins 92.08.xx)|
  1075. and al,not(Enable_TxR or Enable_TxE or Enable_RxR) ;(ins 92.08.xx)|
  1076. mov dx,MaskFFPort[si] ;(ins 92.08.xx)|
  1077. out dx,al ;(ins 92.08.xx)|
  1078. mov MaskFFShadow[si],al ;Sasve Mask bit ;(ins 92.08.xx)|
  1079. call FlagNotActive ;(ins 92.08.xx)|
  1080. else ; NEC_98
  1081. InitCom60:
  1082. mov dx,[si.Port] ;Set comm card address
  1083. xor ax,ax ;Need a zero
  1084. inc dx ;--> Interrupt Enable Register
  1085. .errnz ACE_IER-ACE_RBR-1
  1086. out dx,al ;Turn off interrupts
  1087. call FlagNotActive
  1088. add dl,ACE_MCR-ACE_IER ;--> Modem Control Register
  1089. in al,dx
  1090. and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so
  1091. iodelay ; but tri-state IRQ line
  1092. out dx,al
  1093. endif ; NEC_98
  1094. InitCom70:
  1095. push es ;Zero queue counts and indexes
  1096. push ds
  1097. pop es
  1098. assumes es,Data
  1099. lea di,QInCount[si]
  1100. mov cx,(EFlags-QInCount)/2
  1101. .errnz (EFlags-QInCount) AND 1
  1102. xor ax,ax
  1103. cld
  1104. rep stosw
  1105. .errnz QInGet-QInCount-2
  1106. .errnz QInPut-QInGet-2
  1107. .errnz QOutCount-QInPut-2
  1108. .errnz QOutGet-QOutCount-2
  1109. .errnz QOutPut-QOutGet-2
  1110. .errnz EFlags-QOutPut-2 ;First non-queue item
  1111. pop es
  1112. assumes es,nothing
  1113. mov HSFlag[si],al ;Show no handshakes yet
  1114. mov MiscFlags[si],al ;Show not discarding
  1115. mov EvtWord[si],ax ;Show no events
  1116. mov [si.VCDflags], al
  1117. mov [si.SendTrigger], ax
  1118. dec ax
  1119. mov [si.RecvTrigger], ax
  1120. ;Call $SETCOM to perform further hardware initialization.
  1121. InitCom80:
  1122. ifndef NEC_98
  1123. sub dl,ACE_MCR-ACE_FCR ; dx -> FCR
  1124. in al, dx
  1125. iodelay
  1126. test al, ACE_FIFO_E2 ;Q: FIFO already on?
  1127. jz short @F ; N:
  1128. or EFlags[si], fFIFOpre ; Y: flag it
  1129. @@:
  1130. endif ; NEC_98
  1131. ; needs si, di, and es to be saved from the beginning of inicom
  1132. call $SETCOM ;Set up Comm Device
  1133. jnz short InitCom110 ;jump if failed
  1134. call UnmaskIRQ
  1135. and EFlags[si], fEFlagsMask ;Clear internal state
  1136. InitCom90:
  1137. xor ax,ax ;Return AX = 0 to show success
  1138. mov ComErr[si],ax ;Get rid of any bogus init error
  1139. InitCom100:
  1140. ifdef NEC_98
  1141. FSTI ; (ins 94.05.17)
  1142. endif ; NEC_98
  1143. pop di
  1144. pop si
  1145. ret
  1146. ;
  1147. ; jump to here, if call to $SETCOM failed
  1148. ;
  1149. ; DANGER! *** Call into middle of Terminate to clean things up *** DANGER!
  1150. ;
  1151. InitCom110:
  1152. push ax ;Failure, save error code
  1153. call Terminate45 ;Restore port address, int vec
  1154. pop ax ;Restore error code and exit
  1155. jmp InitCom100
  1156. $INICOM endp
  1157. page
  1158. ;----------------------------Public Routine-----------------------------;
  1159. ;
  1160. ; $TRMCOM - Terminate Communications Channel
  1161. ;
  1162. ; Wait for any outbound data to be transmitted, drop the hardware
  1163. ; handshaking lines, and disable interrupts. If the output queue
  1164. ; contained data when it was closed, an error will be returned
  1165. ;
  1166. ; LPT devices have it easy. They just need to restore the I/O port
  1167. ; address.
  1168. ;
  1169. ; Entry:
  1170. ; AH = Device ID
  1171. ; Returns:
  1172. ; AX = 0
  1173. ; Error Returns:
  1174. ; AX = 8000h if invalid device ID
  1175. ; AX = -2 if output queue timeout occured
  1176. ; Registers Destroyed:
  1177. ; AX,BX,CX,DX,ES,FLAGS
  1178. ; History:
  1179. ;-----------------------------------------------------------------------;
  1180. ;------------------------------Pseudo-Code------------------------------;
  1181. ; {
  1182. ; }
  1183. ;-----------------------------------------------------------------------;
  1184. assumes ds,Data
  1185. assumes es,nothing
  1186. public $TRMCOM
  1187. $TRMCOM proc near
  1188. push si
  1189. push di
  1190. xor cx,cx ;Show no error if LPT port
  1191. call GetDEB
  1192. jc TermCom60 ;ID is invalid, return error
  1193. js TermCom30 ;Port is a LPT port
  1194. push ax ;Save port id
  1195. or MiscFlags[si],Discard ;Show discarding serial data
  1196. mov ComErr[si],cx ;Clear error flags
  1197. mov QInCount[si],cx ;Show no chars in input queue
  1198. call $RECCOM ;Send XON if needed
  1199. ;-----------------------------------------------------------------------;
  1200. ; We have to wait for the output queue to empty. To do this,
  1201. ; a timer will be created. If no character has been transmitted
  1202. ; when the timeout occurs, then an error will be indicated and
  1203. ; the port closed anyway. If the timer cannot be created, then
  1204. ; just loop until the queue empties, which will be better than
  1205. ; discarding charatcers if there are any
  1206. ;-----------------------------------------------------------------------;
  1207. test [si.HSFlag], HHSAlwaysDown ; Q: handshaking ever up?
  1208. jnz TermCom17 ; N: skip wait loop
  1209. TermCom10:
  1210. mov cx,QOutCount[si] ;Get current queue count
  1211. jcxz TermCom20 ;No characters in queue
  1212. cCall GetSystemMsecCount
  1213. mov di, ax
  1214. TermCom15:
  1215. cmp QOutCount[si],cx ;Queue count change?
  1216. jne TermCom10 ; Yes, restart timeout
  1217. cCall GetSystemMsecCount
  1218. sub ax, di
  1219. ifdef NEC_98
  1220. cmp ax, 20000 ;Q: Timeout reached? (ins 94.06.08)
  1221. else ; NEC_98
  1222. cmp ax, Timeout * 1000 ;Q: Timeout reached?
  1223. endif ; NEC_98
  1224. jb TermCom15 ; No, keep waiting
  1225. IFDEF DEBUG_TimeOut
  1226. .286
  1227. pusha
  1228. lea cx, szSendTO
  1229. call Contention_Dlg
  1230. popa
  1231. jz TermCom10
  1232. .8086
  1233. ENDIF
  1234. TermCom17:
  1235. mov cx, TimeoutError ; Yes, show timeout error
  1236. TermCom20:
  1237. pop ax ;Restore cid
  1238. ifdef NEC_98
  1239. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.11)|
  1240. jnz @F ;Now, FIFO mode (ins 94.04.11)|
  1241. TermCom25: ; (ins 92.08.xx)|
  1242. mov dx,ReadSigPort[si] ;CI/CS/CD Signal Port (ins 94.06.08)|
  1243. in al,dx ;in al,33h (ins 94.06.08)|
  1244. test al,40h ;CS Off ? (ins 94.06.08)|
  1245. jnz @f ;y: jump (ins 94.06.08)|
  1246. ; (ins 94.06.08)|
  1247. push ax ; (ins 92.08.xx)|
  1248. push dx ; (ins 92.08.xx)|
  1249. mov dx,StatusPort[si] ;8251 status port read (ins 92.08.xx)|
  1250. in al,dx ; (ins 92.08.xx)|
  1251. ; (ins 92.08.xx)|
  1252. test al,(TX_EMP) ;tx_empty check (ins 92.08.xx)|
  1253. pop dx ; (ins 92.08.xx)|
  1254. pop ax ; (ins 92.08.xx)|
  1255. jz TermCom25 ; (ins 92.08.xx)|
  1256. @@: ; (ins 94.04.11)|
  1257. ;-------------------------------------------------------------- (ins 92.08.xx)|
  1258. ; Close process of system timer (ins 92.08.xx)|
  1259. ;-------------------------------------------------------------- (ins 92.08.xx)|
  1260. push ax ; (ins 92.08.xx)|
  1261. mov ax,hTimer[si] ; Check hTimer (ins 94.04.12)|
  1262. or ax,ax ; Is there TimerProcess?(ins 92.08.xx)|
  1263. jz NoKillTimer ; Y:(Nothing) (ins 92.08.xx)|
  1264. cCall KillSystemTimer,<ax> ; Kill system timer (ins 92.08.xx)|
  1265. mov hTimer[si] ,NULL ; Clear hTimer (ins 94.04.12)|
  1266. NoKillTimer: ; (ins 92.08.xx)|
  1267. pop ax ; (ins 92.08.xx)|
  1268. endif ; NEC_98
  1269. TermCom30:
  1270. mov dx,Port[si] ;Get port base address
  1271. call Terminate ;The real work is done here
  1272. ifndef NEC_98
  1273. mov ax,cx ;Set return code
  1274. endif ; NEC_98
  1275. TermCom60:
  1276. pop di
  1277. pop si
  1278. ret
  1279. $TRMCOM endp
  1280. page
  1281. ;----------------------------Private-Routine----------------------------;
  1282. ;
  1283. ; Terminate - Terminate Device
  1284. ;
  1285. ; Restore the port I/O address and make sure that interrupts are off
  1286. ;
  1287. ; Entry:
  1288. ; AH = Device Id.
  1289. ; DX = Device I/O port address.
  1290. ; SI --> DEB
  1291. ; Returns:
  1292. ; AX = 0
  1293. ; Error Returns:
  1294. ; AX = -1
  1295. ; Registers Destroyed:
  1296. ; AX,BX,DX,FLAGS
  1297. ; History:
  1298. ;-----------------------------------------------------------------------;
  1299. assumes ds,Data
  1300. assumes es,nothing
  1301. public Terminate ;Public for debugging
  1302. Terminate proc near
  1303. or ah,ah ;LPT port?
  1304. jns Terminate10 ; No, process COM port
  1305. .errnz LPTx-10000000b
  1306. Terminate5:
  1307. ifdef NEC_98
  1308. call WPS386 ; WPS386 I/O trap ON (ins 940224)
  1309. call INT_1AH_Close ; (ins 931027)
  1310. call WPS386 ; WPS386 I/O trap OFF (ins 940224)
  1311. endif ; NEC_98
  1312. call ReleasePort386 ; give port back to 386...
  1313. jmp Terminate50 ;That's all
  1314. ;-----------------------------------------------------------------------;
  1315. ; It is a com port!
  1316. ;
  1317. ; We delay for a bit while the last character finishes transmitting
  1318. ; Then we drop DTR and RTS, and disable the interrupt generation at
  1319. ; the 8250. Even if fRTSDisable or fDTRDisable is set, those lines
  1320. ; will be dropped when the port is closed.
  1321. ;-----------------------------------------------------------------------;
  1322. ;
  1323. ; When the OUT2 bit is reset to 0 to disable interrupts, many ports
  1324. ; generate an interrupt which can not be identified, because the the
  1325. ; interrupt ID register will not be set. To work around this hardware
  1326. ; problem we first mask the IRQ, then set the port into loopback mode
  1327. ; and output a NULL to generate a receive interrupt request. Then we
  1328. ; reset OUT2 and unmask the IRQ. This will cause the interrupt to occur
  1329. ; and the interrupt handler will be able to correctly identify the
  1330. ; interrupt as coming from the com port.
  1331. Terminate10:
  1332. ifdef NEC_98
  1333. push ax ; (ins 94.04.18) |
  1334. call FlagNotActive ; don't need to check (ins 94.04.11) |
  1335. ; on timer ticks |
  1336. pop ax ; (ins 94.04.18) |
  1337. FCLI ; (ins 94.06.06) |
  1338. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.11) |
  1339. jz AOBA_Term35 ;Now, 8251 mode (ins 94.04.11) |
  1340. ; |
  1341. ;;;;;;; begin code : process for AOBA---------------------------(ins 94.04.11) |
  1342. push ax ; |
  1343. push dx ; |
  1344. ; |
  1345. mov dx,Port[si] ; (ins 94.06.08)|
  1346. add dx,ACE_MSR ;Modem Status = 134h (ins 94.06.08)|
  1347. in al,dx ;Wait until xmit is empty (ins 94.06.08)|
  1348. out 05fh ,al ; (ins 94.06.08)|
  1349. test al,ACE_CTS ; CS = Off ? (ins 94.06.08)|
  1350. jz AOBA_Term30 ; Y; jump (ins 94.06.08)|
  1351. ; |
  1352. mov dx,Port[si] ; |
  1353. add dx,ACE_LSR ;Line Status register |
  1354. public AOBA_Term20 ; |
  1355. AOBA_Term20: ; |
  1356. in al,dx ;Wait until xmit is empty |
  1357. out 05fh ,al ; (ins 94.06.07) |
  1358. test al,ACE_THRE ; Send FIFO and CCU Send Reg All Empty |
  1359. jz AOBA_Term20 ;Not empty yet |
  1360. ; |
  1361. public AOBA_Term30 ; (ins 94.06.08)|
  1362. AOBA_Term30: ; (ins 94.06.08)|
  1363. call Set8251mode ;Change to 8251 mode |
  1364. pop dx ; |
  1365. pop ax ; |
  1366. ;;;;;;; end code : process for AOBA-----------------------------(ins 94.04.11) |
  1367. ; |
  1368. public AOBA_Term35 ; |
  1369. AOBA_Term35: ; (ins 94.04.11) |
  1370. ; |
  1371. ;;;;;;;;;;;;;;;;8251 F/F interrupt mask ; (ins 92.08.xx) |
  1372. ; (ins 92.08.xx) |
  1373. Terminate11: ; (ins 92.08.xx) |
  1374. cmp ah,ID_Com1 ; com1 ? (ins 92.08.xx) |
  1375. jne Terminate12 ; No: (ins 92.08.xx) |
  1376. mov dx,MaskFFPort[si] ; (ins 92.08.xx) |
  1377. in al,dx ; Read Port C data (ins 92.08.xx) |
  1378. mov MaskFFShadow[si],al ;Int mask data (ins 92.08.xx) |
  1379. ; Port C save (ins 92.08.xx) |
  1380. Terminate12: ; (ins 92.08.xx) |
  1381. mov dx,MaskFFPort[si] ; (ins 92.08.xx) |
  1382. mov al,MaskFFShadow[si] ; (ins 92.08.xx) |
  1383. and al,not(MSK_TXE+MSK_TXR+MSK_RXR);8251 F/F INT mask (ins 92.08.xx) |
  1384. mov MaskFFShadow[si],al ;8251 Mask data save (ins 92.08.xx) |
  1385. out dx,al ;Send mask data (ins 92.08.xx) |
  1386. ; (ins 92.08.xx) |
  1387. ;;;;;;;;;;;;;;;;;;;;8259 interrupt mask on IMR ; (ins 92.08.xx) |
  1388. ; (ins 92.08.xx) |
  1389. push bx ;Save bx (ins 92.08.xx) |
  1390. push dx ;Save dx (ins 92.08.xx) |
  1391. ; (ins 92.08.xx) |
  1392. mov dx,IMRPort[si] ;INT Mask Register Port (ins 92.08.xx) |
  1393. mov bl,Mask8259[si] ;8259 Mask bit (ins 92.08.xx) |
  1394. in al,dx ;AL=IMRPort (ins 92.08.xx) |
  1395. NEWIODELAY 1 ;<OUT 5F,AL> (ins 92.11.14) |
  1396. mov cx,ax ; (ins 92.08.xx) |
  1397. or al,bl ;Mask RS232c (ins 92.08.xx) |
  1398. out dx,al ; (ins 92.08.xx) |
  1399. NEWIODELAY 1 ;<OUT 5F,AL> (ins 92.11.14) |
  1400. pop dx ; (ins 92.08.xx) |
  1401. pop bx ; (ins 92.08.xx) |
  1402. ; (ins 92.08.xx) |
  1403. ;--------- internal reset ------------------------------- (ins 92.08.xx) |
  1404. ; (ins 92.08.xx) |
  1405. Terminate15: ; (ins 92.08.xx) |
  1406. push cx ; (ins 92.08.xx) |
  1407. push ax ; (ins 92.08.xx) |
  1408. push dx ; (ins 92.08.xx) |
  1409. mov cx,3 ; (ins 92.08.xx) |
  1410. xor ax,ax ; (ins 92.08.xx) |
  1411. ; (ins 92.08.xx) |
  1412. Terminate20: ; (ins 92.08.xx) |
  1413. mov dx,CommandPort[si] ; (ins 92.08.xx) |
  1414. out dx,al ; (ins 92.08.xx) |
  1415. NEWIODELAY 20 ;<OUT 5F,AL> (ins 92.11.14) |
  1416. loop Terminate20 ; (ins 92.08.xx) |
  1417. mov al,40h ; (ins 92.08.xx) |
  1418. out dx,al ; (ins 92.08.xx) |
  1419. pop dx ; (ins 92.08.xx) |
  1420. pop ax ; (ins 92.08.xx) |
  1421. pop cx ; (ins 92.08.xx) |
  1422. ; (ins 92.08.xx) |
  1423. Terminate30: ; (ins 94.04.15) |
  1424. else ; NEC_98
  1425. inc dx ;Disable chip interrupts
  1426. .errnz ACE_IER-ACE_RBR-1
  1427. mov al, ACE_ERBFI ; except receive
  1428. out dx,al
  1429. call FlagNotActive ; don't need to check for postmessage
  1430. ; on timer ticks
  1431. add dl,ACE_LSR-ACE_IER ;--> line status register
  1432. iodelay
  1433. Terminate20:
  1434. in al,dx ;Wait until xmit is empty
  1435. and al,ACE_THRE+ACE_TSRE
  1436. cmp al,ACE_THRE+ACE_TSRE
  1437. jne Terminate20 ;Not empty yet
  1438. Terminate30:
  1439. xor al, al
  1440. test EFlags[si], fFIFOpre ;Q: leave FIFO enabled?
  1441. jz short @F ; N:
  1442. mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO
  1443. @@:
  1444. sub dl, ACE_LSR-ACE_FCR
  1445. out dx, al
  1446. iodelay
  1447. call MaskIRQ
  1448. add dl, ACE_MCR-ACE_FCR ;--> Modem Control Register
  1449. in al,dx
  1450. iodelay
  1451. mov ah, al
  1452. or al,ACE_LOOP ; turn on loopback
  1453. out dx, al
  1454. iodelay
  1455. sub dl, ACE_MCR-ACE_THR
  1456. xor al, al
  1457. out dx, al ; output a NULL to generate an int
  1458. iodelay
  1459. add dl, ACE_LSR-ACE_THR
  1460. Terminate35:
  1461. in al,dx ;Wait until xmit is empty
  1462. and al,ACE_THRE+ACE_TSRE
  1463. cmp al,ACE_THRE+ACE_TSRE
  1464. jne Terminate35 ;Not empty yet
  1465. mov al, ah
  1466. dec dl ; now clear OUT2 and loopback
  1467. .errnz ACE_LSR-ACE_MCR-1
  1468. and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so
  1469. out dx,al ; but tri-state IRQ line
  1470. call UnmaskIRQ ; this will cause the receive int
  1471. ; to occur and be processed
  1472. sub dl, ACE_MCR-ACE_IER ; clear the receive int enable
  1473. xor al, al
  1474. out dx, al
  1475. dec dx
  1476. .errnz ACE_IER-ACE_RBR-1
  1477. call MaskIRQ
  1478. endif ; NEC_98
  1479. ;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE!
  1480. ;
  1481. ; Terminate45 is a secondary entrypoint into this routine--it's called
  1482. ; by the initialization code when that code is unable to properly init
  1483. ; a com port and needs to clean-up the mess it's made.
  1484. ;
  1485. ;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE!
  1486. Terminate45:
  1487. push cx ;Save original cx
  1488. push bx ;Save original bx
  1489. ifdef NEC_98
  1490. dec IntVecIntCount[si] ;USE Rotate_Pic() (ins 92.08.xx)
  1491. endif ; NEC_98
  1492. cmp [fVPICD], 0 ;Q: VPICD bimodel services available?
  1493. jl short @F ; N:
  1494. mov ax, ds ; Y: use them
  1495. mov es, ax
  1496. lea di, [si+SIZE ComDEB]
  1497. mov ax, VPICD_Remove_Handler
  1498. call [lpfnVPICD]
  1499. @@:
  1500. mov di, [si.IRQhook]
  1501. dec [di.HookCnt] ;Q: last port using IRQ?
  1502. jne short Terminate495 ; N: unmask IRQ again
  1503. mov al, 0FFh
  1504. xchg al, [di.VecN] ;Interrupt vector number
  1505. cmp al, 0FFh ;Q: IRQ vector hooked?
  1506. je short Terminate49 ; no...
  1507. IFDEF No_DOSX_Bimodal_Services
  1508. cmp [Using_DPMI], 0
  1509. jz short term_no_dpmi
  1510. ;
  1511. ; unhook RM vector thru DPMI for standard mode
  1512. ;
  1513. push ax
  1514. mov ax, Int31_Get_Version SHL 8
  1515. int 31h
  1516. mov bl, [si.IntVecNum]
  1517. mov bh, bl
  1518. add bl, dh ; assume master PIC
  1519. ifndef NEC_98
  1520. sub bh, 8 ;Q: IRQ in master?
  1521. jb @f ; Y: add master's base vec
  1522. add bh, dl ; N: add slave's base vec
  1523. mov bl, bh
  1524. endif ; NEC_98
  1525. @@:
  1526. mov dx, wo [di.RM_OldIntVec][0]
  1527. mov cx, wo [di.RM_OldIntVec][2]
  1528. mov ax, Set_RM_IntVector
  1529. int 31h
  1530. pop ax
  1531. term_no_dpmi:
  1532. ENDIF
  1533. mov dx, __WinFlags ;In Standard mode the PIC interrupt
  1534. test dl, WF_STANDARD ; priorities are changed to favor
  1535. jz Terminate48 ; the comm ports.
  1536. call Rotate_PIC ;This port no longer needs priority
  1537. Terminate48:
  1538. ; *** reset int vector to it's previous state
  1539. assumes ds,nothing
  1540. push ds ;Save original DS [rkh] ...
  1541. lds dx, [di.OldIntVec]
  1542. mov ah, 25h ;DOS Set Vector Function
  1543. int 21h ;Set the DOS vector
  1544. pop ds ;Original DS
  1545. assumes ds,data
  1546. ; *** interrupt vectors have been reset if needed at this point ***
  1547. ;
  1548. Terminate49:
  1549. mov cl, [di.OldMask]
  1550. ; Set the 8259 interrupt mask bit for this IRQ. Leave interrupts enabled
  1551. ; if they were already enabled when the comm port was initialized by us.
  1552. or cl, cl
  1553. jnz @f
  1554. Terminate495:
  1555. call UnmaskIRQ
  1556. @@:
  1557. xor ax, ax
  1558. xchg ax, [si.NextDEB]
  1559. cmp [di.First_DEB], si ;Q: DEB first for IRQ hook?
  1560. je short Terminate46 ; Y:
  1561. mov bx, [di.First_DEB] ; N: get first
  1562. Terminate453:
  1563. cmp [bx.NextDEB], si ;Q: does this DEB point to one terminating?
  1564. je Terminate455 ; Y:
  1565. mov bx, [bx.NextDEB] ; N: get next DEB
  1566. jmp Terminate453
  1567. Terminate455:
  1568. mov [bx.NextDEB], ax ; link previous DEB to NextDEB
  1569. jmp short Terminate47
  1570. Terminate46:
  1571. mov [di.First_DEB], ax ; point IRQ hook at NextDEB
  1572. Terminate47:
  1573. ifdef NEC_98
  1574. test EFlags[si], fNoFIFO ; (ins 94.06.06) |
  1575. jnz @F ; (ins 94.06.06) |
  1576. mov al,preFCRShadow ; (ins 94.06.06) |
  1577. and al,00000110b ;Clear FIFO buffer (ins 94.06.06) |
  1578. mov dx,Port[si] ; (ins 94.06.06) |
  1579. add dx,ACE_FCR ;FIFO control register (ins 94.06.06) |
  1580. out dx, al ; (ins 94.06.06) |
  1581. @@: ; (ins 94.04.13) |
  1582. FSTI ; (ins 94.06.06) |
  1583. endif ; NEC_98
  1584. pop bx ;Original BX
  1585. call ReleaseCOMport386 ; give port back to 386...
  1586. pop cx ;Original CX
  1587. Terminate50: ;Also called from $INICOM !
  1588. xor ax,ax ;Indicate no error
  1589. ret ;Port is closed and deallocated
  1590. Terminate endp
  1591. page
  1592. ;----------------------------Public Routine-----------------------------;
  1593. ;
  1594. ; $ENANOTIFY - Enable Event Notification
  1595. ;
  1596. ; Entry:
  1597. ; AH = Device ID
  1598. ; BX = Window handle for PostMessage
  1599. ; CX = Receive threshold
  1600. ; DX = Transmit threshold
  1601. ; Returns:
  1602. ; AX = 1, if no errors occured
  1603. ; Error Returns:
  1604. ; AX = 0
  1605. ; Registers Preserved:
  1606. ; BX,SI,DI,DS
  1607. ; Registers Destroyed:
  1608. ; AX,CX,DX,ES,FLAGS
  1609. ; History:
  1610. ;-----------------------------------------------------------------------;
  1611. ;------------------------------Pseudo-Code------------------------------;
  1612. ; {
  1613. ; }
  1614. ;-----------------------------------------------------------------------;
  1615. assumes ds,Data
  1616. assumes es,nothing
  1617. public $ENANOTIFY
  1618. $ENANOTIFY proc near
  1619. push si
  1620. call GetDEB
  1621. mov ax, 0
  1622. jc scb_exit
  1623. mov ax, cx
  1624. inc ax
  1625. jz short scb_recv_ok
  1626. cmp cx, [si.QInSize] ;Q: receive threshold reasonable?
  1627. jb short scb_recv_ok ; Y:
  1628. %OUT should we return an error, if thresholds invalid?
  1629. mov cx, [si.QInSize] ; N:
  1630. sub cx, 10
  1631. scb_recv_ok:
  1632. inc dx
  1633. jz short scb_send_ok
  1634. dec dx
  1635. cmp dx, [si.QOutSize] ;Q: receive threshold reasonable?
  1636. jb short scb_send_ok ; Y:
  1637. mov dx, [si.QOutSize] ; N:
  1638. sub dx, 10
  1639. scb_send_ok:
  1640. mov [si.NotifyHandle], bx
  1641. mov [si.NotifyFlagsHI], CN_Notify
  1642. or bx, bx ;Q: null callback?
  1643. jnz scb_save_thresholds ; N: save thresholds
  1644. or cx, -1 ; Y: zero thresholds
  1645. xor dx, dx
  1646. mov [si.NotifyFlagsHI], 0
  1647. scb_save_thresholds:
  1648. mov [si.RecvTrigger], cx
  1649. mov [si.SendTrigger], dx
  1650. or [si.NotifyFlagsHI], CN_TRANSMIT ; we don't want to send
  1651. ; a transmit trigger notification until
  1652. ; the transmit buffer has been filled
  1653. ; above the trigger level and then
  1654. ; emptied below it again!
  1655. cmp wo lpPostMessage[2], 0 ;Q: gotten addr of PostMessage yet?
  1656. jne short scb_good ; Y:
  1657. push ds ; N: get module handle of USER
  1658. lea ax, szUser
  1659. push ax
  1660. cCall GetModuleHandle
  1661. push ax ; module handle
  1662. mov ax, POSTMESSAGE
  1663. cwd
  1664. push dx
  1665. push ax
  1666. cCall GetProcAddress
  1667. mov wo lpPostMessage[0], ax ; save received proc address
  1668. mov wo lpPostMessage[2], dx
  1669. scb_good:
  1670. mov ax, 1
  1671. scb_exit:
  1672. pop si
  1673. ret
  1674. $ENANOTIFY endp
  1675. page
  1676. ;----------------------------Public Routine-----------------------------;
  1677. ;
  1678. ; $SETQUE - Set up Queue Pointers
  1679. ;
  1680. ; Sets pointers to Receive and Transmit Queues, as provided by the
  1681. ; caller, and initializes those queues to be empty.
  1682. ;
  1683. ; Queues must be set before $INICOM is called!
  1684. ;
  1685. ; Entry:
  1686. ; AH = Device ID
  1687. ; ES:BX --> Queue Definition Block
  1688. ; Returns:
  1689. ; AX = 0 if no errors occured
  1690. ; Error Returns:
  1691. ; AX = error code
  1692. ; Registers Preserved:
  1693. ; BX,DX,SI,DI,DS
  1694. ; Registers Destroyed:
  1695. ; AX,CX,ES,FLAGS
  1696. ; History:
  1697. ;-----------------------------------------------------------------------;
  1698. ;------------------------------Pseudo-Code------------------------------;
  1699. ; {
  1700. ; }
  1701. ;-----------------------------------------------------------------------;
  1702. assumes ds,Data
  1703. assumes es,nothing
  1704. public $SETQUE
  1705. $SETQUE proc near
  1706. push si ;These will be used
  1707. push di
  1708. call GetDEB ;Get DEB
  1709. jc SetQue10 ;Invalid, ignore the call
  1710. js SetQue10 ;Ignore call for LPT ports
  1711. push ds ;Set ds:si --> QDB
  1712. push es ;Set es:di --> to ComDCB.QInAddr
  1713. pop ds
  1714. assumes ds,nothing
  1715. pop es
  1716. assumes es,Data
  1717. lea di,QInAddr[si]
  1718. mov si,bx
  1719. cld
  1720. FCLI ;No one else can play with queues
  1721. movsw ; QInAddr = QueueRxAddr
  1722. movsw
  1723. .errnz QueueRxAddr
  1724. sub si, 4 ; AltQInAddr = QueueRxAddr
  1725. mov cx, 5 ; QInSize = QueueRxSize
  1726. rep movsw ; QOutAddr = QueueTxAddr
  1727. sub si, 4
  1728. mov cx, 3 ; AltQOutAddr = QueueTxAddr
  1729. rep movsw ; QOutSize = QueueTxSize
  1730. xor ax,ax ;Will do some zero filling
  1731. mov cl,(EFlags-QInCount)/2
  1732. .errnz (EFlags-QInCount) AND 0FE01h
  1733. rep stosw
  1734. FSTI
  1735. push es ;Restore the data segment
  1736. pop ds
  1737. assumes ds,Data
  1738. assumes es,nothing
  1739. SetQue10:
  1740. pop di ;Restore saved registers
  1741. pop si
  1742. ret
  1743. ; The above code made a few assumptions about how memory
  1744. ; was allocated within the structures:
  1745. .errnz AltQInAddr-QInAddr-4
  1746. .errnz (QueueRxSize-QueueRxAddr)-(QInSize-AltQInAddr)
  1747. .errnz (QueueTxAddr-QueueRxSize)-(QOutAddr-QInSize)
  1748. .errnz AltQOutAddr-QOutAddr-4
  1749. .errnz (QueueTxSize-QueueTxAddr)-(QOutSize-AltQOutAddr)
  1750. .errnz QueueRxSize-QueueRxAddr-4
  1751. .errnz QueueTxAddr-QueueRxSize-2
  1752. .errnz QueueTxSize-QueueTxAddr-4
  1753. .errnz QInSize-AltQInAddr-4
  1754. .errnz QOutAddr-QInSize-2
  1755. .errnz QOutSize-AltQOutAddr-4
  1756. .errnz QInCount-QOutSize-2
  1757. .errnz QInGet-QInCount-2
  1758. .errnz QInPut-QInGet-2
  1759. .errnz QOutCount-QInPut-2
  1760. .errnz QOutGet-QOutCount-2
  1761. .errnz QOutPut-QOutGet-2
  1762. .errnz EFlags-QOutPut-2 ;First non-queue item
  1763. $SETQUE endp
  1764. page
  1765. ;----------------------------Public Routine-----------------------------;
  1766. ;
  1767. ; $SETCOM - Set Communications parameters
  1768. ;
  1769. ; Re-initalizes the requested port if present, and sets up the
  1770. ; port with the given attributes when they are valid.
  1771. ;
  1772. ; For LPT ports, just copies whatever is given since it's ignored
  1773. ; anyway.
  1774. ;
  1775. ; Entry:
  1776. ; ES:BX --> DCB with all fields set.
  1777. ; Returns:
  1778. ; 'Z' Set if no errors occured
  1779. ; AX = 0
  1780. ; Error Returns:
  1781. ; 'Z' clear if errors occured
  1782. ; AX = initialization error code.
  1783. ; Registers Destroyed:
  1784. ; AX,BX,CX,DX,ES,FLAGS
  1785. ; History:
  1786. ;-----------------------------------------------------------------------;
  1787. ;------------------------------Pseudo-Code------------------------------;
  1788. ; {
  1789. ; }
  1790. ;-----------------------------------------------------------------------;
  1791. assumes ds,Data
  1792. assumes es,nothing
  1793. public $SETCOM
  1794. $SETCOM proc near
  1795. cld
  1796. push si
  1797. push di
  1798. mov ah,es:[bx.DCB_Id] ;Get device i.d.
  1799. call GetDEB ;Get DEB pointer in SI
  1800. mov ax,IE_BadID ;Assume unknown device
  1801. jc SetCom10 ;Invalid device, return error
  1802. jns SetCom20 ;COM port
  1803. call SetCom100 ;Copy the DCB
  1804. SetCom5:
  1805. xor ax,ax ;Show no error
  1806. SetCom10:
  1807. or ax,ax ;Set/clear 'Z'
  1808. pop di ; and exit
  1809. pop si
  1810. ret
  1811. ;-----------------------------------------------------------------------;
  1812. ; Have a comm device, check all the serial parameters to make
  1813. ; sure they are correct before moving the new DCB into our space
  1814. ; and changing the ACE parameters.
  1815. ;-----------------------------------------------------------------------;
  1816. SetCom20:
  1817. ifdef NEC_98
  1818. FCLI ; (ins 94.05.17) |
  1819. test EFlags[si], fNoFIFO ; (ins 94.04.13) |
  1820. jnz @F ;no AOBA on board (ins 94.04.13) |
  1821. call Set8251mode ;Change to 8251 mode (ins 94.04.12) |
  1822. @@: ; (ins 94.04.13) |
  1823. FSTI ; (ins 94.06.11)
  1824. endif ; NEC_98
  1825. call SetCom300 ;Baud rate valid?
  1826. jcxz SetCom10 ; No, return error
  1827. call SetCom400 ;Byte size/parity/stop bits correct?
  1828. jc SetCom10 ; No, return error
  1829. ; The parameters seem correct. Copy the DCB into our space and
  1830. ; initialize the ACE with the new parameters
  1831. ifdef NEC_98
  1832. mov dx,MaskFFPort[si] ;Disable INT from 8251 (ins 92.08.xx)|
  1833. cmp es:[bx.DCB_Id],ID_COM1 ; com1 ? (ins 92.08.xx)|
  1834. jne SetCom2001 ; no, Jump SetCom2001 (ins 92.08.xx)|
  1835. in al,dx ; Read port_c (ins 92.08.xx)|
  1836. jmp short SetCom2002 ; (ins 92.08.xx)|
  1837. ; (ins 92.08.xx)|
  1838. SetCom2001: ; (ins 92.08.xx)|
  1839. mov al,MaskFFShadow[si] ;read 8251 mask data (ins 92.08.xx)|
  1840. ; (ins 92.08.xx)|
  1841. SetCom2002: ; (ins 92.08.xx)|
  1842. and al,not(MSK_TXE+MSK_TXR+MSK_RXR) ; (ins 92.08.xx)|
  1843. mov MaskFFShadow[si],al ;write 8251 mask data (ins 92.08.xx)|
  1844. out dx,al ; (ins 92.08.xx)|
  1845. else ; NEC_98
  1846. mov dx,Port[si] ;Disable interrupts from the 8250
  1847. inc dx
  1848. .errnz ACE_IER-1
  1849. xor ax,ax
  1850. out dx,al
  1851. endif ; NEC_98
  1852. call FlagNotActive
  1853. call SetCom100 ;Copy the DCB
  1854. mov bx,si ;Set ES:BX --> DCB
  1855. ifdef NEC_98
  1856. FCLI ; (ins 94.06.11) |
  1857. endif ; NEC_98
  1858. call SetCom200 ;Get timeout masks
  1859. ifdef NEC_98
  1860. FSTI ; (ins 94.06.11)
  1861. endif ; NEC_98
  1862. xchg al,ah ;Want them in the correct registers
  1863. mov wo MSRMask[si],ax
  1864. .errnz MSRInfinite-MSRMask-1
  1865. call SetCom400 ;Get line control byte
  1866. push ax ; and save LCR value
  1867. ifndef NEC_98
  1868. inc dx ;--> LCR
  1869. inc dx
  1870. .errnz ACE_LCR-ACE_IER-2
  1871. or al,ACE_DLAB ;Want access to divisor latch
  1872. out dx,al
  1873. endif ; NEC_98
  1874. mov RxMask[si],ah ;Save Receive character mask
  1875. mov ax,di ;Get flags mask, error mask
  1876. and [si.DCB_Flags],ah ;Disable parity checking if no parity
  1877. mov ErrorMask[si],al ;Save line status error mask
  1878. call SetCom300 ;Get baud rate
  1879. ifdef NEC_98
  1880. ;-----------------------------------------------------------------------------+
  1881. ; timer set !! (ins 92.08.xx)|
  1882. ;---------------------------------------------------------------(ins 92.08.xx)|
  1883. cmp es:[bx.DCB_Id],00h ;Comm1 ? (ins 92.08.xx)|
  1884. jne SetCom21 ; No (ins 92.08.xx)|
  1885. mov al,RS_TIME_MOD ;Mode = counter2,LBS->MSB,mode2 (ins 92.08.xx)|
  1886. out TIME_CTL,al ; (8253) (priscaler) (ins 92.08.xx)|
  1887. NEWIODELAY 2 ; <OUT 5F,AL> (ins 92.11.14)|
  1888. mov ax,cx ;divisor data set (LSB) (ins 92.08.xx)|
  1889. out TIMER2,al ; '=075H' (ins 92.08.xx)|
  1890. NEWIODELAY 2 ; <OUT 5F,AL> (ins 92.11.14)|
  1891. mov al,ah ;divisor data set (MSB) (ins 92.08.xx)|
  1892. out TIMER2,al ; (ins 92.08.xx)|
  1893. ; (ins 92.08.xx)|
  1894. SetCom21: ; (ins 92.08.xx)|
  1895. mov dx,CommandPort[si] ;8251 mode Inst Addr (ins 92.08.xx)|
  1896. xor ax,ax ; (ins 92.08.xx)|
  1897. FCLI ; (ins 94.06.11)|
  1898. out dx,al ;null out (ins 92.08.xx)|
  1899. NEWIODELAY 20 ; <OUT 5F,AL> (ins 92.11.14)|
  1900. out dx,al ;null out (ins 92.08.xx)|
  1901. NEWIODELAY 20 ; <OUT 5F,AL> (ins 92.11.14)|
  1902. out dx,al ;null out (ins 92.08.xx)|
  1903. NEWIODELAY 20 ; <OUT 5F,AL> (ins 92.11.14)|
  1904. mov al,INTER_RESET ;reset (=40h) (ins 92.08.xx)|
  1905. out dx,al ; (ins 92.08.xx)|
  1906. pop ax ;Get Mode Inst (8251) (ins 92.08.xx)|
  1907. NEWIODELAY 20 ; <OUT 5F,AL> (ins 92.11.14)|
  1908. out dx,al ;mode set (ins 92.08.xx)|
  1909. FSTI ; (ins 94.06.11)|
  1910. ;-------------------------------------------------------------------------- |
  1911. ; relative DTR, RTS to FRTSDisable & FDTRDisable |
  1912. ; for hardware handshake !? |
  1913. ;-------------------------------------------------------------------------- |
  1914. ;NOW,DCB_Flags is 8250's format !! |
  1915. mov al,[si.DCB_Flags] ;Align DTR/RTS disable flags for 8251 |
  1916. mov ah,al ; |
  1917. and al,FRTSDisable ;= 00000010b ______. |
  1918. and ah,FDTRDisable ;= 10000000b ______I___________. |
  1919. shl al,1 ; I I |
  1920. shl al,1 ; 8251 mode (7)(6)(5)(4)(3)(2)(1)(0) |
  1921. shl al,1 ; I I I I |
  1922. shl al,1 ; RTS ____I RX_E __I I I |
  1923. rol ah,1 ; DTR ______I TX_E |
  1924. rol ah,1 ; |
  1925. or al,ah ; |
  1926. mov cl,al ; |
  1927. or al,RX_E+TX_E ;add the tx.disable and rx.disable |
  1928. xor al,DTR+RTS ; Enable = "On" |
  1929. FCLI ; (ins 94.06.11)|
  1930. out dx,al ;NOW,DCB_Flags is 8251's format !! |
  1931. FSTI ; (ins 94.06.11)|
  1932. mov CommandShadow[si],al ;Save Command |
  1933. else ; NEC_98
  1934. sub dl,ACE_LCR-ACE_DLL ;--> LSB of divisor latch
  1935. mov al,cl
  1936. out dx,al
  1937. mov al,ch
  1938. inc dx ;--> MSB of divisor latch
  1939. .errnz ACE_DLM-ACE_DLL-1
  1940. iodelay
  1941. out dx,al
  1942. inc dx ;--> LCR and clear divisor access bit
  1943. inc dx
  1944. .errnz ACE_LCR-ACE_DLM-2
  1945. pop ax
  1946. out dx,al
  1947. inc dx ;--> Modem Control Register
  1948. .errnz ACE_MCR-ACE_LCR-1
  1949. endif ; NEC_98
  1950. ;-----------------------------------------------------------------------;
  1951. ; Compute initial state of DTR and RTS. If they have been disabled,
  1952. ; then do not raise them, and disallow being used as a handshaking
  1953. ; line. Also compute the bits to use as hardware handshake bits
  1954. ; (DTR and/or RTS as indicated, qualified with the disabled flags).
  1955. ;-----------------------------------------------------------------------;
  1956. mov al,[si.DCB_Flags] ;Align DTR/RTS disable flags for 8250
  1957. and al,fRTSDisable+fDTRDisable
  1958. rol al,1 ;d0 = DTR, d2 = RTS (1 = disabled)
  1959. shr al,1 ;'C'= DTR, d1 = RTS
  1960. adc al,0 ;d0 = DTR, d1 = RTS
  1961. .errnz fRTSDisable-00000010b
  1962. .errnz fDTRDisable-10000000b
  1963. .errnz ACE_DTR-00000001b
  1964. .errnz ACE_RTS-00000010b
  1965. mov ah,al ;Save disable mask
  1966. ifndef NEC_98
  1967. xor al,ACE_DTR+ACE_RTS+ACE_OUT2
  1968. out dx,al ;Set Modem Control Register
  1969. endif ; NEC_98
  1970. mov al,[si.DCB_Flags2] ;Get hardware handshake flags
  1971. rol al,1 ;Align flags as needed
  1972. rol al,1
  1973. rol al,1
  1974. and al,ACE_DTR+ACE_RTS ;Mask bits of interest
  1975. not ah ;Want inverse of disable mask
  1976. and al,ah ;al = bits to handshake with
  1977. mov HHSLines[si],al ;Save for interrupt code
  1978. .errnz fDTRFlow-00100000b
  1979. .errnz fRTSFlow-01000000b
  1980. .errnz ACE_DTR-00000001b
  1981. .errnz ACE_RTS-00000010b
  1982. mov al,[si.DCB_Flags] ;Compute the mask for the output
  1983. shl al,1 ; hardware handshake lines
  1984. and al,ACE_DSR+ACE_CTS
  1985. mov OutHHSLines[si],al
  1986. .errnz fOutXCTSFlow-00001000b
  1987. .errnz fOutXDSRFlow-00010000b
  1988. .errnz ACE_CTS-00010000b
  1989. .errnz ACE_DSR-00100000b
  1990. ; Compute the queue count where XOff should be issued (or hardware
  1991. ; lines dropped). This will prevent having to do it at interrupt
  1992. ; time.
  1993. mov ax,QInSize[si] ;Get where they want it
  1994. sub ax,[si.DCB_XoffLim] ; and compute queue count
  1995. mov XOffPoint[si],ax
  1996. ifdef NEC_98
  1997. FSTI ; (ins:94.06.11) |
  1998. test EFlags[si], fNoFIFO ; |
  1999. jnz SetCom21_NO_AOBA ; no AOBA on board |
  2000. ; (ins 94.04.11) |
  2001. ; Enable FIFO if possible when baudrate >= 1200 (ins 94.04.11) |
  2002. mov dx,Port[si] ; (ins 94.04.11) |
  2003. add dx,ACE_FCR ; (ins 94.04.11) |
  2004. ; (ins 94.04.11) |
  2005. mov ax, [si.DCB_BaudRate] ; (ins 94.04.11) |
  2006. cmp ah, -1 ;Q: baudrate index? (ins 94.04.11) |
  2007. jne sc_fifo ; N: baudrate >= 1200, enable FIFO |
  2008. sc_fifo: ; (ins 94.04.11) |
  2009. or [si. AOBA_flag],fFIFO_Mode ; (ins 94.04.14) |
  2010. mov al, ACE_TRIG04 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO;(ins 94.06.07) |
  2011. out dx, al ; attempt to enable FIFO(ins 94.06.07) |
  2012. test EFlags[si], fFIFOchkd ;Q: FIFO detect been done? ; |
  2013. jnz sc_fifodone ; Y: enabled FIFO (ins 94.04.11) |
  2014. or EFlags[si], fFIFOchkd ; (ins 94.04.11) |
  2015. jmp short sc_fifodone ; (ins 94.05.12) |
  2016. sc_nofifo: ; (ins 94.04.11) |
  2017. jmp short SetCom21_NO_AOBA ; (ins 94.05.24) |
  2018. sc_fifodone: ; (ins 94.04.11) |
  2019. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.15) |
  2020. jz SetCom21_NO_AOBA ; (ins 94.04.15) |
  2021. mov dx,Port[si] ; (ins 94.04.11) |
  2022. add dx,ACE_MSR ;--> Modem Status reg (ins 94.04.11) |
  2023. in al,dx ;Throw away 1st status read |
  2024. NEWIODELAY 2 ; <OUT 5F,AL> (ins 94.04.18) |
  2025. in al,dx ;Save 2nd for MSRWait (Clear MSR int) |
  2026. call Set8251mode ;Change to 8251 mode (ins 94.05.12) |
  2027. FSTI ; (ins 94.06.09) |
  2028. call MSR_READ_Call ;AOBA-bug ins 94.11.19 KBNES |
  2029. jmp short @f ; (ins 94.04.11) |
  2030. SetCom21_NO_AOBA: ; (ins 94.04.11) |
  2031. FSTI ; (ins 94.06.09) |
  2032. and [si.AOBA_flag],not(fFIFO_Mode) ; (mov 94.05.24) |
  2033. call MSR_READ_Call ; [QN] (ins 92.08.05) |
  2034. @@: ; (ins 94.04.11) |
  2035. else ; NEC_98
  2036. ; Enable FIFO if possible when baudrate >= 4800
  2037. ;
  2038. sub dl,ACE_MCR - ACE_FCR ; dx = FCR
  2039. test EFlags[si], fNoFIFO ;Q: FIFO can be enabled?
  2040. jnz sc_nofifo ; N:
  2041. mov ax, [si.DCB_BaudRate]
  2042. cmp ax, 4800
  2043. jb sc_nofifo
  2044. cmp ah, -1 ;Q: baudrate index?
  2045. jne sc_fifo ; N: baudrate >= 4800, enable FIFO
  2046. cmp ax, CBR_4800
  2047. jb sc_nofifo
  2048. %OUT this isn't correct, if lower baudrates are assigned indices above CBR_4800
  2049. sc_fifo:
  2050. mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO
  2051. out dx, al ; attempt to enable FIFO
  2052. test EFlags[si], fFIFOchkd ;Q: FIFO detect been done?
  2053. jnz sc_fifodone ; Y: enabled FIFO
  2054. iodelay
  2055. .errnz ACE_IIDR-ACE_FCR
  2056. in al, dx
  2057. or EFlags[si], fFIFOchkd
  2058. test al, ACE_FIFO_E2 ;Q: FIFO enabled?
  2059. jz short @F
  2060. test al, ACE_FIFO_E1 ;Q: 16550A detected?
  2061. jnz sc_fifodone ; Y: enabled FIFO
  2062. @@:
  2063. iodelay
  2064. or EFlags[si], fNoFIFO
  2065. sc_nofifo:
  2066. xor al, al
  2067. out dx, al
  2068. sc_fifodone:
  2069. sub dl,ACE_FCR-ACE_RBR ; dx -> RBR
  2070. ;
  2071. ; Delay for things to settle
  2072. ;
  2073. push dx
  2074. cCall GetSystemMsecCount
  2075. pop dx
  2076. mov cx, ax
  2077. delay_loop:
  2078. in al, dx ;Read it once
  2079. push dx
  2080. cCall GetSystemMsecCount
  2081. pop dx
  2082. sub ax, cx
  2083. cmp ax, DELAY_TIME ;Q: Timeout reached?
  2084. ifndef WOW
  2085. jb delay_loop ; N:
  2086. endif
  2087. add dl,ACE_MSR ;--> Modem Status reg
  2088. in al,dx ;Throw away 1st status read
  2089. iodelay
  2090. in al,dx ;Save 2nd for MSRWait (Clear MSR int)
  2091. endif ; NEC_98
  2092. mov MSRShadow[si],al
  2093. ; Win 3.0 didn't check hardware handshaking until the line status changed.
  2094. ; Allow some apps to keep that behavior.
  2095. push dx
  2096. xor ax, ax
  2097. cCall GetAppCompatFlags,<ax>
  2098. pop dx
  2099. test ax, GACF_DELAYHWHNDSHAKECHK
  2100. jnz short sc_HHSup
  2101. ;
  2102. ; HACK FOR SOME MODEMS: apparently some modems set CTS, but don't set DSR
  2103. ; which means that COMM.DRV won't send if the app specifies that hardware
  2104. ; handshaking is based on CTS & DSR being set.
  2105. ;
  2106. mov ah,OutHHSLines[si]
  2107. mov al, MSRShadow[si]
  2108. and al,ah ;Only leave bits of interest
  2109. cmp al, ah ;Q: handshaking lines ok?
  2110. je short sc_HHSup ; Y:
  2111. cmp ah, ACE_CTS OR ACE_DSR ;Q: app looking for both high?
  2112. jne short sc_HHSdown ; N: skip hack
  2113. test [si.EFlags], fUseDSR ;Q: DSR is always significant?
  2114. jnz short sc_HHSdown ; Y: skip hack
  2115. cmp al, ACE_CTS ;Q: DSR low & CTS high
  2116. jne short sc_HHSdown ; N: skip hack
  2117. and ah, NOT ACE_DSR ; Y: ignore DSR line
  2118. mov OutHHSLines[si], ah
  2119. jmp short sc_HHSup
  2120. sc_HHSdown:
  2121. or [si.HSFlag], HHSDown OR HHSAlwaysDown ; flag handshaking down
  2122. sc_HHSup:
  2123. ;-----------------------------------------------------------------------;
  2124. ; Now, at last, interrupts can be enabled. Don't enable the
  2125. ; transmitter empty interrupt. It will be enabled by the first
  2126. ; call to KickTx.
  2127. ;-----------------------------------------------------------------------;
  2128. ifndef NEC_98
  2129. sub dl,ACE_MSR-ACE_IER ;--> Interrupt Enable Register
  2130. endif ; NEC_98
  2131. ; flag port as being active
  2132. push cx
  2133. mov cl, [si.DCB_Id]
  2134. mov ax, 1
  2135. shl ax, cl
  2136. or [activeCOMs], ax
  2137. pop cx
  2138. ifdef NEC_98
  2139. FCLI ; (ins 94.06.09)|
  2140. mov dx,MaskFFPort[si] ;port c address (ins 92.08.xx)|
  2141. cmp [si.DCB_id],ID_COM1 ; (ins 92.08.xx)|
  2142. jne SetCom3001 ; no (ins 92.08.xx)|
  2143. in al,dx ; (ins 92.08.xx)|
  2144. jmp short SetCom3002 ; (ins 92.08.xx)|
  2145. ; (ins 92.08.xx)|
  2146. SetCom3001: ; (ins 92.08.xx)|
  2147. mov al,MaskFFShadow[si] ;Read 8251 mask data (ins 92.08.xx)|
  2148. ; (ins 92.08.xx)|
  2149. SetCom3002: ; (ins 92.08.xx)|
  2150. or al,MSK_RXR ;receive int enable (ins 92.08.xx)|
  2151. out dx,al ; (ins 92.08.xx)|
  2152. mov MaskFFShadow[si],al ;Write 8251 mask data (ins 92.08.xx)|
  2153. FSTI ; (ins 94.06.09)|
  2154. ; (ins 92.08.xx)|
  2155. ;---------------------------------------------------------------(ins 92.08.xx)|
  2156. ; Close process of system timer (ins 92.08.xx)|
  2157. ;---------------------------------------------------------------(ins 92.08.xx)|
  2158. push ax ; (ins 92.08.xx)|
  2159. mov ax,hTimer[si] ; Check hTimer (ins 94.04.12)|
  2160. or ax,ax ; TimerProcess Nothing? (ins 92.08.xx)|
  2161. jz SetNoKillTimer ; Y:(Nothing) (ins 92.08.xx)|
  2162. cCall KillSystemTimer,<ax> ; Kill Syatem Timer (ins 92.08.xx)|
  2163. mov hTimer[si] ,00h ; Clear hTimer (ins 94.04.12)|
  2164. SetNoKillTimer: ; (ins 92.08.xx)|
  2165. ; (ins 92.08.xx)|
  2166. ;---------------------------------------------------------------(ins 92.08.xx)|
  2167. ; make process of system timer (ins 92.08.xx)|
  2168. ;---------------------------------------------------------------(ins 92.08.xx)|
  2169. test DCB_Flags[si],fOutXCTSFlow or fOutXDSRFlow ; (ins 92.08.xx)|
  2170. ; HHS Enable ? (ins 92.08.xx)|
  2171. jz SetCom3003 ; No: No Set Timer (ins 92.08.xx)|
  2172. mov ax, 200 ; create 200msec timer (ins 92.08.xx)|
  2173. push ax ; (ins 92.08.xx)|
  2174. mov ax, _INTERRUPT ; (ins 92.08.xx)|
  2175. push ax ; (ins 92.08.xx)|
  2176. mov ax,TimerProcAdr[si] ;--> timer processor (ins 92.08.xx)|
  2177. push ax ; (ins 92.08.xx)|
  2178. call CreateSystemTimer ; ax = 0, if failed (ins 92.08.xx)|
  2179. mov hTimer[si] ,ax ; Get hTimer (ins 94.04.12)|
  2180. ; (ins 92.08.xx)|
  2181. SetCom3003: ; (ins 92.08.xx)|
  2182. pop ax ; (ins 92.08.xx)|
  2183. ; (ins 92.08.xx)|
  2184. FCLI ; (ins 94.06.09)|
  2185. test [si.AOBA_flag],fFIFO_Mode ; (ins 94.04.15)|
  2186. jz @F ; (ins 94.04.15)|
  2187. call Set8251Mode ;FIFODisable (ins 94.05.16)|
  2188. mov dx,Port[si] ; (ins 94.04.13)|
  2189. add dx,ACE_FCR ; (ins 94.04.13)|
  2190. mov al,FIFO_Set_Buf_Clr ; (ins 94.04.15)|
  2191. out dx,al ; (ins 94.04.13)|
  2192. @@: ; (ins 94.05.12)|
  2193. else ; NEC_98
  2194. mov al,ACE_ERBFI+ACE_ELSI+ACE_EDSSI
  2195. FCLI
  2196. out dx,al ;Enable interrupts.
  2197. add dl,ACE_LSR-ACE_IER ;--> Line Status Register
  2198. iodelay
  2199. in al,dx ;Clear any Line Status interrupt
  2200. sub dl,ACE_LSR ;--> Receiver Buffer Register
  2201. iodelay
  2202. in al,dx ;Clear any Received Data interrupt
  2203. endif ; NEC_98
  2204. FSTI
  2205. jmp SetCom5 ;All done
  2206. $SETCOM endp
  2207. page
  2208. FlagNotActive proc near
  2209. push cx
  2210. mov cl, [si.DCB_Id]
  2211. mov ax, NOT 1
  2212. rol ax, cl
  2213. and [activeCOMs], ax
  2214. pop cx
  2215. ret
  2216. FlagNotActive endp
  2217. ;----------------------------Private-Routine----------------------------;
  2218. ;
  2219. ; SetCom100
  2220. ;
  2221. ; Copy the given DCB into the appropriate DEB. The check has
  2222. ; already been made to determine that the ID was valid, so
  2223. ; that check can be skipped.
  2224. ;
  2225. ; Entry:
  2226. ; ES:BX --> DCB
  2227. ; DS:SI --> DEB
  2228. ; Returns:
  2229. ; DS:SI --> DEB
  2230. ; ES = Data
  2231. ; Error Returns:
  2232. ; None
  2233. ; Registers Destroyed:
  2234. ; AX,CX,ES,DI,FLAGS
  2235. ; History:
  2236. ;-----------------------------------------------------------------------;
  2237. ;------------------------------Pseudo-Code------------------------------;
  2238. ; {
  2239. ; }
  2240. ;-----------------------------------------------------------------------;
  2241. assumes ds,Data
  2242. assumes es,nothing
  2243. SetCom100 proc near
  2244. push si ;Save DEB pointer
  2245. mov di,si
  2246. mov si,bx
  2247. push es
  2248. mov ax,ds
  2249. pop ds
  2250. assumes ds,nothing
  2251. mov es,ax
  2252. assumes es,Data
  2253. mov cx,DCBSize
  2254. cld
  2255. rep movsb
  2256. mov ds,ax
  2257. assumes ds,Data
  2258. pop si ;Restore DEB pointer
  2259. ret
  2260. SetCom100 endp
  2261. page
  2262. ;----------------------------Private-Routine----------------------------;
  2263. ;
  2264. ; SetCom200
  2265. ;
  2266. ; Based on whether or not a timeout has been specified for each
  2267. ; signal, set up a mask byte which is used to mask off lines for
  2268. ; which we wish to detect timeouts. 0 indicates that the line is
  2269. ; to be ignored.
  2270. ;
  2271. ; Also set up a mask to indicate those lines which are set for
  2272. ; infinite timeout. 1 indicates that the line has infinite
  2273. ; timeout.
  2274. ;
  2275. ; Entry:
  2276. ; ES:BX --> DCB
  2277. ; Returns:
  2278. ; ES:BX --> DCB
  2279. ; AH = lines to check
  2280. ; AL = lines with infinite timeout
  2281. ; Error Returns:
  2282. ; None
  2283. ; Registers Destroyed:
  2284. ; AX,CX,FLAGS
  2285. ; History:
  2286. ;-----------------------------------------------------------------------;
  2287. ;------------------------------Pseudo-Code------------------------------;
  2288. ; {
  2289. ; }
  2290. ;-----------------------------------------------------------------------;
  2291. assumes ds,Data
  2292. assumes es,nothing
  2293. SetCom200 proc near
  2294. xor ax,ax
  2295. xor cx,cx ;Get mask of lines with timeout = 0
  2296. call SetCom210
  2297. not al ;Invert result to get lines to check
  2298. and al,ACE_CTS+ACE_DSR+ACE_RLSD
  2299. xchg ah,al
  2300. dec cx ;Get mask of infinite timeouts
  2301. SetCom210:
  2302. cmp es:[bx.DCB_RlsTimeout],cx ;Timeout set to passed value?
  2303. jne SetCom220 ; No
  2304. or al,ACE_RLSD ; Yes, show checking line
  2305. SetCom220:
  2306. cmp es:[bx.DCB_CtsTimeout],cx ;Timeout set to passed value?
  2307. jne SetCom230 ; No
  2308. or al,ACE_CTS ; Yes, show checking line
  2309. SetCom230:
  2310. cmp es:[bx.DCB_DsrTimeout],cx ;Timeout set to passed value?
  2311. jne SetCom240 ; No
  2312. or al,ACE_DSR ; Yes, show checking line
  2313. SetCom240:
  2314. ret
  2315. SetCom200 endp
  2316. page
  2317. ;----------------------------Private-Routine----------------------------;
  2318. ;
  2319. ; SetCom300
  2320. ;
  2321. ; Calculate the correct baudrate divisor for the comm chip.
  2322. ;
  2323. ; Note that the baudrate is allowed to be any integer in the
  2324. ; range 2-19200. The divisor is computed as 115,200/baudrate.
  2325. ;
  2326. ; Entry:
  2327. ; ES:BX --> DCB
  2328. ; Returns:
  2329. ; ES:BX --> DCB
  2330. ; CX = baudrate
  2331. ; Error Returns:
  2332. ; CX = 0 if error
  2333. ; AX = error code if invalid baud rate
  2334. ; Registers Destroyed:
  2335. ; AX,CX,FLAGS
  2336. ; History:
  2337. ;-----------------------------------------------------------------------;
  2338. ifdef NEC_98
  2339. ; If 110bps [QN] (ins 92.08.xx)
  2340. ; *16 10M 1396 [QN] (ins 92.08.xx)
  2341. ; 8M 1135 [QN] (ins 92.08.xx)
  2342. ; *64 10M 349 [QN] (ins 92.08.xx)
  2343. ; 8M 284 [QN] (ins 92.08.xx)
  2344. BaudRateByIndexTable label word ;; (93.04.12)
  2345. dw 110 ; CBR_110 ;; (93.04.12)
  2346. dw 300 ; CBR_300 ;; (93.04.12)
  2347. dw 600 ; CBR_600 ;; (93.04.12)
  2348. dw 1200 ; CBR_1200 ;; (93.04.12)
  2349. dw 2400 ; CBR_2400 ;; (93.04.12)
  2350. dw 4800 ; CBR_4800 ;; (93.04.12)
  2351. dw 9600 ; CBR_9600 ;; (93.04.12)
  2352. dw 14400 ; CBR_14400 ;; (93.04.12)
  2353. dw 19200 ; CBR_19200 ;; (93.04.12)
  2354. dw 0 ; 0FF19h (reserved) ;; (93.04.12)
  2355. dw 0 ; 0FF1Ah (reserved) ;; (93.04.12)
  2356. dw 38400 ; CBR_38400 (reserved) ;; (93.04.12)
  2357. dw 0 ; 0FF1Ch (reserved) ;; (93.04.12)
  2358. dw 0 ; 0FF1Dh (reserved) ;; (93.04.12)
  2359. dw 0 ; 0FF1Eh (reserved) ;; (93.04.12)
  2360. dw 56000 ; CBR_56000 (reserved) ;; (93.04.12)
  2361. else ; NEC_98
  2362. BaudRateByIndexTable label word
  2363. dw 1047 ; CBR_110
  2364. dw 384 ; CBR_300
  2365. dw 192 ; CBR_600
  2366. dw 96 ; CBR_1200
  2367. dw 48 ; CBR_2400
  2368. dw 24 ; CBR_4800
  2369. dw 12 ; CBR_9600
  2370. dw 9 ; CBR_14400
  2371. dw 6 ; CBR_19200
  2372. dw 0 ; 0FF19h (reserved)
  2373. dw 0 ; 0FF1Ah (reserved)
  2374. dw 3 ; CBR_38400
  2375. dw 0 ; 0FF1Ch (reserved)
  2376. dw 0 ; 0FF1Dh (reserved)
  2377. dw 0 ; 0FF1Eh (reserved)
  2378. dw 2 ; CBR_56000
  2379. endif ; NEC_98
  2380. assumes ds,Data
  2381. assumes es,nothing
  2382. SetCom300 proc near
  2383. ifdef NEC_98
  2384. push dx ; (ins 92.08.05)|
  2385. mov dx,13 ;base value of div for 8MHz(ins 92.08.05)|
  2386. ; (ins 92.08.05)|
  2387. mov ax,40h ; (ins 92.08.05)|
  2388. push ds ; (ins 92.08.05)|
  2389. mov ds,ax ;DS <- 40H (ins 92.08.05)|
  2390. test byte ptr ds:[101h],80h ;clock late check (ins 92.08.05)|
  2391. pop ds ; (ins 92.08.05)|
  2392. jnz SetCom328 ;= 1 -> 8MHz (ins 92.08.05)|
  2393. ; |
  2394. ;In the case of 5MHz ----------------(93.03.02)-----------------(ins 93.03.02)|
  2395. xor dx,dx ; (ins 93.03.02)|
  2396. SetCom310: ; (ins 93.03.02)|
  2397. mov ax,es:DCB_BaudRate[bx] ;Save data (ins 93.03.02)|
  2398. ; (ins 93.03.02)|
  2399. cmp ax, CBR_110 ;as an index? (ins 93.04.12)
  2400. jnae not_index5 ; (ins 93.04.12)
  2401. cmp ax, CBR_19200 ; (ins 93.04.12)
  2402. ja not_index5 ; (ins 93.04.12)
  2403. cmp ax, CBR_14400 ; (ins 93.04.12)
  2404. je not_index5 ; (ins 93.04.12)
  2405. push bx ; (ins 93.04.12)
  2406. mov bx, ax ; (ins 93.04.12)
  2407. sub bx, CBR_110 ; (ins 93.04.12)
  2408. shl bx, 1 ; (ins 93.04.12)
  2409. mov ax, cs:[bx+BaudRateByIndexTable]; (ins 93.04.12)
  2410. pop bx ; (ins 93.04.12)
  2411. not_index5: ; (ins 93.04.12)
  2412. cmp ax,19200 ;baudrate=75-19200bps? (ins 93.03.02)|
  2413. ja SetCom330 ; No , go to SetCom330 (ins 93.03.02)|
  2414. ; (ins 93.03.02)|
  2415. cmp ax,110 ;baudrate=110 bps? (ins 93.03.02)|
  2416. je SetCom335 ;Yes, go to SetCom335 (ins 93.03.02)|
  2417. xor cx,cx ; (ins 93.03.02)|
  2418. mov cx,75 ; (ins 93.03.02)|
  2419. div cx ;dx:ax/75=ax dx(mod) (ins 93.03.02)|
  2420. cmp dx,0 ;Good data ? (ins 93.03.02)|
  2421. jne SetCom330 ; No! (ins 93.03.02)|
  2422. cmp ax,0 ;Good data ? (ins 93.03.02)|
  2423. je SetCom330 ; No,dx:ax = 0 (?!) (ins 93.03.02)|
  2424. ; (ins 93.03.02)|
  2425. ; It is good data!!! ; (ins 93.03.02)|
  2426. SetCom320: ; (ins 93.03.02)|
  2427. mov dx,8 ;base value of div for 5MHz(ins 93.03.02)|
  2428. mov cl,7 ; (ins 93.03.02)|
  2429. shl ax,cl ;if 19200, the most high bit is 1.(ins 93.03.02)|
  2430. SetCom327: ; (ins 93.03.02)|
  2431. shl ax,1 ; (ins 93.03.02)|
  2432. jc SetCom340 ;OK,go to return !! (ins 93.03.02)|
  2433. shl dx,1 ; (ins 93.03.02)|
  2434. jmp short SetCom327 ; (ins 93.03.02)|
  2435. ; (ins 93.03.02)|
  2436. SetCom328: ;In the case of 8MHz---(ins 93.03.02)-----------(ins 93.03.02)|
  2437. mov ax,es:DCB_BaudRate[bx] ;Save data (ins 93.03.02)|
  2438. cmp ax, CBR_110 ;as an index? (ins 93.04.12)
  2439. jnae not_index8 ; (ins 93.04.12)
  2440. cmp ax, CBR_9600 ; (ins 93.04.12)
  2441. ja not_index8 ; (ins 93.04.12)
  2442. cmp ax, CBR_14400 ; (ins 93.04.12)
  2443. je not_index8 ; (ins 93.04.12)
  2444. push bx ; (ins 93.04.12)
  2445. mov bx, ax ; (ins 93.04.12)
  2446. sub bx, CBR_110 ; (ins 93.04.12)
  2447. shl bx, 1 ; (ins 93.04.12)
  2448. mov ax, cs:[bx+BaudRateByIndexTable]; (ins 93.04.12)
  2449. pop bx ; (ins 93.04.12)
  2450. not_index8: ; (ins 93.04.12)
  2451. cmp ax,9600 ;baudrate=75-9600bps? (ins 93.03.02)|
  2452. ja SetCom330 ; No , go to SetCom330 (ins 93.03.02)|
  2453. cmp ax,110 ;baudrate=110 bps? (ins 93.03.02)|
  2454. je SetCom335 ;Yes, go to SetCom335 (ins 93.03.02)|
  2455. mov cl,75 ; (ins 93.03.02)|
  2456. div cl ;ax/75=al ah(mod) (ins 93.03.02)|
  2457. cmp ah,0 ;Good data ? (ins 93.03.02)|
  2458. jne SetCom330 ; No! (ins 93.03.02)|
  2459. cmp al,0 ;Good data ? (ins 93.03.02)|
  2460. je SetCom330 ; No,ax = 0 (?!) (ins 93.03.02)|
  2461. ; (ins 93.03.02)|
  2462. ; It is good data!!! ; (ins 93.03.02)|
  2463. SetCom329: ; (ins 93.03.02)|
  2464. shl al,1 ; (ins 93.03.02)|
  2465. jc SetCom340 ; (ins 93.03.02)|
  2466. shl dx,1 ; (ins 93.03.02)|
  2467. jmp short SetCom329 ; (ins 93.03.02)|
  2468. ; (ins 93.03.02)|
  2469. ;-------(end 93.03.02)----------------------------------------- (ins 93.03.02)|
  2470. SetCom330: ; (ins 92.08.05)|
  2471. xor cx,cx ; (ins 92.08.05)|
  2472. mov ax,IE_Baudrate ;Show Unsupported BaudRate(ins 92.08.05)|
  2473. pop dx ; (ins 92.08.05)|
  2474. ret ; (ins 92.08.05)|
  2475. ; (ins 92.08.05)|
  2476. SetCom335: ;for 110bps (ins 92.08.05)|
  2477. cmp dx,13 ;8MHz ? (ins 92.08.05)|
  2478. je SetCom338 ; (ins 92.08.05)|
  2479. mov cx,1396 ;Save timer value for 110bps(ins 92.08.05)|
  2480. jmp short SetCom339 ; (ins 92.08.05)|
  2481. SetCom338: ; (ins 92.08.05)|
  2482. mov cx,1135 ;Save timer value for 110bps(ins 92.08.05)|
  2483. SetCom339: ; (ins 92.08.05)|
  2484. pop dx ; (ins 92.08.05)|
  2485. ret ; (ins 92.08.05)|
  2486. SetCom340: ; (ins 92.08.05)|
  2487. mov cx,dx ;Save result (ins 92.08.05)|
  2488. pop dx ; (ins 92.08.05)|
  2489. ret ; (ins 92.08.05)|
  2490. else ; NEC_98
  2491. push dx
  2492. mov cx,es:[bx.DCB_BaudRate] ;Get requested baud rate
  2493. xor ax,ax ;Assume error
  2494. cmp cx, CBR_110 ;Q: baudrate specified as an index?
  2495. jae by_index
  2496. cmp cx,2 ;Within valid range?
  2497. jnae SetCom310 ; No, return error
  2498. mov dx,1 ;(dx:ax) = 115,200
  2499. mov ax,0C200h
  2500. div cx ;(ax) = 115,200/baud
  2501. SetCom310:
  2502. mov cx,ax ;(cx) = baud rate, or error code (0)
  2503. mov ax,IE_Baudrate ;Set error code incase bad baud
  2504. pop dx
  2505. ret
  2506. by_index:
  2507. cmp cx, CBR_56000 ;Q: above supported?
  2508. ja SetCom310 ; Y: return error
  2509. push bx
  2510. mov bx, cx
  2511. sub bx, CBR_110
  2512. shl bx, 1
  2513. mov ax, cs:[bx+BaudRateByIndexTable] ; get divisor
  2514. pop bx
  2515. jmp SetCom310 ; Y: return error
  2516. endif ; NEC_98
  2517. SetCom300 endp
  2518. page
  2519. ;----------------------------Private-Routine----------------------------;
  2520. ;
  2521. ; SetCom400
  2522. ;
  2523. ; Check the line configuration (Parity, Stop bits, Byte size)
  2524. ;
  2525. ; Entry:
  2526. ; ES:BX --> DCB
  2527. ; Returns:
  2528. ; ES:BX --> DCB
  2529. ; 'C' clear if OK
  2530. ; AL = Line Control Register
  2531. ; AH = RxMask
  2532. ; DI[15:8] = Flags mask (to remove parity checking)
  2533. ; DI[7:0] = Error mask (to remove parity error)
  2534. ; Error Returns:
  2535. ; 'C' set if error
  2536. ; AX = error code
  2537. ; Registers Destroyed:
  2538. ; AX,CX,DI,FLAGS
  2539. ; History:
  2540. ;-----------------------------------------------------------------------;
  2541. ;------------------------------Pseudo-Code------------------------------;
  2542. ; {
  2543. ; }
  2544. ;-----------------------------------------------------------------------;
  2545. assumes ds,Data
  2546. assumes es,nothing
  2547. SetCom400 proc near
  2548. ifdef NEC_98
  2549. assumes es,nothing
  2550. ;[QN](ins 92.08.xx)---------------------------------------------------------+
  2551. ; [QN]|
  2552. ; (Parity, Stop bits, Byte size) Check Signal Status [QN]|
  2553. ; [QN]|
  2554. ; Entry: es:bx --> DCB [QN]|
  2555. ; [QN]|
  2556. ; Exit: es:bx --> DCB [QN]|
  2557. ; 'C' clear if OK [QN]|
  2558. ; al = 8251 Mode instruction [QN]|
  2559. ; ah = RxMask [QN]|
  2560. ; di[15:8] = Flags mask (to remove parity checking) [QN]|
  2561. ; di[7:0] = Error mask (to remove parity error) [QN]|
  2562. ; 'C' set if error [QN]|
  2563. ; ax = error code [QN]|
  2564. ; [QN]|
  2565. ; Uses: ax,cx,di,flags [QN]|
  2566. ; [QN]|
  2567. ; 8251 mode instruction format [QN]|
  2568. ; (7) (6) (5) (4) (3) (2) (1) (0) [QN]|
  2569. ; <-------> <-------> <-------> <-------> [QN]|
  2570. ; stop bit parity bit byte size clock(x16)=10b [QN]|
  2571. ; 0 0 <----------------- none [QN]|
  2572. ; 0 1 <----------------- 1 [QN]|
  2573. ; 1 0 <----------------- 1.5 [QN]|
  2574. ; 1 1 <----------------- 2 [QN]|
  2575. ; 0 <------------------ odd parity [QN]|
  2576. ; 1 <------------------ even parity [QN]|
  2577. ; 0 <----------------- parity disable [QN]|
  2578. ; 1 <----------------- parity enable [QN]|
  2579. ; 0 0 <--------- 5 bit [QN]|
  2580. ; 0 1 <--------- 6 bit [QN]|
  2581. ; 1 0 <--------- 7 bit [QN]|
  2582. ; 1 1 <--------- 8 bit [QN]|
  2583. ; 0 0 <-sync [QN]|
  2584. ; 0 1 <-async x1 [QN]|
  2585. ; 1 0 <-async x16 [QN]|
  2586. ; 1 1 <-async x64 [QN]|
  2587. ; ins 92.08.05 [QN]|
  2588. ;-----------------------------------------------------------------------[QN]|
  2589. mov ax,wo es:[bx.DCB_ByteSize] ;al=byte size, ah=parity [QN]|
  2590. mov ah,es:DCB_Parity[bx] ;ah =parity [QN]|
  2591. cmp ah,2 ;Is parity incorrect ? [QN]|
  2592. ja SetCom470 ; Yes, return error [QN]|
  2593. mov di,0FF00h+ACE_OR+ACE_PE+ACE_FE+ACE_BI; [QN]|
  2594. ;ACE_OR(overrun err) [QN]|
  2595. ;ACE_PE(parity err) [QN]|
  2596. ;ACE_FE(framing err) [QN]|
  2597. ;ACE_BI(break interrupt) [QN]|
  2598. ; [QN]|
  2599. or ah,ah ;non-parity ? [QN]|
  2600. jnz SetCom410 ; No, It has parity. [QN]|
  2601. xor di,(fParity*256)+ACE_PE ; [QN]|
  2602. ;Don't check parity [QN]|
  2603. SetCom410: ; [QN]|
  2604. cmp al,8 ;byte size = 8 Bit ? [QN]|
  2605. ja SetCom460 ;If bytesize > 8 Bit , error!! [QN]|
  2606. cmp al,5 ;If bytesize < 5 Bit [QN]|
  2607. jc SetCom460 ; , Error!! [QN]|
  2608. SetCom420: ; [QN]|
  2609. sub al,5 ;Shift byte size to bit1&0 [QN]|
  2610. ; [QN]|
  2611. add ah,ah ;Map parity to ACE bits [QN]|
  2612. jz SetCom430 ;0=>0, 1=>1, 2=>3, 3=>5, 4=>7 [QN]|
  2613. dec ah ; [QN]|
  2614. ; [QN]|
  2615. SetCom430: ; [QN]|
  2616. shl ax,1 ;Align with 8251 parity bits [QN]|
  2617. shl ax,1 ; [QN]|
  2618. shl ah,1 ; [QN]|
  2619. shl ah,1 ; [QN]|
  2620. or al,ah ;Add to byte size [QN]|
  2621. ; [QN]|
  2622. mov ah,es:[bx.DCB_StopBits] ;Get # of stop bits 0=1,1/2= .GT.1 [QN]|
  2623. cmp ah,3 ;Is it out of area ? [QN]|
  2624. jnc SetCom470 ; Yes, Return Error [QN]|
  2625. inc ah ; stop1 = 00h [QN]|
  2626. ror ah,1 ; stop1.5 = 01h [QN]|
  2627. ror ah,1 ; stop2 = 10h [QN]|
  2628. ; [QN]|
  2629. SetCom440: ; [QN]|
  2630. or al,ah ; [QN]|
  2631. or al,00000010b ;clock late (x16) set [QN]|
  2632. else ; NEC_98
  2633. mov ax,wo es:[bx.DCB_ByteSize] ;al = byte size, ah = parity
  2634. cmp ah,SpaceParity ;Parity out of range?
  2635. ja SetCom470 ; Yes, return error
  2636. mov di,0FF00h+ACE_OR+ACE_PE+ACE_FE+ACE_BI
  2637. or ah,ah ;Is parity "NONE"?
  2638. jnz SetCom410 ; No, something is there for parity
  2639. xor di,(fParity*256)+ACE_PE ;Disable parity checking
  2640. SetCom410:
  2641. cmp al,8 ;Byte size out of range?
  2642. ja SetCom460 ; Yes, error
  2643. SetCom420:
  2644. sub al,5 ;Shift byte size to bits 0&1
  2645. .errnz ACE_WLS-00000011b ;Word length must be these bits
  2646. jc SetCom460 ;Byte size is illegal, return error
  2647. add ah,ah ;Map parity to ACE bits
  2648. jz SetCom430 ;0=>0, 1=>1, 2=>3, 3=>5, 4=>7
  2649. dec ah
  2650. SetCom430:
  2651. shl ah,1 ;Align with 8250 parity bits
  2652. shl ah,1
  2653. shl ah,1
  2654. or al,ah ;Add to byte size
  2655. .errnz NoParity-0
  2656. .errnz OddParity-1
  2657. .errnz EvenParity-2
  2658. .errnz MarkParity-3
  2659. .errnz SpaceParity-4
  2660. .errnz ACE_PEN-00001000b
  2661. .errnz ACE_PSB-00110000b
  2662. .errnz ACE_EPS-00010000b
  2663. .errnz ACE_SP-00100000b
  2664. or al,ACE_2SB ;Assume 2 stop bits
  2665. mov ah,es:[bx.DCB_StopBits] ;Get # of stop bits 0=1,1/2= .GT. 1
  2666. or ah,ah ;Out of range?
  2667. js SetCom470 ; Yes, return error
  2668. jz SetCom440 ;One stop bit
  2669. sub ah,2
  2670. jz SetCom450 ;Two stop bits
  2671. jns SetCom470 ;Not 1.5, return error
  2672. test al,ACE_WLS ;1.5 stop bits, 5 bit words?
  2673. jnz SetCom470 ; No, illegal
  2674. .errnz OneStopBit-0
  2675. .errnz One5StopBits-1
  2676. .errnz TwoStopBits-2
  2677. .errnz ACE_5BW
  2678. SetCom440:
  2679. and al,NOT ACE_2SB ;Show 1 (or 1.5) stop bit(s)
  2680. endif ; NEC_98
  2681. ; From the byte size, get a mask to be used for stripping
  2682. ; off unused bits as the characters are received.
  2683. SetCom450:
  2684. push dx
  2685. mov cl,es:[bx.DCB_ByteSize] ;Get data byte size
  2686. mov dx,00FFh ;Turn into mask by shifting bits
  2687. shl dx,cl
  2688. mov ah,dh ;Return mask in ah
  2689. pop dx
  2690. clc ;Show all is fine
  2691. ret
  2692. SetCom460:
  2693. mov ax,IE_ByteSize ;Show byte size is wrong
  2694. stc ;Show error
  2695. ret
  2696. SetCom470:
  2697. mov ax,IE_Default ;Show something is wrong
  2698. stc ;Show error
  2699. ret
  2700. SetCom400 endp
  2701. page
  2702. ;----------------------------------------------------------------------------
  2703. ; SuspendOpenCommPorts:
  2704. ;
  2705. ; This routine is called from 286 Winoldaps to simply deinstall the comm port
  2706. ; hooks.
  2707. ;----------------------------------------------------------------------------
  2708. cProc SuspendOpenCommPorts,<FAR,PUBLIC,PASCAL>
  2709. cBegin nogen
  2710. assumes cs,Code
  2711. assumes ds,Data
  2712. %OUT not masking IRQ's
  2713. ; Nothing to do under 3.1!
  2714. ret
  2715. cEnd nogen
  2716. ;----------------------------------------------------------------------------;
  2717. ; ReactivateOpenCommPorts: ;
  2718. ; ;
  2719. ; This routine reinstalls the comm hooks in real mode and reads the 8250 ;
  2720. ; data and status registers to clear pending interrupts. ;
  2721. ;----------------------------------------------------------------------------;
  2722. cProc ReactivateOpenCommPorts,<FAR,PASCAL,PUBLIC>,<si,di>
  2723. cBegin
  2724. call Rotate_PIC ;make comm ports highest priority
  2725. mov cx, MAXCOM+1
  2726. mov di,dataOffset COMptrs
  2727. rcp_loop:
  2728. mov si, [di]
  2729. mov dx, Port[si]
  2730. or dx, dx
  2731. jz @f
  2732. call InitAPort ;read comm port regs to clr pending ints
  2733. @@:
  2734. add di, 2
  2735. loop rcp_loop
  2736. cEnd
  2737. ;----------------------------------------------------------------------------;
  2738. ; InitAPort: ;
  2739. ; ;
  2740. ; reads the data,status & IIR registers of a port (has to be 8250!) ;
  2741. ; ;
  2742. ; If the port has an out queue pending, then this woutine will also start ;
  2743. ; the transmit process by faking a comm interrupt. ;
  2744. ;----------------------------------------------------------------------------;
  2745. public InitAPort
  2746. InitAPort proc near
  2747. ifdef NEC_98
  2748. cmp IntVecNum[si],0 ; [QN] (ins 92.08.05)
  2749. je InitAPort1 ; [QN] (ins 92.08.05)
  2750. mov dx,DataPort[si] ; [QN] (ins 92.08.05)
  2751. in al,dx ; [QN] (ins 92.08.05)
  2752. else ; NEC_98
  2753. add dl,ACE_RBR ;dx=receive buffer register
  2754. in al,dx ;read the data port
  2755. jmp short $+2 ;i/o delay
  2756. add dl,ACE_LSR - ACE_RBR ;get to the status port
  2757. in al,dx ;read it too.
  2758. jmp short $+2 ;i/o delay
  2759. add dl,ACE_IIDR - ACE_LSR ;get to the line status register
  2760. in al,dx ;read it once more
  2761. jmp short $+2 ;i/o delay
  2762. add dl,ACE_MSR - ACE_IIDR ;get to the modem status register
  2763. in al,dx ;read it once more
  2764. jmp short $+2 ;i/o delay
  2765. add dl,ACE_RBR - ACE_MSR ;get to the receive buffer register
  2766. in al,dx ;read it once more
  2767. jmp short $+2 ;i/o delay
  2768. endif ; NEC_98
  2769. call UnmaskIRQ
  2770. ; now if the port has characters pending to be sent out then we must fake a
  2771. ; comm interrupt.
  2772. cmp [si].QOutCount,0 ;characters pending to be sent ?
  2773. jz @f ;no.
  2774. FCLI ;disable interrupts
  2775. call FakeCOMIntFar ;fake an interrupt
  2776. FSTI ;renable interrupts
  2777. @@:
  2778. ifdef NEC_98
  2779. InitAPort1: ;(ins 92.08.xx)
  2780. endif ; NEC_98
  2781. ret
  2782. InitAPort endp
  2783. page
  2784. ;----------------------------Public Routine-----------------------------;
  2785. ;
  2786. ; $DCBPtr - Return Pointer To DCB
  2787. ;
  2788. ; Returns a long pointer to the DCB for the requested device.
  2789. ;
  2790. ; Entry:
  2791. ; AH = Device ID
  2792. ; Returns:
  2793. ; DX:AX = pointer to DCB.
  2794. ; Error Returns:
  2795. ; DX:AX = 0
  2796. ; Registers Preserved:
  2797. ; SI,DI,DS
  2798. ; Registers Destroyed:
  2799. ; BX,CX,ES,FLAGS
  2800. ; History:
  2801. ;-----------------------------------------------------------------------;
  2802. ;------------------------------Pseudo-Code------------------------------;
  2803. ; {
  2804. ; }
  2805. ;-----------------------------------------------------------------------;
  2806. assumes ds,Data
  2807. assumes es,nothing
  2808. public $DCBPTR
  2809. $DCBPTR proc near
  2810. push si
  2811. xor dx,dx
  2812. call GetDEB ;Get pointer to DEB
  2813. mov ax,dx
  2814. jc DCBPtr10 ;Jump if invalid device
  2815. mov ax,si ;else return value here
  2816. mov dx,ds
  2817. DCBPtr10:
  2818. pop si
  2819. ret
  2820. $DCBPTR endp
  2821. page
  2822. ;----------------------------Private-Routine----------------------------;
  2823. ;
  2824. ; GetDEB - Get Pointer To Device's DEB
  2825. ;
  2826. ; Returns a pointer to appropriate DEB, based on device number.
  2827. ;
  2828. ; Entry:
  2829. ; AH = cid
  2830. ; Returns:
  2831. ; 'C' clear
  2832. ; 'S' set if LPT device
  2833. ; DS:SI --> DEB is valid cid
  2834. ; AH = cid
  2835. ; Error Returns:
  2836. ; 'C' set if error (cid is invalid)
  2837. ; AX = 8000h
  2838. ; Registers Preserved:
  2839. ; BX,CX,DX,DI,DS,ES
  2840. ; Registers Destroyed:
  2841. ; AX,SI,FLAGS
  2842. ; History:
  2843. ;-----------------------------------------------------------------------;
  2844. ;------------------------------Pseudo-Code------------------------------;
  2845. ; {
  2846. ; }
  2847. ;-----------------------------------------------------------------------;
  2848. assumes ds,Data
  2849. assumes es,nothing
  2850. public GetDEB ;Public for debugging
  2851. GetDEB proc near
  2852. push cx
  2853. mov cl, ah
  2854. and cx, (NOT LPTx AND 0FFh)
  2855. test ah, ah ;Q: LPT id?
  2856. js short GetDEB10 ; Y:
  2857. .errnz LPTx - 80h
  2858. cmp ah, MAXCOM ;Q: Within range?
  2859. ja GetDEB30 ; N: return invalid ID
  2860. shl cx, 1
  2861. mov si, cx
  2862. mov si, [si+COMptrs]
  2863. jmp short GetDEB20
  2864. GetDEB10:
  2865. cmp ah, LPTx+MAXLPT ;Q: Within range?
  2866. ja GetDEB30 ; N: return invalid ID
  2867. ifdef NEC_98
  2868. cmp ah, ID_LPT1 ; (ins 940115)
  2869. je @f ; (ins 940115)
  2870. ; (ins 940125)
  2871. ; Don't guarantee Ex board on Highreso mode. (ins 940125)
  2872. ; So return ID error if the request is LPT2/3. (ins 940125)
  2873. ; (ins 940125)
  2874. ; 40H:[101H] bit3 (ins 940125)
  2875. ; =0 : Normal mode (ins 940125)
  2876. ; =1 : Highreso mode (ins 940125)
  2877. push ax ; (ins 940125)
  2878. push ds ; (ins 940125)
  2879. mov ax,40H ; (ins 940125)
  2880. mov ds,ax ; (ins 940125)
  2881. test by ds:[101H],00001000b ; normal mode ? (ins 940125)
  2882. pop ds ; (ins 940125)
  2883. pop ax ; (ins 940125)
  2884. jz NormalRez ; Y: Next Check (ins 940125)
  2885. jmp short GetDEB30 ; N: return invalid ID (ins 940125)
  2886. NormalRez: ; (ins 940125)
  2887. push ax ; Check whether request (ins 940115)
  2888. push dx ; LPT2/3 without Ex board(ins 940115)
  2889. mov dx, Toki_ControlStatus+400h ; (ins 940115)
  2890. in al, dx ; (ins 940115)
  2891. cmp al, 0ffh ; Is there Ex board ? (ins 940115)
  2892. pop dx ; (ins 940115)
  2893. pop ax ; (ins 940115)
  2894. je GetDEB30 ; N: Error (ins 940115)
  2895. @@: ; Y: Next (ins 940115)
  2896. ; (ins 931225)
  2897. cmp ah, ID_LPT3 ; Open LPT3 ? (ins 931225)
  2898. jne @f ; N: NEXT (ins 931225)
  2899. push dx ; (ins 931225)
  2900. push ax ; (ins 931225)
  2901. mov dx, 54fh ; (ins 931225)
  2902. in al, dx ; (ins 931225)
  2903. test al, 00000100b ; Ex board=LPT1/2 ? (ins 931225)
  2904. pop ax ; (ins 931225)
  2905. pop dx ; (ins 931225)
  2906. jz GetDEB30 ; Y: error (ins 931225)
  2907. @@: ;
  2908. endif ; NEC_98
  2909. mov si, DataOFFSET LPT1
  2910. jcxz GetDEB20
  2911. GetDEB15:
  2912. add si, SIZE LptDEB
  2913. loop GetDEB15
  2914. GetDEB20:
  2915. pop cx
  2916. or ah, ah ; clear Carry & set S, if LPT port
  2917. ret
  2918. GetDEB30:
  2919. pop cx
  2920. mov ax,8000h ;Set error code
  2921. stc ;Set 'C' to show error
  2922. ret
  2923. GetDEB endp
  2924. page
  2925. CvtHex proc near
  2926. ; assume DS=SS
  2927. ifndef NEC_98
  2928. push si
  2929. mov cl, 4
  2930. mov si, di
  2931. xor dx, dx
  2932. cld
  2933. ch_lp:
  2934. lodsb
  2935. sub al, '0' ;Q: char < '0'
  2936. jb ch_exit ; Y: return
  2937. cmp al, 9 ;Q: char <= '9'
  2938. jbe ch_got_digit ; Y: move digit into result
  2939. sub al, 'A' - '0' ;Q: char < 'A'
  2940. jb ch_exit ; Y: return
  2941. add al, 10
  2942. cmp al, 15 ;Q: char <= 'F'
  2943. jbe ch_got_digit ; Y: move hex char into result
  2944. sub al, 10 + 'a' - 'A' ;Q: char < 'a'
  2945. jb ch_exit ; Y: return
  2946. add al, 10
  2947. cmp al, 15 ;Q: char > 'f'
  2948. ja ch_exit ; Y: return
  2949. ch_got_digit:
  2950. shl dx, cl
  2951. or dl, al
  2952. jmp ch_lp
  2953. ch_exit:
  2954. mov ax, dx
  2955. pop si
  2956. endif ; NEC_98
  2957. ret
  2958. CvtHex endp
  2959. .286
  2960. ; attempt to read base from SYSTEM.INI
  2961. GetComBase proc near
  2962. push ds ; save our DS
  2963. sub sp, 6
  2964. mov di, sp
  2965. mov byte ptr ss:[di], 0
  2966. push ds
  2967. push DataOFFSET lpCommSection
  2968. push ds
  2969. push DataOFFSET lpCommBase
  2970. push ss ; temp buffer
  2971. push di
  2972. push ss ; default = temp buffer
  2973. push di
  2974. push 5
  2975. push ds
  2976. push DataOFFSET lpSYSTEMINI
  2977. mov cx, ss ; temporarily assign DS=SS
  2978. mov ds, cx ; to allow KERNEL to thunk
  2979. assumes ds,nothing
  2980. call GetPrivateProfileString ; our segment in real mode
  2981. or ax, ax
  2982. jz short gcb_exit
  2983. call CvtHex ; DS still equal to SS
  2984. gcb_exit:
  2985. add sp, 6
  2986. pop ds ; restore our DS
  2987. assumes ds,Data
  2988. ret
  2989. GetComBase endp
  2990. GetPortIRQ proc near
  2991. push ds ; save our DS
  2992. push ds
  2993. push DataOFFSET lpCommSection
  2994. push ds
  2995. push DataOFFSET lpCommIrq
  2996. push bx
  2997. mov bl, [si.DCB_Id]
  2998. cmp bl, 4
  2999. jb @f
  3000. mov bl, 4
  3001. @@:
  3002. xor bh, bh
  3003. mov bl, [bx+default_table]
  3004. mov cx, bx
  3005. pop bx
  3006. push cx ; default
  3007. push ds
  3008. push DataOFFSET lpSYSTEMINI
  3009. mov cx, ss ; temporarily assign DS=SS
  3010. mov ds, cx ; to allow KERNEL to thunk
  3011. assumes ds,nothing
  3012. call GetPrivateProfileInt ; our segment in real mode
  3013. pop ds ; restore our DS
  3014. assumes ds,Data
  3015. ret
  3016. GetPortIRQ endp
  3017. GetPortFlags proc near
  3018. mov al, [si.DCB_Id]
  3019. .erre MAXCOM LT 9 ;only single digit port numbers supported
  3020. add al, '1'
  3021. mov [CommFIFOX], al
  3022. mov [CommDSRx], al
  3023. call GetPortFIFO
  3024. call GetPortDSR
  3025. ret
  3026. GetPortFlags endp
  3027. GetPortFIFO proc near
  3028. push ds ; save our DS
  3029. push ds
  3030. push DataOFFSET lpCommSection
  3031. push ds
  3032. push DataOFFSET lpCommFifo
  3033. push 2
  3034. push ds
  3035. push DataOFFSET lpSYSTEMINI
  3036. mov cx, ss ; temporarily assign DS=SS
  3037. mov ds, cx ; to allow KERNEL to thunk
  3038. assumes ds,nothing
  3039. call GetPrivateProfileInt ; our segment in real mode
  3040. pop ds ; restore our DS
  3041. assumes ds,Data
  3042. cmp ax, 1
  3043. ja short gpf_exit ; just check at open
  3044. jb short gpf_no_fifo ; force OFF, if = 0
  3045. or EFlags[si], fFIFOchkd ; flag as checked, to force ON
  3046. jmp short gpf_exit
  3047. gpf_no_fifo:
  3048. or EFlags[si], fNoFIFO OR fFIFOchkd ; force OFF
  3049. gpf_exit:
  3050. ret
  3051. GetPortFIFO endp
  3052. GetPortDSR proc near
  3053. push ds ; save our DS
  3054. push ds
  3055. push DataOFFSET lpCommSection
  3056. push ds
  3057. push DataOFFSET lpCommDSR
  3058. push 0
  3059. push ds
  3060. push DataOFFSET lpSYSTEMINI
  3061. mov cx, ss ; temporarily assign DS=SS
  3062. mov ds, cx ; to allow KERNEL to thunk
  3063. assumes ds,nothing
  3064. call GetPrivateProfileInt ; our segment in real mode
  3065. pop ds ; restore our DS
  3066. assumes ds,Data
  3067. or ax, ax
  3068. jz short gpd_exit
  3069. or EFlags[si], fUseDSR
  3070. gpd_exit:
  3071. ret
  3072. GetPortDSR endp
  3073. ; FindCOMPort
  3074. ;
  3075. ; DS:SI -> DEB
  3076. ;
  3077. PUBLIC FindCOMPort
  3078. FindCOMPort proc near
  3079. ;
  3080. ; Examine BIOS data area to get base I/O addresses for COM and LPT ports
  3081. ;
  3082. push bx
  3083. push cx
  3084. push es
  3085. ifndef NEC_98
  3086. mov ax, __0040H
  3087. mov es, ax
  3088. assumes es,nothing
  3089. mov al, [si.DCB_Id]
  3090. mov ah, al
  3091. .erre MAXCOM LT 9 ;only single digit port numbers supported
  3092. add ah, '1'
  3093. mov [CommBaseX], ah
  3094. mov [CommIRQX], ah
  3095. mov [CommFIFOX], ah
  3096. mov [CommDSRx], ah
  3097. cmp al, 4
  3098. jae fcp_not_phys_com
  3099. xor ah, ah
  3100. shl ax, 1
  3101. mov bx, ax
  3102. mov ax, es:[bx+RS232B]
  3103. or ax, ax
  3104. jnz fcp_got_com_base
  3105. fcp_not_phys_com:
  3106. call GetComBase
  3107. or ax, ax
  3108. jnz fcp_got_com_base
  3109. mov bl, [si.DCB_Id]
  3110. cmp bl, 2
  3111. jne fcp_invalid ; jump, if base = 0 & com port <> com3
  3112. mov ax, 3E8h ; default COM3 to 3E8h
  3113. endif ; NEC_98
  3114. fcp_got_com_base:
  3115. push ax
  3116. call GetPortIRQ
  3117. mov dx, ax
  3118. pop ax
  3119. ifndef NEC_98
  3120. or dl, dl ;Q: non-zero IRQ?
  3121. jz fcp_invalid ; N:
  3122. cmp dl, 15 ;Q: IRQ in range?
  3123. ja fcp_invalid ; N:
  3124. endif ; NEC_98
  3125. xor dh, dh
  3126. push ax
  3127. push dx
  3128. call GetPortFIFO
  3129. call GetPortDSR
  3130. pop dx
  3131. pop ax
  3132. clc
  3133. fcp_exit:
  3134. pop es
  3135. pop cx
  3136. pop bx
  3137. ret
  3138. ifndef NEC_98
  3139. fcp_invalid:
  3140. or ax, -1
  3141. mov dx, ax
  3142. stc
  3143. jmp fcp_exit
  3144. endif ; NEC_98
  3145. FindCOMPort endp
  3146. .8086
  3147. page
  3148. ;--------------------------Private Routine-----------------------------;
  3149. ;
  3150. ; Rotate the PIC interrupt priorities so the communication ports are
  3151. ; highest priority.
  3152. ;
  3153. ; NOTE: Only rotates priorities on master PIC.
  3154. ;
  3155. ;-----------------------------------------------------------------------;
  3156. assumes ds,Data
  3157. assumes es,nothing
  3158. public Rotate_PIC
  3159. Rotate_PIC proc near
  3160. ifdef NEC_98
  3161. push ax ; [QN]|
  3162. mov al, [si.DCB_Id] ; Port is 2ch/3ch ? [QN]|
  3163. or al, al ; [QN]|
  3164. jnz rotate30 ; Y: goto Return [QN]|
  3165. xor ah,ah ; [QN]|
  3166. cmp byte ptr IntVecIntcount[si],0 ; [QN]|
  3167. je rotate10 ; [QN]|
  3168. mov al,11000011b ; IRQ3 is lower [QN]|
  3169. jmp short rotate20 ; [QN]|
  3170. rotate10: ; [QN]|
  3171. mov al,11000111b ; IRQ7 is lower [QN]|
  3172. rotate20: ; [QN]|
  3173. out 00H,al ; [QN]|
  3174. rotate30: ; [QN]|
  3175. pop ax ; [QN]|
  3176. ret ; [QN]|
  3177. else ; NEC_98
  3178. push ax
  3179. push cx
  3180. push di
  3181. mov al, 8 ; 0 - 7 rotated
  3182. mov cx, MAXCOM+1
  3183. mov di, DataOFFSET IRQhooks
  3184. rp_loop:
  3185. mov ah, [di.IRQn]
  3186. cmp ah, 0 ;End of hooked IRQ list?
  3187. je rp_set
  3188. cmp [di.VecN], 0FFh ;Hooked?
  3189. je rp_next
  3190. cmp ah, 8 ;If on slave PIC, treat as IRQ2
  3191. jb @f
  3192. mov ah, 2
  3193. @@:
  3194. cmp ah, al
  3195. jae rp_next
  3196. mov al, ah ;AL = lowest hooked comm IRQ
  3197. rp_next:
  3198. add di, SIZE IRQ_Hook_Struc
  3199. loop rp_loop
  3200. rp_set:
  3201. dec al ;Setting IRQ(n-1) as the lowest
  3202. and al, 07h ; priority makes IRQn the highest
  3203. or al, 0C0h
  3204. out INTA0, al
  3205. pop di
  3206. pop cx
  3207. pop ax
  3208. ret
  3209. endif ; NEC_98
  3210. Rotate_PIC endp
  3211. ifdef NEC_98
  3212. ;-----------------------------Public-Routine---------------------------;[QN]
  3213. ; [QN]
  3214. ; Get_PortAddr_and_INTVect - get port address and interrupt vector [QN]
  3215. ; [QN]
  3216. ; The interrupt vector number and the port address are returned [QN]
  3217. ; to the caller. [QN]
  3218. ; [QN]
  3219. ; Entry: [QN]
  3220. ; DS:SI --> DEB [QN]
  3221. ; CX = Port base address [QN]
  3222. ; DS = Data [QN]
  3223. ; Returns: [QN]
  3224. ; AH = IRQ number [QN]
  3225. ; AL = 8259 Mask [QN]
  3226. ; DI:DX --> interrupt handler [QN]
  3227. ; IMRPort = IMR Port Addr [QN]
  3228. ; EOIPort = EOI Port Addr [QN]
  3229. ; Mask8259 = INT mask of COM1,COM2,COM3(PIC) [QN]
  3230. ; IntVecNum = COM1,COM2,COM3 Vect (0CH,etc...) [QN]
  3231. ; MaskFFPort [QN]
  3232. ; ReadSigPort [QN]
  3233. ; DataPort [QN]
  3234. ; CommandPort [QN]
  3235. ; StatusPort [QN]
  3236. ; TimerProcAdr= Timer Process Addr (TickEntry1,TickEntry2,TickEntry3) [QN]
  3237. ; [QN]
  3238. ; [QN]
  3239. ; Error Returns: [QN]
  3240. ; None [QN]
  3241. ; Registers Destroyed: [QN]
  3242. ; FLAGS [QN]
  3243. ; History: [QN]
  3244. ;----------------------------------------------------------------------;[QN]
  3245. assumes ds,Data ; [QN]
  3246. assumes es,nothing ; [QN]
  3247. ; [QN]
  3248. public Get_PortAddr_and_INTVect ; [QN]
  3249. Get_PortAddr_and_INTVect proc near; [QN]
  3250. push bx ; [QN]
  3251. push cx ; [QN]
  3252. ;------------------------------------------------------------- [QN]
  3253. ; Get Port Address and INT Level [QN]
  3254. ;------------------------------------------------------------- [QN]
  3255. Get_Interrupt_Dat001: ; [QN]
  3256. mov ah,[si.DCB_id] ;Get device ID from DCB [QN]
  3257. cmp ah,ID_COM1 ;Com1 ? [QN]
  3258. jne Get_Interrupt_Dat002 ; No (Com2/3 select) [QN]
  3259. ;-------- Com1 -------------------------- [QN]
  3260. mov IMRPort[si],02h ;Store IMR Port Addr [QN]
  3261. mov EOIPort[si],00h ;Store EOI Port Addr [QN]
  3262. mov Mask8259[si],00010000b ;INT mask of Com1(PIC) [QN]
  3263. mov IntVecNum[si],0Ch ;Store Com1 Vect (0CH) [QN]
  3264. ; [QN]
  3265. mov MaskFFPort[si],035h ; [QN]
  3266. mov ReadSigPort[si],033h ; [QN]
  3267. mov DataPort[si],030h ; [QN]
  3268. mov CommandPort[si],032h ; [QN]
  3269. mov StatusPort[si],032h ; [QN]
  3270. lea ax,TickEntry1 ;(ins 92.09.25) [QN]
  3271. mov TimerProcAdr[si],ax ;(ins 92.09.25) [QN]
  3272. jmp Get_Interrupt_Dat004 ;next [QN]
  3273. ;-------- Com2 or Com3 -------------------------- [QN]
  3274. Get_Interrupt_Dat002: ; [QN]
  3275. mov MaskFFPort[si],0B2h ;COM3 (CHANGE 93.03.20) [QN]
  3276. mov ReadSigPort[si],0B2h ;COM3 (CHANGE 93.03.20) [QN]
  3277. mov DataPort[si],0B9h ;COM3 (CHANGE 93.03.20) [QN]
  3278. mov CommandPort[si],0BBh ;COM3 (CHANGE 93.03.20) [QN]
  3279. mov StatusPort[si],0BBh ;COM3 (CHANGE 93.03.20) [QN]
  3280. push ax ; [QN]
  3281. lea ax,TickEntry3 ;COM3 (CHANGE 93.03.20) [QN]
  3282. mov TimerProcAdr[si],ax ;COM3 (CHANGE 93.03.20) [QN]
  3283. pop ax ; [QN]
  3284. ; [QN]
  3285. cmp ah,ID_COM3 ;Com3 ? [QN]
  3286. je Get_Interrupt_Dat3 ; YES [QN]
  3287. ; [QN]
  3288. mov MaskFFPort[si],0B0h ;COM2 (CHANGE 93.03.20) [QN]
  3289. mov ReadSigPort[si],0B0h ;COM2 (CHANGE 93.03.20) [QN]
  3290. mov DataPort[si],0B1h ;COM2 (CHANGE 93.03.20) [QN]
  3291. mov CommandPort[si],0B3h ;COM2 (CHANGE 93.03.20) [QN]
  3292. mov StatusPort[si],0B3h ;COM2 (CHANGE 93.03.20) [QN]
  3293. push ax ; [QN]
  3294. lea ax,TickEntry2 ;COM2 (CHANGE 93.03.20) [QN]
  3295. mov TimerProcAdr[si],ax ;COM2 (CHANGE 93.03.20) [QN]
  3296. pop ax ; [QN]
  3297. ; [QN]
  3298. Get_Interrupt_Dat3: ; [QN]
  3299. mov dx,ReadSigPort[si] ;CI/CS/CD Signal Port [QN]
  3300. in al,dx ;INT Level data save [QN]
  3301. and al,03h ;Mask of BIT 0,1 for INT [QN]
  3302. push bx ;DCB Pointer save [QN]
  3303. mov bl,al ; [QN]
  3304. xor bh,bh ; [QN]
  3305. shl bx,1 ;Made of Word Pointer [QN]
  3306. call GetPortIRQ ; Get IRQ from system.ini(Registry)
  3307. mov bx,ax
  3308. ;----- Not Com1(Board is available) -----
  3309. mov dx,PORT_TBL[bx] ;
  3310. mov IMRPort[si],dx ;Get IMR Port Addr
  3311. ;
  3312. mov dx,PORT_EOI[bx] ;
  3313. mov EOIPort[si],dx ;EOI set resistor
  3314. ;
  3315. mov dl,MASK_TBL[bx] ;
  3316. mov Mask8259[si],dl ;Get IMR Pattern
  3317. ;
  3318. shr bx,1 ; byte pointer
  3319. mov dl,VECT_TBL[bx] ;
  3320. mov IntVecNum[si],dl ;Get INT Num(0b/0d/0e/11/13/14/15)h
  3321. pop bx ;
  3322. Get_Interrupt_Dat004: ; [QN]
  3323. mov al,Mask8259[si] ; al = Pic mask data [QN]
  3324. mov ah,IntVecNum[si] ; ah = Interrupt Req [QN]
  3325. mov di,cs ; di = Int Vecter Seg [QN]
  3326. ; [QN]
  3327. pop cx ; [QN]
  3328. pop bx ; [QN]
  3329. ret ; [QN]
  3330. Get_PortAddr_and_INTVect endp ; [QN]
  3331. ; [QN]
  3332. ;(ins end 92.08.24) ; [QN]
  3333. ;;;---------------------------------------------------------------------[QN]
  3334. ;(ins 93.03.24)
  3335. ;-----------------------------Public-Routine----------------------------;
  3336. ;
  3337. ; OUT5FCheck - out 5f check logic for IOrecovery time
  3338. ;
  3339. ; Entry:
  3340. ; out5f_flag == 0 :default
  3341. ; Returns:
  3342. ; out5f_flag == 0 :
  3343. ; out5f_flag == 1 :out5f ok
  3344. ; Error Returns:
  3345. ; None
  3346. ; Registers Destroyed:
  3347. ; es,ax
  3348. ; History:
  3349. ;-----------------------------------------------------------------------;
  3350. assumes ds,Data ;
  3351. assumes es,nothing ;
  3352. ;
  3353. public OUT5FCheck ;
  3354. OUT5FCheck proc near ;
  3355. push es
  3356. push ax
  3357. mov AX,40h
  3358. mov ES,AX
  3359. test byte ptr ES:[BIOS_FLAG5],80h ; NESA(OUT5F support)?
  3360. jz @F
  3361. mov out5f_flag,1
  3362. jmp short OUT5FCheckEnd
  3363. @@:
  3364. test byte ptr ES:[BIOS_FLAG7],80h ; Normal(OUT5F support)?
  3365. jz OUT5FCheckEnd
  3366. mov out5f_flag,1
  3367. public OUT5FCheckEnd
  3368. OUT5FCheckEnd:
  3369. pop ax
  3370. pop es
  3371. ret
  3372. OUT5FCheck endp ;
  3373. ;(ins end 93.03.24)
  3374. ;(ins 94.04.11)
  3375. ;-----------------------------Public-Routine----------------------------;
  3376. ; AOBACheck - Check whether AOBA on board
  3377. ;
  3378. ; IID_Port = 0y36H using bit:6-5 PRS(1-0) register
  3379. ; (y =1) for FIFO
  3380. ; Entry:
  3381. ;
  3382. ; Returns:
  3383. ; AOBA on board EFlags[si] reset fNoFIFO
  3384. ; non AOBA on board EFlags[si] set fNoFIFO
  3385. ; Error Returns:
  3386. ; NONE
  3387. ; Registers Destroyed:
  3388. ; NONE
  3389. ; History: QNES T-MATUDA
  3390. ;-----------------------------------------------------------------------;
  3391. assumes ds,Data
  3392. assumes es,nothing
  3393. public AOBACheck
  3394. AOBACheck proc near
  3395. push ax
  3396. push dx
  3397. push cx
  3398. xor cx,cx
  3399. mov dx,130H ;
  3400. add dx,ACE_IIDR ; dx = 136H
  3401. in al,dx ;
  3402. test al,040H ;PRS(1-0) == 1x ?
  3403. jnz AOBACheck1 ;(rel 94.05.11)
  3404. in al,dx ;
  3405. AOBACheck1:
  3406. inc cx
  3407. in al,dx ;
  3408. test al,060H ;PRS(1-0) == 00 ?
  3409. jnz NoAOBA ;non AOBA on board
  3410. in al,dx ;
  3411. and al,060H ;PRS(1-0) == 10 ?
  3412. cmp al,040H ;
  3413. jne NoAOBA ;non AOBA on board
  3414. cmp cx,2 ;
  3415. jb AOBACheck1 ;check twice ?
  3416. and EFlags[si], not(fNoFIFO) ;(ins 94.05.11)
  3417. jmp short @F
  3418. NoAOBA:
  3419. or EFlags[si], fNoFIFO ;
  3420. @@:
  3421. pop cx
  3422. pop dx
  3423. pop ax
  3424. ret
  3425. AOBACheck endp
  3426. ;-----------------------------Public-Routine----------------------------;
  3427. ; Set8251mode - Change to 8251 mode
  3428. ;
  3429. ; Entry:
  3430. ;
  3431. ; Returns:
  3432. ;
  3433. ; Error Returns:
  3434. ; NONE
  3435. ; Registers Destroyed:
  3436. ; NONE
  3437. ; History: QNES T-MATUDA
  3438. ;-----------------------------------------------------------------------;
  3439. assumes ds,Data
  3440. assumes es,nothing
  3441. public Set8251mode
  3442. Set8251mode proc near
  3443. push dx ;
  3444. push ax ;
  3445. mov dx,Port[si] ;
  3446. cmp dx,0130h ;(ins 94.5.31)
  3447. je Set8251mode001 ;(ins 94.5.31)
  3448. pop ax ;(ins 94.5.31)
  3449. pop dx ;(ins 94.5.31)
  3450. ret ;(ins 94.5.31)
  3451. Set8251mode001: ;(ins 94.5.31)
  3452. add dx,ACE_FCR ;
  3453. mov al,0 ;set 8251 mode <94.5.16>
  3454. out dx,al ;
  3455. NEWIODELAY 3 ;(ins 94.04.25)
  3456. PUSH CX
  3457. Set8251mode002: ; (94.05.19)
  3458. mov cx,1000h ; (94.05.19)
  3459. Set8251mode003: ; (94.05.19)
  3460. in al,dx ; (94.05.19)
  3461. NEWIODELAY 3 ; (94.05.19)
  3462. test al,ACE_EFIFO ; (94.05.19)
  3463. jz @f ; (94.05.19)
  3464. loop Set8251mode003 ; (94.05.19)
  3465. ; (94.05.19)
  3466. mov dx,132h ; (94.05.19)
  3467. in al,dx ; (94.05.19)
  3468. NEWIODELAY 3 ; (94.05.19)
  3469. mov dx,130h ; (94.05.19)
  3470. in al,dx ; (94.05.19)
  3471. NEWIODELAY 3 ; (94.05.19)
  3472. mov dx,138h ; (94.05.19)
  3473. jmp Set8251mode002 ; (94.05.19)
  3474. @@: ; (94.05.19)
  3475. POP CX
  3476. pop ax ;
  3477. pop dx ;
  3478. ret
  3479. Set8251mode endp
  3480. ;-----------------------------Public-Routine----------------------------;
  3481. ; SetFIFOmode - Change to FIFO mode
  3482. ;
  3483. ; Entry:
  3484. ;
  3485. ; Returns:
  3486. ;
  3487. ; Error Returns:
  3488. ; NONE
  3489. ; Registers Destroyed:
  3490. ; NONE
  3491. ; History: QNES T-MATUDA
  3492. ;-----------------------------------------------------------------------;
  3493. assumes ds,Data
  3494. assumes es,nothing
  3495. public SetFIFOmode
  3496. SetFIFOmode proc near
  3497. push dx ;
  3498. push ax ;
  3499. mov dx,Port[si] ;
  3500. add dx,ACE_FCR ;
  3501. in al, dx ;(ins 94.5.16)
  3502. NEWIODELAY 3 ; <OUT 5F,AL> (ins 94.04.25) |
  3503. test al, 01h ;(ins 94.5.16)
  3504. jz running_8251_mode ;(ins 94.5.16)
  3505. pop ax ;(ins 94.5.16)
  3506. pop dx ;(ins 94.5.16)
  3507. ret ;(ins 94.5.16)
  3508. running_8251_mode: ;(ins 94.5.16)
  3509. ;Set_FIFO == RLInt_Enable + ACE_TRIG14 + ACE_EFIFO
  3510. mov al,Set_FIFO ;set FIFO mode
  3511. out dx,al ;
  3512. NEWIODELAY 3 ; <OUT 5F,AL> (ins 94.04.25) |
  3513. pop ax ;
  3514. pop dx ;
  3515. ret
  3516. SetFIFOmode endp
  3517. public Set8251modeFar
  3518. Set8251modeFar proc far
  3519. call Set8251mode
  3520. ret
  3521. Set8251modeFar endp
  3522. public SetFIFOmodeFar
  3523. SetFIFOmodeFar proc far
  3524. call SetFIFOmode
  3525. ret
  3526. SetFIFOmodeFar endp
  3527. ;(ins end 94.04.11)
  3528. TOMOE_PAT DB 16 DUP('PATCH !!') ;PATCH AREA (ins 92.11.11)
  3529. endif ; NEC_98
  3530. ifdef DEBUG
  3531. public InitCom10, InitCom20, InitCom40, InitCom50, InitCom59
  3532. public InitCom60, InitCom70, InitCom80, InitCom90, InitCom100
  3533. public TermCom10, TermCom15, TermCom20, TermCom30
  3534. ifdef NEC_98
  3535. public TermCom60, Terminate5, Terminate10, Terminate20
  3536. else ; NEC_98
  3537. public TermCom60, Terminate5, Terminate10, Terminate20, Terminate30
  3538. endif ; NEC_98
  3539. public Terminate45, Terminate49, Terminate50
  3540. public SetQue10
  3541. public SetCom5, SetCom10, SetCom20, SetCom210, SetCom220, SetCom230
  3542. public SetCom240, SetCom310, SetCom410, SetCom420, SetCom430
  3543. public SetCom440, SetCom450, SetCom460, SetCom470
  3544. public GetDEB10, GetDEB20, GetDEB30
  3545. public DCBPtr10
  3546. endif
  3547. sEnd code
  3548. page
  3549. createSeg _INIT,init,word,public,CODE
  3550. sBegin init
  3551. assumes cs,init
  3552. ;------------------------------------------------------------------------------
  3553. ;------------------------------------------------------------------------------
  3554. IBMmodel proc near
  3555. ifndef NEC_98
  3556. push ax
  3557. push bx
  3558. push es
  3559. mov ah, 0c0h
  3560. int 15h
  3561. jc IBMmodel_exit
  3562. assumes es,nothing
  3563. cmp by es:[bx+2], 0f8h ; PS/2 80
  3564. je IBMmodel_exit ; return carry clear
  3565. cmp by es:[bx+2], 0fch ; AT or PS/2 50 or 60
  3566. jne OldBios ; assume OldBios
  3567. cmp by es:[bx+3], 04h ; PS/2 50
  3568. je IBMmodel_exit ; return carry clear
  3569. cmp by es:[bx+3], 05h ; PS/2 60
  3570. je IBMmodel_exit ; return carry clear
  3571. OldBios:
  3572. stc
  3573. IBMmodel_exit:
  3574. pop es
  3575. pop bx
  3576. pop ax
  3577. endif ; NEC_98
  3578. ret
  3579. IBMmodel endp
  3580. cProc LoadLib, <FAR,PUBLIC,NODATA>,<si,di>
  3581. cBegin
  3582. ifndef NEC_98
  3583. push ds
  3584. mov ax, __F000H
  3585. mov ds, ax
  3586. assumes ds, ROMBios
  3587. mov al, [MachineID]
  3588. pop ds
  3589. assumes ds,Data
  3590. mov [$MachineID], al
  3591. call IBMmodel ;Q: PS/2?
  3592. jc @F ; N:
  3593. mov [default_table+2], 3 ; Y: change COM3 default IRQ to 3
  3594. @@:
  3595. push ds
  3596. mov ax, __0040H
  3597. mov ds, ax
  3598. assumes ds,nothing
  3599. cmp word ptr ds:[RS232B], 2F8h ;Q: COM2 base in COM1 slot?
  3600. pop ds
  3601. assumes ds,Data
  3602. jne @F ; N: leave IRQ default as 4
  3603. mov [default_table], 3 ; Y: change IRQ default to 3
  3604. @@:
  3605. endif ; NEC_98
  3606. mov [fVPICD], -1 ; assume no
  3607. xor di, di
  3608. mov es, di
  3609. mov ax, GET386API
  3610. mov bx, VPICD
  3611. int MULTIPLEX
  3612. mov wo [lpfnVPICD], di
  3613. mov wo [lpfnVPICD+2], es
  3614. mov ax, es
  3615. or ax, di
  3616. jz short no_VPICD ; jump if no bimodel services available
  3617. ;
  3618. ; version check VPICD
  3619. ;
  3620. mov ax, VPICD_API_Get_Ver
  3621. call [lpfnVPICD]
  3622. %OUT version check VPICD
  3623. mov [fVPICD], 1 ; flag services are available
  3624. IFDEF No_DOSX_Bimodal_Services
  3625. jmp short skip_dosx_stuff
  3626. no_VPICD:
  3627. mov ax, __WinFlags
  3628. and al, WF_PMODE or WF_WIN286
  3629. cmp al, WF_PMODE or WF_WIN286
  3630. jne skip_dosx_stuff
  3631. .286
  3632. mov ax, Int31_Get_Version SHL 8
  3633. int 31h
  3634. test bl, 10b ;Q: processor goes to real mode
  3635. ; for int reflection?
  3636. jz skip_dosx_stuff ; N:
  3637. mov [Using_DPMI], 0FFh ; Y: flag use of DPMI
  3638. mov ax, ds
  3639. cCall GetSelectorBase,<ax> ;DX:AX = segment of selector
  3640. shr ax, 4
  3641. shl dl, 4
  3642. or ah, dl ;AX now points to interrupt *segment*
  3643. push ax ;save on stack
  3644. mov ax, _INTERRUPT ;write data SEGMENT into _INTERRUPT
  3645. cCall AllocCStoDSAlias,<ax> ; code segment -- requires a data alias
  3646. mov es, ax
  3647. pop ax
  3648. mov es:[RM_IntDataSeg],ax
  3649. push ds
  3650. push es
  3651. mov ax, ds
  3652. mov es, ax
  3653. mov ax, _INTERRUPT
  3654. mov ds, ax
  3655. mov ax, (Int31_Trans_Serv SHL 8) + Trans_Call_Back
  3656. mov si, IntCodeOFFSET Entry_From_RM
  3657. mov di, DataOFFSET RM_Call_Struc
  3658. int 31h
  3659. pop es
  3660. pop ds
  3661. mov ax, 0
  3662. jnc @f
  3663. jmp short LoadExit
  3664. @@:
  3665. mov wo es:[RM_CallBack], dx
  3666. mov wo es:[RM_CallBack+2], cx
  3667. cCall FreeSelector,<es> ;don't need CS alias any longer
  3668. .8086
  3669. skip_dosx_stuff:
  3670. ELSE
  3671. no_VPICD:
  3672. ENDIF
  3673. ;
  3674. ; find base values for LPT ports
  3675. ;
  3676. ifndef NEC_98
  3677. mov cx, __0040h
  3678. mov es, cx
  3679. mov cx, MAXLPT+1
  3680. mov si, DataOFFSET LPT1
  3681. ll_initl_lp:
  3682. mov bx, [si.BIOSPortLoc]
  3683. or bx, bx
  3684. jz ll_not_phys_lpt
  3685. mov ax, es:[bx]
  3686. or ah, ah ;Q: lpt redirected, or 0?
  3687. jz ll_not_phys_lpt ; Y:
  3688. cmp bx, LPTB ;Q: first LPT?
  3689. je ll_got_lpt_base ; Y:
  3690. cmp ax, es:[bx-2] ;Q: base same as previous (redirected)?
  3691. jne ll_got_lpt_base ; N: must be real
  3692. ll_not_phys_lpt:
  3693. %OUT attempt to read base from SYSTEM.INI
  3694. ll_got_lpt_base:
  3695. mov [si.Port], ax
  3696. loop ll_initl_lp
  3697. endif ; NEC_98
  3698. ;
  3699. ; create system timer for signalling chars in receive buffer
  3700. ;
  3701. ifndef WOW
  3702. mov ax, 100 ; create 100msec timer
  3703. push ax
  3704. mov ax, _INTERRUPT
  3705. push ax
  3706. mov ax, IntCodeOFFSET TimerProc
  3707. push ax
  3708. call CreateSystemTimer ; ax = 0, if failed
  3709. %OUT should I display an error message here?
  3710. endif
  3711. assumes es,nothing
  3712. LoadExit:
  3713. cEnd
  3714. sEnd init
  3715. End LoadLib