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.

3121 lines
81 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 940923 KBNES
  40. externFP TickEntry4 ;Ins 940923 KBNES
  41. else ; NEC_98
  42. externFP WowCloseComPort
  43. endif ; NEC_98
  44. externNP $RECCOM
  45. externA __0040H
  46. externA __F000h
  47. externB IRQhooks
  48. IF 0
  49. externD OldIntVecIntB
  50. externD OldIntVecIntC
  51. externD OurIntVecIntB
  52. externD OurIntVecIntC
  53. ENDIF
  54. externB szMessage
  55. externB pLPTByte
  56. externB szCOMMessage
  57. externB pCOMByte
  58. externB _szTitle
  59. MULTIPLEX equ 2Fh ; multiplex interrupt number
  60. GET386API equ 1684h ; Get API entry point from VxD
  61. VPD equ 000Fh ; device ID of VPD device
  62. VPD_GETPORT equ 0004h ; function: assign port to current VM
  63. VPD_RELPORT equ 0005h ; function: release port
  64. VCD equ 000Eh ; device ID of VCD device
  65. VCD_GETVER equ 0000h ; get version API
  66. VCD_GETPORT equ 0004h ; function: assign port to current VM
  67. VCD_RELPORT equ 0005h ; function: release port
  68. VCD_STEALPORT equ 0006h
  69. VPICD equ 0003h ; device ID of VPICD device
  70. POSTMESSAGE equ 110 ; export ordinal of PostMessage()
  71. MESSAGEBOX equ 1 ; export ordinal of MessageBox()
  72. MB_TASKMODAL equ 2000h
  73. MB_YESNO equ 0004h ; messagebox flags
  74. MB_ICONEXCLAMATION equ 0030h
  75. IDYES equ 6
  76. createSeg _INTERRUPT,IntCode,word,public,CODE
  77. sBegin IntCode
  78. assumes cs,IntCode
  79. externFP FakeCOMIntFar
  80. externFP TimerProc
  81. externFP Control
  82. externFP COMHandler
  83. externFP APIHandler
  84. IFDEF No_DOSX_Bimodal_Services
  85. externW RM_IntDataSeg
  86. externFP RM_APIHandler
  87. externFP Entry_From_RM
  88. externD RM_CallBack
  89. ENDIF
  90. sEnd IntCode
  91. page
  92. sBegin Data
  93. externB lpCommBase
  94. externB CommBaseX
  95. externB lpCommIrq
  96. externB CommIrqX
  97. externB lpCommFifo
  98. externB CommFifoX
  99. externB lpCommDSR
  100. externB CommDSRx
  101. externB lpCommSection
  102. externB lpSYSTEMINI
  103. ;------------------------------------------------------------------------------
  104. ;
  105. ; Reserve data space for COM ports
  106. ;
  107. DefineCommX MACRO num
  108. public Comm&num
  109. Comm&num label byte
  110. db num-1
  111. .errnz DCB_Id
  112. db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; ComDCB
  113. dw 0 ; ComErr
  114. dw 0 ; Port
  115. dw 0 ; NotifyHandle
  116. dw 0 ; NotifyFlags
  117. dw -1 ; RecvTrigger
  118. dw 0 ; SendTrigger
  119. .errnz IRQhook - SendTrigger - 2
  120. db (SIZE ComDEB) - IRQhook DUP(0)
  121. .errnz $ - Comm&num - (SIZE ComDEB)
  122. Declare_PM_BIS 0,Control,COMHandler,APIHandler,_INTERRUPT,_DATA
  123. db (SIZE EBIS_Sel_Struc) * 2 DUP(0) ; res space for 2 selectors
  124. ENDM
  125. DW_OFFSET_CommX MACRO num
  126. dw DataOFFSET Comm&num
  127. ENDM
  128. ??portnum = 1
  129. REPT MAXCOM+1
  130. DefineCommX %??portnum
  131. ??portnum = ??portnum+1
  132. ENDM
  133. PUBLIC COMptrs ; table of offsets to CommX's declared above
  134. COMptrs label word
  135. ??portnum = 1
  136. REPT MAXCOM+1
  137. DW_OFFSET_CommX %??portnum
  138. ??portnum = ??portnum+1
  139. ENDM
  140. PURGE DefineCommX
  141. PURGE DW_OFFSET_CommX
  142. ;------------------------------------------------------------------------------
  143. ;
  144. ; Reserve data space for LPT ports
  145. ;
  146. DefineLPTx MACRO num
  147. public LPT&num
  148. LPT&num label byte
  149. db num-1+LPTx
  150. .errnz DCB_Id
  151. db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; xComDCB
  152. dw 0 ; xComErr
  153. dw 0 ; xPort
  154. dw 0 ; xNotifyHandle
  155. dw 0 ; xNotifyFlags
  156. dw -1 ; xRecvTrigger
  157. dw 0 ; xSendTrigger
  158. IF num LE 3
  159. dw LPTB + (num-1)*2
  160. ELSE
  161. dw 0 ; BIOSPortLoc
  162. ENDIF
  163. .errnz $-LPT&num - SIZE LptDEB
  164. ENDM
  165. ??portnum = 1
  166. REPT MAXLPT+1
  167. DefineLPTx %??portnum
  168. ??portnum = ??portnum+1
  169. ENDM
  170. PURGE DefineLPTx
  171. page
  172. PUBLIC $MachineID, Using_DPMI
  173. $MachineID db 0 ;IBM Machine ID
  174. Using_DPMI db 0 ; 0FFh, if TRUE
  175. ALIGN 2
  176. PUBLIC activeCOMs
  177. activeCOMs dw 0
  178. PUBLIC lpPostMessage, lpfnMessageBox, lpfnVPD, fVPD
  179. lpPostMessage dd 0
  180. lpfnMessageBox dd 0
  181. lpfnVPD dd 0 ; far pointer to win 386 VPD entry point
  182. lpfnVCD dd 0 ; far pointer to win 386 VCD entry point
  183. lpfnVPICD dd 0 ; far pointer to win 386 VPICD entry point
  184. PUBLIC VCD_int_callback
  185. VCD_int_callback df 0 ; VCD returns the address for this callback
  186. ; on every call to acquire a COM port, but
  187. ; it is always the same address, so we will
  188. ; just maintain it globally.
  189. fVPD db 0 ; 0-not checked, 1 vpd present, -1 no vpd
  190. fVCD db 0 ; 0-not checked, 1 vcd present, -1 no vcd
  191. fVPICD db 0 ; 0-not checked, 1 vpicd present, -1 no vpicd
  192. szUser db 'USER',0
  193. default_table db 4, 3, 4, 3, 0 ; Default IRQ's (COM3 default is changed to
  194. ; 3 for PS/2's during LoadLib)
  195. IFDEF No_DOSX_Bimodal_Services
  196. RM_Call_Struc Real_Mode_Call_Struc <>
  197. ENDIF
  198. IFDEF DEBUG_TimeOut
  199. %OUT including code to display MsgBox, if closing comm with data in buffer
  200. szSendTO db 'TimedOut CloseComm with data in buffer. Retry?', 0
  201. ENDIF
  202. ifdef NEC_98
  203. CM_VxD_Device_ID EQU 034h
  204. CM_GetVersion EQU 0
  205. CM_GetConfig EQU 1
  206. CM_LockConfig EQU 2
  207. CM_UnlockConfig EQU 3
  208. CM_ConfigBuffSize EQU SIZE Config_Info_Struc
  209. Max_Mem_Registers EQU 9
  210. Max_IO_Ports EQU 20
  211. Max_IRQs EQU 7
  212. Max_DMA_Channels EQU 7
  213. Config_info_Struc STRUC
  214. CIS_Bus_id dd ?
  215. CIS_Device_id dd ?
  216. CIS_Serial_Number dd ?
  217. CIS_Log_ID dd ?
  218. CIS_Flags dd ?
  219. ;
  220. ; NOTE:For this example,we are using the ISA Plug&Play card access data only
  221. ; since the sample driver is for a theoretical new ISA card.
  222. ;
  223. CIS_CSN db ?
  224. CIS_LogicalDevNumber db ?
  225. CIS_Read_data_port dw ?
  226. ;
  227. ; Below this point is data common to all device on all busses
  228. ;
  229. CIS_NumMemWindows dw ?
  230. CIS_MemBase dd Max_Mem_Registers dup(?)
  231. CIS_MemLength dd Max_Mem_Registers dup(?)
  232. CIS_MemAttrib dw Max_Mem_Registers dup(?)
  233. CIS_NumIOPorts dw ?
  234. CIS_IOPort_Base dw Max_IO_Ports dup(?)
  235. CIS_IOPort_Length dw Max_IO_Ports dup(?)
  236. CIS_NumIRQs dw ?
  237. CIS_IRQRegisters db Max_IRQs dup(?)
  238. CIS_IRQAttrib db Max_IRQs dup(?)
  239. CIS_NumDMAs dw ?
  240. CIS_DMAList db Max_DMA_Channels dup(?)
  241. CIS_DMAAttrib dw Max_DMA_Channels dup(?)
  242. CIS_Reserved db 3 dup(?)
  243. Config_Info_Struc ENDS
  244. CM_Entry_Point LABEL DWORD
  245. CM_Entry_Point_Off dw ?
  246. CM_Entry_Point_Seg dw ?
  247. My_Config_Buffer Config_Info_Struc<>
  248. My_Search_Buffer LABEL DWORD
  249. dd ? ;My_Bus_ID
  250. dd ? ;My_Dev_ID
  251. dd ? ;My_Serial_Num
  252. My_Log_ID dd 04180a3b8h ;My_Log_ID Fax ID 94.08.02
  253. endif ; NEC_98
  254. sEnd Data
  255. ROMBios segment at 0F000h
  256. org 0FFFEh
  257. MachineID label byte
  258. RomBios Ends
  259. sBegin Code
  260. assumes cs,Code
  261. assumes ds,Data
  262. page
  263. IFDEF No_DOSX_Bimodal_Services
  264. ;----------------------------Private-Routine----------------------------;
  265. ; SegmentFromSelector
  266. ;
  267. ; Converts a selector to a segment...note that this routine assumes
  268. ; the memory pointed to by the selector is below the 1Meg line!
  269. ;
  270. ; Params:
  271. ; AX = selector to convert to segment
  272. ;
  273. ; Returns:
  274. ; AX = segment of selector given
  275. ;
  276. ; Error Returns:
  277. ; None
  278. ;
  279. ; Registers Destroyed:
  280. ; CX
  281. ;
  282. ;-----------------------------------------------------------------------;
  283. assumes ds,Data
  284. assumes es,nothing
  285. public SegmentFromSelector
  286. SegmentFromSelector proc far
  287. .286
  288. push dx
  289. cCall GetSelectorBase,<ax> ;DX:AX = segment of selector
  290. shr ax, 4
  291. shl dl, 4
  292. or ah, dl ;AX now points to interrupt *segment*
  293. pop dx
  294. ret
  295. .8086
  296. SegmentFromSelector endp
  297. ENDIF
  298. page
  299. ;------------------------------------------------------------------------------
  300. ;
  301. ; Get_API_Entry
  302. ;
  303. ; entry - BX = device id
  304. ; DS:DI -> DWORD for proc address
  305. ; exit - Z flag set, if failed
  306. ;
  307. Get_API_Entry proc near
  308. push di
  309. xor di, di
  310. mov es, di
  311. mov ax, GET386API
  312. int MULTIPLEX
  313. mov ax, di
  314. pop di
  315. mov [di], ax
  316. mov [di+2], es
  317. or ax, [di+2]
  318. ret
  319. Get_API_Entry endp
  320. ;----------------------------Private-Routine----------------------------;
  321. ;
  322. ; Contention_Dlg
  323. ;
  324. ; If running under Win386, this routine can be called to ask the user to
  325. ; resolve contention for a COM or LPT port.
  326. ;
  327. ; entry - CX is offset of message string for dialog box
  328. ;
  329. ; exit - Z flag set, if user specified that Windows should steal the port
  330. Contention_Dlg proc near
  331. PUBLIC Contention_Dlg
  332. xor ax,ax
  333. push ax ; hwndOwner
  334. push ds
  335. push cx ; message ptr
  336. cmp wo lpfnMessageBox[2], 0 ;Q: ptr to MessageBox proc valid?
  337. jne short gmbp_done ; Y: we can call it
  338. push ds ; N: get module handle of USER
  339. lea ax, szUser
  340. push ax
  341. cCall GetModuleHandle
  342. push ax ; module handle
  343. mov ax, MESSAGEBOX
  344. cwd
  345. push dx
  346. push ax
  347. cCall GetProcAddress
  348. mov wo lpfnMessageBox[0], ax ; save received proc address
  349. mov wo lpfnMessageBox[2], dx
  350. gmbp_done:
  351. push ds
  352. lea ax, _szTitle
  353. push ax
  354. mov ax, MB_ICONEXCLAMATION or MB_YESNO or MB_TASKMODAL
  355. push ax
  356. cCall lpfnMessageBox
  357. cmp ax, IDYES ; user allows us to take the port?
  358. ret
  359. Contention_Dlg endp
  360. ifndef NEC_98
  361. ;----------------------------Private-Routine----------------------------;
  362. ;
  363. ; GetPort386
  364. ;
  365. ; If running under Win386, tell the VPD to assign an LPT port to us.
  366. ; The comm driver will handle contention.
  367. ;
  368. ; entry - DI contains offset in ROM area of port...
  369. ; 8 - LPT1, A - LPT2, etc
  370. ;
  371. ; exit - registers saved, carry = clear if OK to proceed, set if
  372. ; user won't allow assignment of port or Win386 error
  373. ;
  374. GetPort386 proc near
  375. public GetPort386
  376. cmp fVPD, 0
  377. jl getport_VPDNotInstalled
  378. jnz short getport_CallVPD
  379. push di
  380. mov bx, VPD
  381. mov di, DataOFFSET lpfnVPD
  382. call Get_API_Entry
  383. pop di
  384. jnz short getport_CallVPD
  385. mov fVPD, -1
  386. getport_VPDNotInstalled:
  387. clc
  388. jmp short getport_exit
  389. getport_CallVPD:
  390. mov fVPD, 1
  391. push di
  392. sub di, LPTB
  393. shr di, 1 ; turn DI into port number
  394. xor ax, ax
  395. mov dx, VPD_GETPORT
  396. mov cx, di
  397. call [lpfnVPD]
  398. jnc getport_gotit
  399. ; port owned by another VM... ask the user for it
  400. add cl, '1' ; fix up the port name...
  401. mov pLPTByte, cl ; HACK HACK HACK
  402. lea cx, szMessage
  403. call Contention_Dlg
  404. jnz getport_userwontallow
  405. mov ax, 1 ; tell win386 we really do want it
  406. mov cx, di ;
  407. mov dx, VPD_GETPORT ;
  408. call [lpfnVPD] ; return with C set or clear...
  409. jmp short getport_gotit
  410. getport_userwontallow:
  411. stc
  412. getport_gotit:
  413. pop di
  414. getport_exit:
  415. ret
  416. GetPort386 endp
  417. endif ; NEC_98
  418. ;----------------------------Private-Routine----------------------------;
  419. ;
  420. ; ReleasePort386
  421. ;
  422. ; If running under Win386, tell the VPD to deassign an LPT port.
  423. ;
  424. ; entry - DS:SI -> COMDEB
  425. ;
  426. ReleasePort386 proc near
  427. cmp fVPD, 1
  428. jne release_noVPD
  429. xor cx, cx
  430. mov cl, [si.DCB_id]
  431. and cl, NOT LPTx ; clear high bit
  432. mov dx, VPD_RELPORT
  433. call [lpfnVPD]
  434. release_noVPD:
  435. ret
  436. ReleasePort386 endp
  437. ifndef NEC_98
  438. ;----------------------------Private-Routine----------------------------;
  439. ;
  440. ; GetCOMport386
  441. ;
  442. ; If running under Win386, tell the VCD to assign a COM port to us.
  443. ; The comm driver will handle contention.
  444. ;
  445. ; entry - DS:SI -> COMDEB
  446. ;
  447. ; exit - registers saved, carry = clear if OK to proceed, set if
  448. ; user won't allow assignment of port or Win386 error
  449. ;
  450. .386
  451. GetCOMport386 proc near
  452. public GetCOMport386
  453. push es
  454. pushad
  455. cmp fVCD, 0
  456. jl short getcomport_VCDNotInstalled
  457. jnz short getcomport_CallVCD
  458. mov bx, VCD
  459. mov di, DataOFFSET lpfnVCD
  460. call Get_API_Entry
  461. jz short getcomport_checknoVCD
  462. mov dx, VCD_GETVER
  463. call [lpfnVCD]
  464. cmp ax, 30Ah ;Q: 3.1 or greater?
  465. jae short getcomport_CallVCD ; Y:
  466. getcomport_checknoVCD:
  467. mov fVCD, -1
  468. getcomport_VCDNotInstalled:
  469. clc
  470. jmp short getcomport_exit
  471. getcomport_CallVCD:
  472. mov fVCD, 1
  473. mov ax, 10b ; flag ring0 int handler
  474. call VCD_GetPort_API
  475. jnc short getcomport_success ; jump if acquire worked
  476. jnz short getcomport_noport ; jump if port doesn't exist
  477. ; port owned by another VM... ask the user for it
  478. mov cl, [si.DCB_id]
  479. add cl, '1' ; fix up the port name...
  480. mov pCOMByte, cl
  481. lea cx, szCOMMessage
  482. call Contention_Dlg
  483. stc
  484. jnz short getcomport_exit
  485. mov ax, 11b ; tell win386 we really do want it
  486. call VCD_GetPort_API
  487. jc short getcomport_exit
  488. getcomport_success:
  489. mov dword ptr [VCD_int_callback], edi
  490. mov word ptr [VCD_int_callback+4], cx
  491. mov [si.VCD_data], ebx
  492. xchg ax, [si.Port]
  493. or ax, ax ;Q: already had port base?
  494. jnz short getcomport_exit ; Y: don't update vector #, or FIFO
  495. mov [si.IntVecNum], dl
  496. call GetPortFlags
  497. clc
  498. getcomport_exit:
  499. popad
  500. pop es
  501. ret
  502. getcomport_noport:
  503. mov [si.Port], -1
  504. jmp getcomport_exit
  505. GetCOMport386 endp
  506. VCD_GetPort_API proc near
  507. mov dx, VCD_GETPORT
  508. xor cx, cx
  509. mov cl, [si.DCB_Id] ; cx = port #
  510. mov di, VCDflags ; offset from start of DEB
  511. call [lpfnVCD]
  512. ret
  513. VCD_GetPort_API endp
  514. .8086
  515. ;----------------------------Private-Routine----------------------------;
  516. ;
  517. ; ReleaseCOMport386
  518. ;
  519. ; If running under Win386, tell the VCD to deassign a COM port.
  520. ;
  521. ; entry - DS:SI -> COMDEB
  522. ;
  523. ReleaseCOMport386 proc near
  524. ifndef WOW
  525. cmp fVCD, 1
  526. jne release_noVCD
  527. xor cx, cx
  528. mov cl, [si.DCB_id]
  529. mov dx, VCD_RELPORT
  530. call [lpfnVCD]
  531. else
  532. xor cx, cx
  533. mov cl, [si.DCB_id]
  534. push cx
  535. call WowCloseComPort
  536. endif
  537. release_noVCD:
  538. ret
  539. ReleaseCOMport386 endp
  540. endif ; NEC_98
  541. PUBLIC StealPort
  542. StealPort proc near
  543. cmp fVCD, 1
  544. jne sp_yes
  545. mov dx, VCD_STEALPORT
  546. xor cx, cx
  547. mov cl, [si.DCB_id]
  548. call [lpfnVCD]
  549. or al, al
  550. jnz sp_yes
  551. sp_no:
  552. stc
  553. ret
  554. sp_yes:
  555. clc
  556. mov [si.VCDflags], 0
  557. ret
  558. StealPort endp
  559. page
  560. ;------------------------------------------------------------------------------
  561. ;
  562. ; ENTER: DS:SI -> ComDEB
  563. ; EXIT: AL = 0, if IRQ was unmasked, else -1, if IRQ was already masked
  564. ;
  565. MaskIRQ proc near
  566. push es
  567. push di
  568. mov di, ds
  569. mov es, di
  570. lea di, [si+SIZE ComDEB]
  571. mov ax, BIH_API_Get_Mask
  572. call APIHandler ; returns Carry Set, if masked
  573. jc short already_masked
  574. pushf
  575. mov ax, BIH_API_Mask
  576. call APIHandler ; mask IRQ
  577. xor ax, ax
  578. popf
  579. jnc short mask_exit
  580. already_masked:
  581. or al, -1
  582. mask_exit:
  583. pop di
  584. pop es
  585. ret
  586. MaskIRQ endp
  587. ;------------------------------------------------------------------------------
  588. ;
  589. ; ENTER: DS:SI -> ComDEB
  590. ;
  591. UnmaskIRQ proc near
  592. push es
  593. push di
  594. mov di, ds
  595. mov es, di
  596. lea di, [si+SIZE ComDEB]
  597. mov ax, BIH_API_Unmask
  598. call APIHandler
  599. pop di
  600. pop es
  601. ret
  602. UnmaskIRQ endp
  603. page
  604. ;----------------------------Public Routine-----------------------------;
  605. ;
  606. ; $INICOM - Initialize A Port
  607. ;
  608. ; Initalizes the requested port if present, and sets
  609. ; up the port with the given attributes when they are valid.
  610. ; This routine also initializes communications buffer control
  611. ; variables. This routine is passed the address of a device
  612. ; control block.
  613. ;
  614. ; The RLSD, CTS, and DSR signals should be ignored by all COM
  615. ; routines if the corresponding timeout values are 0.
  616. ;
  617. ; For the LPT ports, a check is performed to see if the hardware
  618. ; is present (via the LPT port addresses based at 40:8h. If the
  619. ; port is unavailable, an error is returned. If the port is
  620. ; available, then the DEB is set up for the port. $SETCOM will
  621. ; be called to set up the DEB so that there will be something
  622. ; valid to pass back to the caller when he inquires the DEB.
  623. ;
  624. ; No hardware initialization will be performed to prevent the
  625. ; RESET line from being asserted and resetting the printer every
  626. ; time this routine is called.
  627. ;
  628. ; Entry:
  629. ; EX:BX --> Device Control Block with all fields set.
  630. ; Returns:
  631. ; AX = 0 if no errors occured
  632. ; Error Returns:
  633. ; AX = initialization error code otherwise
  634. ; Registers Preserved:
  635. ; None
  636. ; Registers Destroyed:
  637. ; AX,BX,CX,DX,ES,FLAGS
  638. ; History:
  639. ;-----------------------------------------------------------------------;
  640. ;------------------------------Pseudo-Code------------------------------;
  641. ; {
  642. ; }
  643. ;-----------------------------------------------------------------------;
  644. assumes ds,Data
  645. assumes es,nothing
  646. public $INICOM
  647. $INICOM proc near
  648. push si ;As usual, save register variables
  649. push di
  650. mov ah,es:[bx.DCB_Id] ;Get device i.d.
  651. call GetDEB ;--> DEB for this device
  652. mov ax, IE_BADID ; call it a bad id (spooler uses DOS)
  653. jc InitCom15 ;Invalid device
  654. jns InitCom20 ; jmp if COM port
  655. ifndef NEC_98
  656. push ds
  657. mov di, [si.BIOSPortLoc]
  658. cmp di, LPTB
  659. jb short InitLPT_Installed
  660. mov cx,__0040H ;[rkh] ...
  661. mov ds,cx ;Point DS: at ROM Save Area.
  662. assumes ds,nothing
  663. mov ax, IE_HARDWARE
  664. mov cx, wo [di]
  665. jcxz InitCom10 ; if zero, no hardware
  666. mov ax,IE_BadID ;Show bad device
  667. cmp ch, 0 ; zero hibyte -> not valid (redir)
  668. jz InitCom10 ; call it a bad id (spooler uses DOS)
  669. cmp di, LPTB ; LPT1?
  670. jz InitLPT_Installed ; yes, must be installed
  671. cmp cx, wo [di-2] ;Q: duplicate of previous port
  672. je InitCom10 ; Y: (redirected port)
  673. InitLPT_Installed:
  674. pop ds
  675. mov [si.Port], cx
  676. call $SETCOM
  677. call GetPort386 ; tell win386 we're using the port
  678. mov ax, IE_OPEN ; port already open (by another VM)
  679. jc InitCom15 ; error
  680. jmp InitCom90 ;That's all
  681. endif ; NEC_98
  682. InitCom10:
  683. pop ds ; get DS back
  684. InitCom15:
  685. jmp InitCom100
  686. assumes ds,Data
  687. InitCom17:
  688. mov ax, IE_OPEN
  689. cmp [si.Port], -1 ;Q: determined that port didn't exist?
  690. jne InitCom15 ; N: return IE_OPEN
  691. jmp short InitCom27 ; Y: return IE_HARDWARE
  692. ; *** Set up serial port ***
  693. ;
  694. InitCom20:
  695. cmp [si.Port], -1 ;Q: port exists?
  696. je InitCom27 ; N: report not found
  697. mov ax, __WinFlags
  698. test ax, WF_ENHANCED
  699. jz short @F
  700. ifndef NEC_98
  701. call GetCOMport386
  702. jc InitCom17
  703. endif ; NEC_98
  704. @@:
  705. ifdef NEC_98
  706. push ax ;Ins 940923 KBNES
  707. lea ax,TickEntry4 ;Ins 940923 KBNES
  708. mov TimerProcAdr[si],ax ;Ins 940923 KBNES
  709. pop ax ;Ins 940923 KBNES
  710. endif ; NEC_98
  711. cmp [si.Port], 0 ;Q: already got info?
  712. jnz @F
  713. call FindCOMPort
  714. jc InitCom27 ; report not found, if error
  715. mov [si.Port], ax
  716. mov [si.IntVecNum], dl
  717. @@:
  718. push es ;Save these registers
  719. push di
  720. push cx ;needed later for $SETCOM etc
  721. push bx
  722. mov al, [si.IntVecNum]
  723. xor ah, ah
  724. lea di, [si+SIZE ComDEB]
  725. mov [di.BIS_IRQ_Number], ax
  726. mov di, DataOFFSET IRQhooks
  727. mov cx, MAXCOM+1
  728. InitCom25:
  729. ifdef NEC_98
  730. jmp InitCom35 ;Add 1994.08.02 KBNES
  731. endif ; NEC_98
  732. cmp al, [di.IRQn] ;Q: hooked IRQ matches ours?
  733. je short InitCom30 ; Y:
  734. cmp [di.IRQn], 0 ;Q: end of hooked IRQ list?
  735. je short InitCom35 ; Y:
  736. add di, SIZE IRQ_Hook_Struc ; N: check next hook
  737. loop InitCom25
  738. int 3 ; data structures corrupt if we
  739. ; get here, because no hook table
  740. ; entries exist and there is suppose
  741. ; to be at least 1 for each DEB
  742. InitCom26:
  743. ifndef NEC_98
  744. call ReleaseCOMport386 ; give port back to 386...
  745. endif ; NEC_98
  746. pop bx
  747. pop cx
  748. pop di
  749. pop es
  750. InitCom27:
  751. mov ax, IE_HARDWARE ; jump if port not available
  752. jmp InitCom100
  753. InitCom30:
  754. cmp [di.HookCnt], 0 ;Q: IRQ still hooked?
  755. je short InitCom35 ; N: rehook
  756. inc [di.HookCnt] ; Y: inc hook count
  757. mov [si.IRQhook], di ; & link DEB into list
  758. mov ax, [di.First_DEB]
  759. mov [si.NextDEB], ax
  760. mov [di.First_DEB], si
  761. jmp short InitCom40
  762. InitCom35:
  763. mov [di.IRQn], al ; hook IRQ for first time, or rehook
  764. mov [si.IRQhook], di
  765. mov [di.First_DEB], si
  766. mov [di.HookCnt], 1
  767. call MaskIRQ
  768. mov [di.OldMask], al
  769. InitCom40: ; di -> IRQ_Hook_Struc
  770. cmp [fVPICD], 0 ;Q: VPICD bimodel services available?
  771. jl short InitCom415 ; N:
  772. mov ax, ds ; Y: use them
  773. mov es, ax
  774. lea di, [si+SIZE ComDEB]
  775. mov [di.BIS_Descriptor_Count], 2
  776. mov ax, word ptr [si.QInAddr+2] ; get selector of in queue
  777. mov [di.EBIS_Sel1.EBIS_User_Mode_Sel], ax
  778. mov ax, word ptr [si.QOutAddr+2] ; get selector of out queue
  779. mov [di.EBIS_Sel2.EBIS_User_Mode_Sel], ax
  780. mov ax, VPICD_Install_Handler
  781. call [lpfnVPICD]
  782. jnc InitCom42
  783. cmp [di.OldMask], 0
  784. jne InitCom26
  785. call UnmaskIRQ
  786. jmp InitCom26
  787. InitCom42:
  788. ;
  789. ; save newly allocated selectors/segments into "Alt" queue pointers
  790. ;
  791. mov ax, [di.EBIS_Sel1.EBIS_Super_Mode_Sel]
  792. mov word ptr [si.AltQInAddr+2], ax
  793. mov ax, [di.EBIS_Sel2.EBIS_Super_Mode_Sel]
  794. mov word ptr [si.AltQOutAddr+2], ax
  795. InitCom414:
  796. jmp InitCom59
  797. InitCom415:
  798. cmp [di.VecN], 0FFh ;Q: int already hooked?
  799. IFDEF No_DOSX_Bimodal_Services
  800. jnz short InitCom52 ; Y: init RMode ptrs in BIS
  801. ELSE
  802. jnz InitCom414 ; Y:
  803. ENDIF
  804. mov al, [si.IntVecNum]
  805. add al, 8 ; 1st PIC starts at vector 8h
  806. cmp al, 16 ;Q: 2nd PIC?
  807. jb short InitCom418 ; N:
  808. add al, 70h-16 ; Y: 2nd PIC starts at vector 70h
  809. InitCom418:
  810. mov [di.VecN], al
  811. ; *** Set interrupt vectors ***
  812. ;
  813. mov ah,35h ;Get the DOS vector
  814. int 21h ;DOS Get Vector Function
  815. mov wo [di.OldIntVec][0], bx
  816. mov wo [di.OldIntVec][2], es
  817. InitCom50:
  818. push ds ;Save original DS
  819. mov dx, [di.HandlerOff]
  820. mov bx, _INTERRUPT
  821. mov ds, bx ;Interrupt handler address in ds:dx
  822. assumes ds,nothing
  823. mov ah, 25h ;DOS Set Vector Function
  824. int 21h ;Set the DOS vector
  825. pop ds ;Original DS
  826. assumes ds,Data
  827. IFDEF No_DOSX_Bimodal_Services
  828. InitCom52:
  829. cmp [Using_DPMI], 0
  830. jz short InitCom57
  831. mov ax, Int31_Get_Version SHL 8
  832. int 31h
  833. mov bl, [si.IntVecNum]
  834. mov bh, bl
  835. add bl, dh ; assume master PIC
  836. sub bh, 8 ;Q: IRQ in master?
  837. jb @f ; Y: add master's base vec
  838. add bh, dl ; N: add slave's base vec
  839. mov bl, bh
  840. @@:
  841. mov ax, Get_RM_IntVector
  842. int 31h
  843. mov wo [di.RM_OldIntVec][0], dx
  844. mov wo [di.RM_OldIntVec][2], cx
  845. mov dx, [di.RM_HandlerOff]
  846. mov ax, _INTERRUPT
  847. call SegmentFromSelector
  848. mov cx, ax
  849. push cx
  850. mov ax, Set_RM_IntVector
  851. int 31h
  852. lea di, [si+SIZE ComDEB]
  853. mov wo [di.BIS_Super_Mode_API], IntCodeOFFSET RM_APIHandler
  854. pop cx
  855. mov wo [di.BIS_Super_Mode_API+2], cx
  856. ;
  857. ; Get segment addresses for the Q's and set AltQInAddr and AltQOutAddr
  858. ;
  859. mov ax, wo [si.AltQInAddr+2]
  860. call SegmentFromSelector
  861. mov wo [si.AltQInAddr+2], ax
  862. mov ax, wo [si.AltQOutAddr+2]
  863. call SegmentFromSelector
  864. mov wo [si.AltQOutAddr+2], ax
  865. InitCom57:
  866. ENDIF
  867. mov ax, __WinFlags ;In Standard mode, the PIC IRQ
  868. test al, WF_STANDARD ; priorities get rotated to favor
  869. jz InitCom59 ; the comm ports.
  870. call Rotate_PIC
  871. ; *** Interrupt handler set : jump here if handler is already installed ***
  872. ;
  873. InitCom59:
  874. pop bx
  875. pop cx
  876. pop di
  877. pop es
  878. InitCom60:
  879. mov dx,[si.Port] ;Set comm card address
  880. xor ax,ax ;Need a zero
  881. inc dx ;--> Interrupt Enable Register
  882. .errnz ACE_IER-ACE_RBR-1
  883. out dx,al ;Turn off interrupts
  884. ifdef NEC_98
  885. iodelay ;1994.08.01 KBNES
  886. endif ; NEC_98
  887. call FlagNotActive
  888. add dl,ACE_MCR-ACE_IER ;--> Modem Control Register
  889. in al,dx
  890. and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so
  891. iodelay ; but tri-state IRQ line
  892. out dx,al
  893. ifdef NEC_98
  894. iodelay ;1994.08.01 KBNES
  895. endif ; NEC_98
  896. InitCom70:
  897. push es ;Zero queue counts and indexes
  898. push ds
  899. pop es
  900. assumes es,Data
  901. lea di,QInCount[si]
  902. mov cx,(EFlags-QInCount)/2
  903. .errnz (EFlags-QInCount) AND 1
  904. xor ax,ax
  905. cld
  906. rep stosw
  907. .errnz QInGet-QInCount-2
  908. .errnz QInPut-QInGet-2
  909. .errnz QOutCount-QInPut-2
  910. .errnz QOutGet-QOutCount-2
  911. .errnz QOutPut-QOutGet-2
  912. .errnz EFlags-QOutPut-2 ;First non-queue item
  913. pop es
  914. assumes es,nothing
  915. mov HSFlag[si],al ;Show no handshakes yet
  916. mov MiscFlags[si],al ;Show not discarding
  917. mov EvtWord[si],ax ;Show no events
  918. mov [si.VCDflags], al
  919. mov [si.SendTrigger], ax
  920. dec ax
  921. mov [si.RecvTrigger], ax
  922. ;Call $SETCOM to perform further hardware initialization.
  923. InitCom80:
  924. sub dl,ACE_MCR-ACE_FCR ; dx -> FCR
  925. in al, dx
  926. iodelay
  927. test al, ACE_FIFO_E2 ;Q: FIFO already on?
  928. jz short @F ; N:
  929. or EFlags[si], fFIFOpre ; Y: flag it
  930. @@:
  931. ; needs si, di, and es to be saved from the beginning of inicom
  932. call $SETCOM ;Set up Comm Device
  933. jnz short InitCom110 ;jump if failed
  934. call UnmaskIRQ
  935. and EFlags[si], fEFlagsMask ;Clear internal state
  936. InitCom90:
  937. xor ax,ax ;Return AX = 0 to show success
  938. mov ComErr[si],ax ;Get rid of any bogus init error
  939. InitCom100:
  940. pop di
  941. pop si
  942. ret
  943. ;
  944. ; jump to here, if call to $SETCOM failed
  945. ;
  946. ; DANGER! *** Call into middle of Terminate to clean things up *** DANGER!
  947. ;
  948. InitCom110:
  949. push ax ;Failure, save error code
  950. call Terminate45 ;Restore port address, int vec
  951. pop ax ;Restore error code and exit
  952. jmp InitCom100
  953. $INICOM endp
  954. page
  955. ;----------------------------Public Routine-----------------------------;
  956. ;
  957. ; $TRMCOM - Terminate Communications Channel
  958. ;
  959. ; Wait for any outbound data to be transmitted, drop the hardware
  960. ; handshaking lines, and disable interrupts. If the output queue
  961. ; contained data when it was closed, an error will be returned
  962. ;
  963. ; LPT devices have it easy. They just need to restore the I/O port
  964. ; address.
  965. ;
  966. ; Entry:
  967. ; AH = Device ID
  968. ; Returns:
  969. ; AX = 0
  970. ; Error Returns:
  971. ; AX = 8000h if invalid device ID
  972. ; AX = -2 if output queue timeout occured
  973. ; Registers Destroyed:
  974. ; AX,BX,CX,DX,ES,FLAGS
  975. ; History:
  976. ;-----------------------------------------------------------------------;
  977. ;------------------------------Pseudo-Code------------------------------;
  978. ; {
  979. ; }
  980. ;-----------------------------------------------------------------------;
  981. assumes ds,Data
  982. assumes es,nothing
  983. public $TRMCOM
  984. $TRMCOM proc near
  985. push si
  986. push di
  987. xor cx,cx ;Show no error if LPT port
  988. call GetDEB
  989. jc TermCom60 ;ID is invalid, return error
  990. js TermCom30 ;Port is a LPT port
  991. push ax ;Save port id
  992. or MiscFlags[si],Discard ;Show discarding serial data
  993. mov ComErr[si],cx ;Clear error flags
  994. mov QInCount[si],cx ;Show no chars in input queue
  995. call $RECCOM ;Send XON if needed
  996. ;-----------------------------------------------------------------------;
  997. ; We have to wait for the output queue to empty. To do this,
  998. ; a timer will be created. If no character has been transmitted
  999. ; when the timeout occurs, then an error will be indicated and
  1000. ; the port closed anyway. If the timer cannot be created, then
  1001. ; just loop until the queue empties, which will be better than
  1002. ; discarding charatcers if there are any
  1003. ;-----------------------------------------------------------------------;
  1004. test [si.HSFlag], HHSAlwaysDown ; Q: handshaking ever up?
  1005. jnz TermCom17 ; N: skip wait loop
  1006. TermCom10:
  1007. mov cx,QOutCount[si] ;Get current queue count
  1008. jcxz TermCom20 ;No characters in queue
  1009. cCall GetSystemMsecCount
  1010. mov di, ax
  1011. TermCom15:
  1012. cmp QOutCount[si],cx ;Queue count change?
  1013. jne TermCom10 ; Yes, restart timeout
  1014. cCall GetSystemMsecCount
  1015. sub ax, di
  1016. cmp ax, Timeout * 1000 ;Q: Timeout reached?
  1017. jb TermCom15 ; No, keep waiting
  1018. IFDEF DEBUG_TimeOut
  1019. .286
  1020. pusha
  1021. lea cx, szSendTO
  1022. call Contention_Dlg
  1023. popa
  1024. jz TermCom10
  1025. .8086
  1026. ENDIF
  1027. TermCom17:
  1028. mov cx, TimeoutError ; Yes, show timeout error
  1029. TermCom20:
  1030. pop ax ;Restore cid
  1031. ifdef NEC_98
  1032. ;-------------------------------------------------------------- Ins 940923 KBNES
  1033. ; Close Process of System Timer Ins 940923 KBNES
  1034. ;-------------------------------------------------------------- Ins 940923 KBNES
  1035. push ax ; Ins 940923 KBNES
  1036. mov ax,hTimer[si] ; Check hTimer Ins 940923 KBNES
  1037. or ax,ax ; Is there TimerProcess?Ins 940923 KBNES
  1038. jz NoKillTimer ; Y:(Nothing) Ins 940923 KBNES
  1039. cCall KillSystemTimer,<ax> ; Kill System Timer Ins 940923 KBNES
  1040. mov hTimer[si] ,NULL ; Clear hTimer Ins 940923 KBNES
  1041. NoKillTimer: ; Ins 940923 KBNES
  1042. pop ax ; Ins 940923 KBNES
  1043. endif ; NEC_98
  1044. TermCom30:
  1045. mov dx,Port[si] ;Get port base address
  1046. call Terminate ;The real work is done here
  1047. mov ax,cx ;Set return code
  1048. TermCom60:
  1049. pop di
  1050. pop si
  1051. ret
  1052. $TRMCOM endp
  1053. page
  1054. ;----------------------------Private-Routine----------------------------;
  1055. ;
  1056. ; Terminate - Terminate Device
  1057. ;
  1058. ; Restore the port I/O address and make sure that interrupts are off
  1059. ;
  1060. ; Entry:
  1061. ; AH = Device Id.
  1062. ; DX = Device I/O port address.
  1063. ; SI --> DEB
  1064. ; Returns:
  1065. ; AX = 0
  1066. ; Error Returns:
  1067. ; AX = -1
  1068. ; Registers Destroyed:
  1069. ; AX,BX,DX,FLAGS
  1070. ; History:
  1071. ;-----------------------------------------------------------------------;
  1072. assumes ds,Data
  1073. assumes es,nothing
  1074. public Terminate ;Public for debugging
  1075. Terminate proc near
  1076. or ah,ah ;LPT port?
  1077. jns Terminate10 ; No, process COM port
  1078. .errnz LPTx-10000000b
  1079. Terminate5:
  1080. call ReleasePort386 ; give port back to 386...
  1081. jmp Terminate50 ;That's all
  1082. ;-----------------------------------------------------------------------;
  1083. ; It is a com port!
  1084. ;
  1085. ; We delay for a bit while the last character finishes transmitting
  1086. ; Then we drop DTR and RTS, and disable the interrupt generation at
  1087. ; the 8250. Even if fRTSDisable or fDTRDisable is set, those lines
  1088. ; will be dropped when the port is closed.
  1089. ;-----------------------------------------------------------------------;
  1090. ;
  1091. ; When the OUT2 bit is reset to 0 to disable interrupts, many ports
  1092. ; generate an interrupt which can not be identified, because the the
  1093. ; interrupt ID register will not be set. To work around this hardware
  1094. ; problem we first mask the IRQ, then set the port into loopback mode
  1095. ; and output a NULL to generate a receive interrupt request. Then we
  1096. ; reset OUT2 and unmask the IRQ. This will cause the interrupt to occur
  1097. ; and the interrupt handler will be able to correctly identify the
  1098. ; interrupt as coming from the com port.
  1099. Terminate10:
  1100. inc dx ;Disable chip interrupts
  1101. .errnz ACE_IER-ACE_RBR-1
  1102. mov al, ACE_ERBFI ; except receive
  1103. out dx,al
  1104. call FlagNotActive ; don't need to check for postmessage
  1105. ; on timer ticks
  1106. add dl,ACE_LSR-ACE_IER ;--> line status register
  1107. iodelay
  1108. Terminate20:
  1109. in al,dx ;Wait until xmit is empty
  1110. ifdef NEC_98
  1111. iodelay ;1994.08.01 KBNES
  1112. endif ; NEC_98
  1113. and al,ACE_THRE+ACE_TSRE
  1114. cmp al,ACE_THRE+ACE_TSRE
  1115. jne Terminate20 ;Not empty yet
  1116. Terminate30:
  1117. xor al, al
  1118. test EFlags[si], fFIFOpre ;Q: leave FIFO enabled?
  1119. jz short @F ; N:
  1120. mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO
  1121. @@:
  1122. sub dl, ACE_LSR-ACE_FCR
  1123. out dx, al
  1124. iodelay
  1125. call MaskIRQ
  1126. add dl, ACE_MCR-ACE_FCR ;--> Modem Control Register
  1127. in al,dx
  1128. iodelay
  1129. mov ah, al
  1130. or al,ACE_LOOP ; turn on loopback
  1131. out dx, al
  1132. iodelay
  1133. sub dl, ACE_MCR-ACE_THR
  1134. xor al, al
  1135. out dx, al ; output a NULL to generate an int
  1136. iodelay
  1137. add dl, ACE_LSR-ACE_THR
  1138. Terminate35:
  1139. in al,dx ;Wait until xmit is empty
  1140. ifdef NEC_98
  1141. iodelay ;1994.08.01 KBNES
  1142. endif ; NEC_98
  1143. and al,ACE_THRE+ACE_TSRE
  1144. cmp al,ACE_THRE+ACE_TSRE
  1145. jne Terminate35 ;Not empty yet
  1146. mov al, ah
  1147. dec dl ; now clear OUT2 and loopback
  1148. .errnz ACE_LSR-ACE_MCR-1
  1149. and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so
  1150. out dx,al ; but tri-state IRQ line
  1151. ifdef NEC_98
  1152. iodelay ;1994.08.01 KBNES
  1153. endif ; NEC_98
  1154. call UnmaskIRQ ; this will cause the receive int
  1155. ; to occur and be processed
  1156. sub dl, ACE_MCR-ACE_IER ; clear the receive int enable
  1157. xor al, al
  1158. out dx, al
  1159. ifdef NEC_98
  1160. iodelay ;1994.08.01 KBNES
  1161. endif ; NEC_98
  1162. dec dx
  1163. .errnz ACE_IER-ACE_RBR-1
  1164. call MaskIRQ
  1165. ;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE!
  1166. ;
  1167. ; Terminate45 is a secondary entrypoint into this routine--it's called
  1168. ; by the initialization code when that code is unable to properly init
  1169. ; a com port and needs to clean-up the mess it's made.
  1170. ;
  1171. ;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE!
  1172. Terminate45:
  1173. push cx ;Save original cx
  1174. push bx ;Save original bx
  1175. cmp [fVPICD], 0 ;Q: VPICD bimodel services available?
  1176. jl short @F ; N:
  1177. mov ax, ds ; Y: use them
  1178. mov es, ax
  1179. lea di, [si+SIZE ComDEB]
  1180. mov ax, VPICD_Remove_Handler
  1181. call [lpfnVPICD]
  1182. @@:
  1183. mov di, [si.IRQhook]
  1184. dec [di.HookCnt] ;Q: last port using IRQ?
  1185. jne short Terminate495 ; N: unmask IRQ again
  1186. mov al, 0FFh
  1187. xchg al, [di.VecN] ;Interrupt vector number
  1188. cmp al, 0FFh ;Q: IRQ vector hooked?
  1189. je short Terminate49 ; no...
  1190. IFDEF No_DOSX_Bimodal_Services
  1191. cmp [Using_DPMI], 0
  1192. jz short term_no_dpmi
  1193. ;
  1194. ; unhook RM vector thru DPMI for standard mode
  1195. ;
  1196. push ax
  1197. mov ax, Int31_Get_Version SHL 8
  1198. int 31h
  1199. mov bl, [si.IntVecNum]
  1200. mov bh, bl
  1201. add bl, dh ; assume master PIC
  1202. sub bh, 8 ;Q: IRQ in master?
  1203. jb @f ; Y: add master's base vec
  1204. add bh, dl ; N: add slave's base vec
  1205. mov bl, bh
  1206. @@:
  1207. mov dx, wo [di.RM_OldIntVec][0]
  1208. mov cx, wo [di.RM_OldIntVec][2]
  1209. mov ax, Set_RM_IntVector
  1210. int 31h
  1211. pop ax
  1212. term_no_dpmi:
  1213. ENDIF
  1214. mov dx, __WinFlags ;In Standard mode the PIC interrupt
  1215. test dl, WF_STANDARD ; priorities are changed to favor
  1216. jz Terminate48 ; the comm ports.
  1217. call Rotate_PIC ;This port no longer needs priority
  1218. Terminate48:
  1219. ; *** reset int vector to it's previous state
  1220. assumes ds,nothing
  1221. push ds ;Save original DS [rkh] ...
  1222. lds dx, [di.OldIntVec]
  1223. mov ah, 25h ;DOS Set Vector Function
  1224. int 21h ;Set the DOS vector
  1225. pop ds ;Original DS
  1226. assumes ds,data
  1227. ; *** interrupt vectors have been reset if needed at this point ***
  1228. ;
  1229. Terminate49:
  1230. mov cl, [di.OldMask]
  1231. ; Set the 8259 interrupt mask bit for this IRQ. Leave interrupts enabled
  1232. ; if they were already enabled when the comm port was initialized by us.
  1233. or cl, cl
  1234. jnz @f
  1235. Terminate495:
  1236. call UnmaskIRQ
  1237. @@:
  1238. xor ax, ax
  1239. xchg ax, [si.NextDEB]
  1240. cmp [di.First_DEB], si ;Q: DEB first for IRQ hook?
  1241. je short Terminate46 ; Y:
  1242. mov bx, [di.First_DEB] ; N: get first
  1243. Terminate453:
  1244. cmp [bx.NextDEB], si ;Q: does this DEB point to one terminating?
  1245. je Terminate455 ; Y:
  1246. mov bx, [bx.NextDEB] ; N: get next DEB
  1247. jmp Terminate453
  1248. Terminate455:
  1249. mov [bx.NextDEB], ax ; link previous DEB to NextDEB
  1250. jmp short Terminate47
  1251. Terminate46:
  1252. mov [di.First_DEB], ax ; point IRQ hook at NextDEB
  1253. Terminate47:
  1254. pop bx ;Original BX
  1255. ifndef NEC_98
  1256. call ReleaseCOMport386 ; give port back to 386...
  1257. endif ; NEC_98
  1258. pop cx ;Original CX
  1259. Terminate50: ;Also called from $INICOM !
  1260. xor ax,ax ;Indicate no error
  1261. ret ;Port is closed and deallocated
  1262. Terminate endp
  1263. page
  1264. ;----------------------------Public Routine-----------------------------;
  1265. ;
  1266. ; $ENANOTIFY - Enable Event Notification
  1267. ;
  1268. ; Entry:
  1269. ; AH = Device ID
  1270. ; BX = Window handle for PostMessage
  1271. ; CX = Receive threshold
  1272. ; DX = Transmit threshold
  1273. ; Returns:
  1274. ; AX = 1, if no errors occured
  1275. ; Error Returns:
  1276. ; AX = 0
  1277. ; Registers Preserved:
  1278. ; BX,SI,DI,DS
  1279. ; Registers Destroyed:
  1280. ; AX,CX,DX,ES,FLAGS
  1281. ; History:
  1282. ;-----------------------------------------------------------------------;
  1283. ;------------------------------Pseudo-Code------------------------------;
  1284. ; {
  1285. ; }
  1286. ;-----------------------------------------------------------------------;
  1287. assumes ds,Data
  1288. assumes es,nothing
  1289. public $ENANOTIFY
  1290. $ENANOTIFY proc near
  1291. push si
  1292. call GetDEB
  1293. mov ax, 0
  1294. jc scb_exit
  1295. mov ax, cx
  1296. inc ax
  1297. jz short scb_recv_ok
  1298. cmp cx, [si.QInSize] ;Q: receive threshold reasonable?
  1299. jb short scb_recv_ok ; Y:
  1300. %OUT should we return an error, if thresholds invalid?
  1301. mov cx, [si.QInSize] ; N:
  1302. sub cx, 10
  1303. scb_recv_ok:
  1304. inc dx
  1305. jz short scb_send_ok
  1306. dec dx
  1307. cmp dx, [si.QOutSize] ;Q: receive threshold reasonable?
  1308. jb short scb_send_ok ; Y:
  1309. mov dx, [si.QOutSize] ; N:
  1310. sub dx, 10
  1311. scb_send_ok:
  1312. mov [si.NotifyHandle], bx
  1313. mov [si.NotifyFlagsHI], CN_Notify
  1314. or bx, bx ;Q: null callback?
  1315. jnz scb_save_thresholds ; N: save thresholds
  1316. or cx, -1 ; Y: zero thresholds
  1317. xor dx, dx
  1318. mov [si.NotifyFlagsHI], 0
  1319. scb_save_thresholds:
  1320. mov [si.RecvTrigger], cx
  1321. mov [si.SendTrigger], dx
  1322. or [si.NotifyFlagsHI], CN_TRANSMIT ; we don't want to send
  1323. ; a transmit trigger notification until
  1324. ; the transmit buffer has been filled
  1325. ; above the trigger level and then
  1326. ; emptied below it again!
  1327. cmp wo lpPostMessage[2], 0 ;Q: gotten addr of PostMessage yet?
  1328. jne short scb_good ; Y:
  1329. push ds ; N: get module handle of USER
  1330. lea ax, szUser
  1331. push ax
  1332. cCall GetModuleHandle
  1333. push ax ; module handle
  1334. mov ax, POSTMESSAGE
  1335. cwd
  1336. push dx
  1337. push ax
  1338. cCall GetProcAddress
  1339. mov wo lpPostMessage[0], ax ; save received proc address
  1340. mov wo lpPostMessage[2], dx
  1341. scb_good:
  1342. mov ax, 1
  1343. scb_exit:
  1344. pop si
  1345. ret
  1346. $ENANOTIFY endp
  1347. page
  1348. ;----------------------------Public Routine-----------------------------;
  1349. ;
  1350. ; $SETQUE - Set up Queue Pointers
  1351. ;
  1352. ; Sets pointers to Receive and Transmit Queues, as provided by the
  1353. ; caller, and initializes those queues to be empty.
  1354. ;
  1355. ; Queues must be set before $INICOM is called!
  1356. ;
  1357. ; Entry:
  1358. ; AH = Device ID
  1359. ; ES:BX --> Queue Definition Block
  1360. ; Returns:
  1361. ; AX = 0 if no errors occured
  1362. ; Error Returns:
  1363. ; AX = error code
  1364. ; Registers Preserved:
  1365. ; BX,DX,SI,DI,DS
  1366. ; Registers Destroyed:
  1367. ; AX,CX,ES,FLAGS
  1368. ; History:
  1369. ;-----------------------------------------------------------------------;
  1370. ;------------------------------Pseudo-Code------------------------------;
  1371. ; {
  1372. ; }
  1373. ;-----------------------------------------------------------------------;
  1374. assumes ds,Data
  1375. assumes es,nothing
  1376. public $SETQUE
  1377. $SETQUE proc near
  1378. push si ;These will be used
  1379. push di
  1380. call GetDEB ;Get DEB
  1381. jc SetQue10 ;Invalid, ignore the call
  1382. js SetQue10 ;Ignore call for LPT ports
  1383. push ds ;Set ds:si --> QDB
  1384. push es ;Set es:di --> to ComDCB.QInAddr
  1385. pop ds
  1386. assumes ds,nothing
  1387. pop es
  1388. assumes es,Data
  1389. lea di,QInAddr[si]
  1390. mov si,bx
  1391. cld
  1392. FCLI ;No one else can play with queues
  1393. movsw ; QInAddr = QueueRxAddr
  1394. movsw
  1395. .errnz QueueRxAddr
  1396. sub si, 4 ; AltQInAddr = QueueRxAddr
  1397. mov cx, 5 ; QInSize = QueueRxSize
  1398. rep movsw ; QOutAddr = QueueTxAddr
  1399. sub si, 4
  1400. mov cx, 3 ; AltQOutAddr = QueueTxAddr
  1401. rep movsw ; QOutSize = QueueTxSize
  1402. xor ax,ax ;Will do some zero filling
  1403. mov cl,(EFlags-QInCount)/2
  1404. .errnz (EFlags-QInCount) AND 0FE01h
  1405. rep stosw
  1406. FSTI
  1407. push es ;Restore the data segment
  1408. pop ds
  1409. assumes ds,Data
  1410. assumes es,nothing
  1411. SetQue10:
  1412. pop di ;Restore saved registers
  1413. pop si
  1414. ret
  1415. ; The above code made a few assumptions about how memory
  1416. ; was allocated within the structures:
  1417. .errnz AltQInAddr-QInAddr-4
  1418. .errnz (QueueRxSize-QueueRxAddr)-(QInSize-AltQInAddr)
  1419. .errnz (QueueTxAddr-QueueRxSize)-(QOutAddr-QInSize)
  1420. .errnz AltQOutAddr-QOutAddr-4
  1421. .errnz (QueueTxSize-QueueTxAddr)-(QOutSize-AltQOutAddr)
  1422. .errnz QueueRxSize-QueueRxAddr-4
  1423. .errnz QueueTxAddr-QueueRxSize-2
  1424. .errnz QueueTxSize-QueueTxAddr-4
  1425. .errnz QInSize-AltQInAddr-4
  1426. .errnz QOutAddr-QInSize-2
  1427. .errnz QOutSize-AltQOutAddr-4
  1428. .errnz QInCount-QOutSize-2
  1429. .errnz QInGet-QInCount-2
  1430. .errnz QInPut-QInGet-2
  1431. .errnz QOutCount-QInPut-2
  1432. .errnz QOutGet-QOutCount-2
  1433. .errnz QOutPut-QOutGet-2
  1434. .errnz EFlags-QOutPut-2 ;First non-queue item
  1435. $SETQUE endp
  1436. page
  1437. ;----------------------------Public Routine-----------------------------;
  1438. ;
  1439. ; $SETCOM - Set Communications parameters
  1440. ;
  1441. ; Re-initalizes the requested port if present, and sets up the
  1442. ; port with the given attributes when they are valid.
  1443. ;
  1444. ; For LPT ports, just copies whatever is given since it's ignored
  1445. ; anyway.
  1446. ;
  1447. ; Entry:
  1448. ; ES:BX --> DCB with all fields set.
  1449. ; Returns:
  1450. ; 'Z' Set if no errors occured
  1451. ; AX = 0
  1452. ; Error Returns:
  1453. ; 'Z' clear if errors occured
  1454. ; AX = initialization error code.
  1455. ; Registers Destroyed:
  1456. ; AX,BX,CX,DX,ES,FLAGS
  1457. ; History:
  1458. ;-----------------------------------------------------------------------;
  1459. ;------------------------------Pseudo-Code------------------------------;
  1460. ; {
  1461. ; }
  1462. ;-----------------------------------------------------------------------;
  1463. assumes ds,Data
  1464. assumes es,nothing
  1465. public $SETCOM
  1466. $SETCOM proc near
  1467. cld
  1468. push si
  1469. push di
  1470. mov ah,es:[bx.DCB_Id] ;Get device i.d.
  1471. call GetDEB ;Get DEB pointer in SI
  1472. mov ax,IE_BadID ;Assume unknown device
  1473. jc SetCom10 ;Invalid device, return error
  1474. jns SetCom20 ;COM port
  1475. call SetCom100 ;Copy the DCB
  1476. SetCom5:
  1477. xor ax,ax ;Show no error
  1478. SetCom10:
  1479. or ax,ax ;Set/clear 'Z'
  1480. pop di ; and exit
  1481. pop si
  1482. ret
  1483. ;-----------------------------------------------------------------------;
  1484. ; Have a comm device, check all the serial parameters to make
  1485. ; sure they are correct before moving the new DCB into our space
  1486. ; and changing the ACE parameters.
  1487. ;-----------------------------------------------------------------------;
  1488. SetCom20:
  1489. call SetCom300 ;Baud rate valid?
  1490. jcxz SetCom10 ; No, return error
  1491. call SetCom400 ;Byte size/parity/stop bits correct?
  1492. jc SetCom10 ; No, return error
  1493. ; The parameters seem correct. Copy the DCB into our space and
  1494. ; initialize the ACE with the new parameters
  1495. mov dx,Port[si] ;Disable interrupts from the 8250
  1496. inc dx
  1497. .errnz ACE_IER-1
  1498. xor ax,ax
  1499. out dx,al
  1500. ifdef NEC_98
  1501. iodelay ;1994.08.01 KBNES
  1502. endif ; NEC_98
  1503. call FlagNotActive
  1504. call SetCom100 ;Copy the DCB
  1505. mov bx,si ;Set ES:BX --> DCB
  1506. call SetCom200 ;Get timeout masks
  1507. xchg al,ah ;Want them in the correct registers
  1508. mov wo MSRMask[si],ax
  1509. .errnz MSRInfinite-MSRMask-1
  1510. call SetCom400 ;Get line control byte
  1511. push ax ; and save LCR value
  1512. inc dx ;--> LCR
  1513. inc dx
  1514. .errnz ACE_LCR-ACE_IER-2
  1515. or al,ACE_DLAB ;Want access to divisor latch
  1516. out dx,al
  1517. ifdef NEC_98
  1518. iodelay ;1994.08.01 KBNES
  1519. endif ; NEC_98
  1520. mov RxMask[si],ah ;Save Receive character mask
  1521. mov ax,di ;Get flags mask, error mask
  1522. and [si.DCB_Flags],ah ;Disable parity checking if no parity
  1523. mov ErrorMask[si],al ;Save line status error mask
  1524. call SetCom300 ;Get baud rate
  1525. sub dl,ACE_LCR-ACE_DLL ;--> LSB of divisor latch
  1526. mov al,cl
  1527. out dx,al
  1528. mov al,ch
  1529. inc dx ;--> MSB of divisor latch
  1530. .errnz ACE_DLM-ACE_DLL-1
  1531. iodelay
  1532. out dx,al
  1533. ifdef NEC_98
  1534. iodelay ;1994.08.01 KBNES
  1535. endif ; NEC_98
  1536. inc dx ;--> LCR and clear divisor access bit
  1537. inc dx
  1538. .errnz ACE_LCR-ACE_DLM-2
  1539. pop ax
  1540. out dx,al
  1541. ifdef NEC_98
  1542. iodelay ;1994.08.01 KBNES
  1543. endif ; NEC_98
  1544. inc dx ;--> Modem Control Register
  1545. .errnz ACE_MCR-ACE_LCR-1
  1546. ;-----------------------------------------------------------------------;
  1547. ; Compute initial state of DTR and RTS. If they have been disabled,
  1548. ; then do not raise them, and disallow being used as a handshaking
  1549. ; line. Also compute the bits to use as hardware handshake bits
  1550. ; (DTR and/or RTS as indicated, qualified with the disabled flags).
  1551. ;-----------------------------------------------------------------------;
  1552. mov al,[si.DCB_Flags] ;Align DTR/RTS disable flags for 8250
  1553. and al,fRTSDisable+fDTRDisable
  1554. rol al,1 ;d0 = DTR, d2 = RTS (1 = disabled)
  1555. shr al,1 ;'C'= DTR, d1 = RTS
  1556. adc al,0 ;d0 = DTR, d1 = RTS
  1557. .errnz fRTSDisable-00000010b
  1558. .errnz fDTRDisable-10000000b
  1559. .errnz ACE_DTR-00000001b
  1560. .errnz ACE_RTS-00000010b
  1561. mov ah,al ;Save disable mask
  1562. xor al,ACE_DTR+ACE_RTS+ACE_OUT2
  1563. out dx,al ;Set Modem Control Register
  1564. ifdef NEC_98
  1565. iodelay ;1994.08.01 KBNES
  1566. endif ; NEC_98
  1567. mov al,[si.DCB_Flags2] ;Get hardware handshake flags
  1568. rol al,1 ;Align flags as needed
  1569. rol al,1
  1570. rol al,1
  1571. and al,ACE_DTR+ACE_RTS ;Mask bits of interest
  1572. not ah ;Want inverse of disable mask
  1573. and al,ah ;al = bits to handshake with
  1574. mov HHSLines[si],al ;Save for interrupt code
  1575. .errnz fDTRFlow-00100000b
  1576. .errnz fRTSFlow-01000000b
  1577. .errnz ACE_DTR-00000001b
  1578. .errnz ACE_RTS-00000010b
  1579. mov al,[si.DCB_Flags] ;Compute the mask for the output
  1580. shl al,1 ; hardware handshake lines
  1581. and al,ACE_DSR+ACE_CTS
  1582. mov OutHHSLines[si],al
  1583. .errnz fOutXCTSFlow-00001000b
  1584. .errnz fOutXDSRFlow-00010000b
  1585. .errnz ACE_CTS-00010000b
  1586. .errnz ACE_DSR-00100000b
  1587. ; Compute the queue count where XOff should be issued (or hardware
  1588. ; lines dropped). This will prevent having to do it at interrupt
  1589. ; time.
  1590. mov ax,QInSize[si] ;Get where they want it
  1591. sub ax,[si.DCB_XoffLim] ; and compute queue count
  1592. mov XOffPoint[si],ax
  1593. ; Enable FIFO if possible when baudrate >= 4800
  1594. ;
  1595. sub dl,ACE_MCR - ACE_FCR ; dx = FCR
  1596. test EFlags[si], fNoFIFO ;Q: FIFO can be enabled?
  1597. jnz sc_nofifo ; N:
  1598. mov ax, [si.DCB_BaudRate]
  1599. cmp ax, 4800
  1600. jb sc_nofifo
  1601. cmp ah, -1 ;Q: baudrate index?
  1602. jne sc_fifo ; N: baudrate >= 4800, enable FIFO
  1603. cmp ax, CBR_4800
  1604. jb sc_nofifo
  1605. %OUT this isn't correct, if lower baudrates are assigned indices above CBR_4800
  1606. sc_fifo:
  1607. mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO
  1608. out dx, al ; attempt to enable FIFO
  1609. ifdef NEC_98
  1610. iodelay ;1994.08.01 KBNES
  1611. endif ; NEC_98
  1612. test EFlags[si], fFIFOchkd ;Q: FIFO detect been done?
  1613. jnz sc_fifodone ; Y: enabled FIFO
  1614. iodelay
  1615. .errnz ACE_IIDR-ACE_FCR
  1616. in al, dx
  1617. ifdef NEC_98
  1618. iodelay ;1994.08.01 KBNES
  1619. endif ; NEC_98
  1620. or EFlags[si], fFIFOchkd
  1621. test al, ACE_FIFO_E2 ;Q: FIFO enabled?
  1622. jz short @F
  1623. test al, ACE_FIFO_E1 ;Q: 16550A detected?
  1624. jnz sc_fifodone ; Y: enabled FIFO
  1625. @@:
  1626. iodelay
  1627. or EFlags[si], fNoFIFO
  1628. sc_nofifo:
  1629. xor al, al
  1630. out dx, al
  1631. ifdef NEC_98
  1632. iodelay ;1994.08.01 KBNES
  1633. endif ; NEC_98
  1634. sc_fifodone:
  1635. sub dl,ACE_FCR-ACE_RBR ; dx -> RBR
  1636. ;
  1637. ; Delay for things to settle
  1638. ;
  1639. push dx
  1640. cCall GetSystemMsecCount
  1641. pop dx
  1642. mov cx, ax
  1643. delay_loop:
  1644. in al, dx ;Read it once
  1645. ifdef NEC_98
  1646. iodelay ;1994.08.01 KBNES
  1647. endif ; NEC_98
  1648. push dx
  1649. cCall GetSystemMsecCount
  1650. pop dx
  1651. sub ax, cx
  1652. cmp ax, DELAY_TIME ;Q: Timeout reached?
  1653. ifdef NEC_98
  1654. jb delay_loop ; N:
  1655. else ; NEC_98
  1656. ifndef WOW
  1657. jb delay_loop ; N:
  1658. endif
  1659. endif ; NEC_98
  1660. add dl,ACE_MSR ;--> Modem Status reg
  1661. in al,dx ;Throw away 1st status read
  1662. iodelay
  1663. in al,dx ;Save 2nd for MSRWait (Clear MSR int)
  1664. ifdef NEC_98
  1665. iodelay ;1994.08.01 KBNES
  1666. endif ; NEC_98
  1667. mov MSRShadow[si],al
  1668. ; Win 3.0 didn't check hardware handshaking until the line status changed.
  1669. ; Allow some apps to keep that behavior.
  1670. push dx
  1671. xor ax, ax
  1672. cCall GetAppCompatFlags,<ax>
  1673. pop dx
  1674. test ax, GACF_DELAYHWHNDSHAKECHK
  1675. jnz short sc_HHSup
  1676. ;
  1677. ; HACK FOR SOME MODEMS: apparently some modems set CTS, but don't set DSR
  1678. ; which means that COMM.DRV won't send if the app specifies that hardware
  1679. ; handshaking is based on CTS & DSR being set.
  1680. ;
  1681. mov ah,OutHHSLines[si]
  1682. mov al, MSRShadow[si]
  1683. and al,ah ;Only leave bits of interest
  1684. cmp al, ah ;Q: handshaking lines ok?
  1685. je short sc_HHSup ; Y:
  1686. cmp ah, ACE_CTS OR ACE_DSR ;Q: app looking for both high?
  1687. jne short sc_HHSdown ; N: skip hack
  1688. test [si.EFlags], fUseDSR ;Q: DSR is always significant?
  1689. jnz short sc_HHSdown ; Y: skip hack
  1690. cmp al, ACE_CTS ;Q: DSR low & CTS high
  1691. jne short sc_HHSdown ; N: skip hack
  1692. and ah, NOT ACE_DSR ; Y: ignore DSR line
  1693. mov OutHHSLines[si], ah
  1694. jmp short sc_HHSup
  1695. sc_HHSdown:
  1696. or [si.HSFlag], HHSDown OR HHSAlwaysDown ; flag handshaking down
  1697. sc_HHSup:
  1698. ;-----------------------------------------------------------------------;
  1699. ; Now, at last, interrupts can be enabled. Don't enable the
  1700. ; transmitter empty interrupt. It will be enabled by the first
  1701. ; call to KickTx.
  1702. ;-----------------------------------------------------------------------;
  1703. sub dl,ACE_MSR-ACE_IER ;--> Interrupt Enable Register
  1704. ; flag port as being active
  1705. push cx
  1706. mov cl, [si.DCB_Id]
  1707. mov ax, 1
  1708. shl ax, cl
  1709. or [activeCOMs], ax
  1710. pop cx
  1711. ifdef NEC_98
  1712. ;---------------------------------------------------------------Ins 940923 KBNES
  1713. ; Close process of system timer Ins 940923 KBNES
  1714. ;---------------------------------------------------------------Ins 940923 KBNES
  1715. push dx ; Ins 940924 KBNES
  1716. push ax ; Ins 940923 KBNES
  1717. mov ax,hTimer[si] ; Check hTimer Ins 940923 KBNES
  1718. or ax,ax ; TimerProcess Nothing? Ins 940923 KBNES
  1719. jz SetNoKillTimer ; Y:(Nothing) Ins 940923 KBNES
  1720. cCall KillSystemTimer,<ax> ; Kill Syatem Timer Ins 940923 KBNES
  1721. mov hTimer[si] ,00h ; Clear hTimer Ins 940923 KBNES
  1722. SetNoKillTimer: ; Ins 940923 KBNES
  1723. ;---------------------------------------------------------------Ins 940923 KBNES
  1724. ; make process of system timer Ins 940923 KBNES
  1725. ;---------------------------------------------------------------Ins 940923 KBNES
  1726. mov ax, 200 ; create 200msec timer Ins 940923 KBNES
  1727. push ax ; Ins 940923 KBNES
  1728. mov ax, _INTERRUPT ; Ins 940923 KBNES
  1729. push ax ; Ins 940923 KBNES
  1730. mov ax,TimerProcAdr[si] ;--> timer processor Ins 940923 KBNES
  1731. push ax ; Ins 940923 KBNES
  1732. call CreateSystemTimer ; ax = 0, if failed Ins 940923 KBNES
  1733. mov hTimer[si] ,ax ; Get hTimer Ins 940923 KBNES
  1734. SetCom3003: ; Ins 940923 KBNES
  1735. pop ax ; Ins 940923 KBNES
  1736. pop dx ; Ins 940924 KBNES
  1737. endif ; NEC_98
  1738. mov al,ACE_ERBFI+ACE_ELSI+ACE_EDSSI
  1739. FCLI
  1740. out dx,al ;Enable interrupts.
  1741. add dl,ACE_LSR-ACE_IER ;--> Line Status Register
  1742. iodelay
  1743. in al,dx ;Clear any Line Status interrupt
  1744. sub dl,ACE_LSR ;--> Receiver Buffer Register
  1745. iodelay
  1746. in al,dx ;Clear any Received Data interrupt
  1747. ifdef NEC_98
  1748. iodelay ;1994.08.01 KBNES
  1749. endif ; NEC_98
  1750. FSTI
  1751. jmp SetCom5 ;All done
  1752. $SETCOM endp
  1753. page
  1754. FlagNotActive proc near
  1755. push cx
  1756. mov cl, [si.DCB_Id]
  1757. mov ax, NOT 1
  1758. rol ax, cl
  1759. and [activeCOMs], ax
  1760. pop cx
  1761. ret
  1762. FlagNotActive endp
  1763. ;----------------------------Private-Routine----------------------------;
  1764. ;
  1765. ; SetCom100
  1766. ;
  1767. ; Copy the given DCB into the appropriate DEB. The check has
  1768. ; already been made to determine that the ID was valid, so
  1769. ; that check can be skipped.
  1770. ;
  1771. ; Entry:
  1772. ; ES:BX --> DCB
  1773. ; DS:SI --> DEB
  1774. ; Returns:
  1775. ; DS:SI --> DEB
  1776. ; ES = Data
  1777. ; Error Returns:
  1778. ; None
  1779. ; Registers Destroyed:
  1780. ; AX,CX,ES,DI,FLAGS
  1781. ; History:
  1782. ;-----------------------------------------------------------------------;
  1783. ;------------------------------Pseudo-Code------------------------------;
  1784. ; {
  1785. ; }
  1786. ;-----------------------------------------------------------------------;
  1787. assumes ds,Data
  1788. assumes es,nothing
  1789. SetCom100 proc near
  1790. push si ;Save DEB pointer
  1791. mov di,si
  1792. mov si,bx
  1793. push es
  1794. mov ax,ds
  1795. pop ds
  1796. assumes ds,nothing
  1797. mov es,ax
  1798. assumes es,Data
  1799. mov cx,DCBSize
  1800. cld
  1801. rep movsb
  1802. mov ds,ax
  1803. assumes ds,Data
  1804. pop si ;Restore DEB pointer
  1805. ret
  1806. SetCom100 endp
  1807. page
  1808. ;----------------------------Private-Routine----------------------------;
  1809. ;
  1810. ; SetCom200
  1811. ;
  1812. ; Based on whether or not a timeout has been specified for each
  1813. ; signal, set up a mask byte which is used to mask off lines for
  1814. ; which we wish to detect timeouts. 0 indicates that the line is
  1815. ; to be ignored.
  1816. ;
  1817. ; Also set up a mask to indicate those lines which are set for
  1818. ; infinite timeout. 1 indicates that the line has infinite
  1819. ; timeout.
  1820. ;
  1821. ; Entry:
  1822. ; ES:BX --> DCB
  1823. ; Returns:
  1824. ; ES:BX --> DCB
  1825. ; AH = lines to check
  1826. ; AL = lines with infinite timeout
  1827. ; Error Returns:
  1828. ; None
  1829. ; Registers Destroyed:
  1830. ; AX,CX,FLAGS
  1831. ; History:
  1832. ;-----------------------------------------------------------------------;
  1833. ;------------------------------Pseudo-Code------------------------------;
  1834. ; {
  1835. ; }
  1836. ;-----------------------------------------------------------------------;
  1837. assumes ds,Data
  1838. assumes es,nothing
  1839. SetCom200 proc near
  1840. xor ax,ax
  1841. xor cx,cx ;Get mask of lines with timeout = 0
  1842. call SetCom210
  1843. not al ;Invert result to get lines to check
  1844. and al,ACE_CTS+ACE_DSR+ACE_RLSD
  1845. xchg ah,al
  1846. dec cx ;Get mask of infinite timeouts
  1847. SetCom210:
  1848. cmp es:[bx.DCB_RlsTimeout],cx ;Timeout set to passed value?
  1849. jne SetCom220 ; No
  1850. or al,ACE_RLSD ; Yes, show checking line
  1851. SetCom220:
  1852. cmp es:[bx.DCB_CtsTimeout],cx ;Timeout set to passed value?
  1853. jne SetCom230 ; No
  1854. or al,ACE_CTS ; Yes, show checking line
  1855. SetCom230:
  1856. cmp es:[bx.DCB_DsrTimeout],cx ;Timeout set to passed value?
  1857. jne SetCom240 ; No
  1858. or al,ACE_DSR ; Yes, show checking line
  1859. SetCom240:
  1860. ret
  1861. SetCom200 endp
  1862. page
  1863. ;----------------------------Private-Routine----------------------------;
  1864. ;
  1865. ; SetCom300
  1866. ;
  1867. ; Calculate the correct baudrate divisor for the comm chip.
  1868. ;
  1869. ; Note that the baudrate is allowed to be any integer in the
  1870. ; range 2-19200. The divisor is computed as 115,200/baudrate.
  1871. ;
  1872. ; Entry:
  1873. ; ES:BX --> DCB
  1874. ; Returns:
  1875. ; ES:BX --> DCB
  1876. ; CX = baudrate
  1877. ; Error Returns:
  1878. ; CX = 0 if error
  1879. ; AX = error code if invalid baud rate
  1880. ; Registers Destroyed:
  1881. ; AX,CX,FLAGS
  1882. ; History:
  1883. ;-----------------------------------------------------------------------;
  1884. BaudRateByIndexTable label word
  1885. dw 1047 ; CBR_110
  1886. dw 384 ; CBR_300
  1887. dw 192 ; CBR_600
  1888. dw 96 ; CBR_1200
  1889. dw 48 ; CBR_2400
  1890. dw 24 ; CBR_4800
  1891. dw 12 ; CBR_9600
  1892. dw 9 ; CBR_14400
  1893. dw 6 ; CBR_19200
  1894. dw 0 ; 0FF19h (reserved)
  1895. dw 0 ; 0FF1Ah (reserved)
  1896. dw 3 ; CBR_38400
  1897. dw 0 ; 0FF1Ch (reserved)
  1898. dw 0 ; 0FF1Dh (reserved)
  1899. dw 0 ; 0FF1Eh (reserved)
  1900. dw 2 ; CBR_56000
  1901. ifdef NEC_98
  1902. dw 0 ; 0FF20h (reserved)
  1903. dw 0 ; 0FF21h (reserved)
  1904. dw 0 ; 0FF22h (reserved)
  1905. dw 1 ; CBR_128000
  1906. endif ; NEC_98
  1907. assumes ds,Data
  1908. assumes es,nothing
  1909. SetCom300 proc near
  1910. push dx
  1911. mov cx,es:[bx.DCB_BaudRate] ;Get requested baud rate
  1912. xor ax,ax ;Assume error
  1913. cmp cx, CBR_110 ;Q: baudrate specified as an index?
  1914. jae by_index
  1915. cmp cx,2 ;Within valid range?
  1916. jnae SetCom310 ; No, return error
  1917. mov dx,1 ;(dx:ax) = 115,200
  1918. mov ax,0C200h
  1919. div cx ;(ax) = 115,200/baud
  1920. SetCom310:
  1921. mov cx,ax ;(cx) = baud rate, or error code (0)
  1922. mov ax,IE_Baudrate ;Set error code incase bad baud
  1923. pop dx
  1924. ret
  1925. by_index:
  1926. ifdef NEC_98
  1927. cmp cx, CBR_128000 ;ins 95.03.25 KBNES
  1928. else ; NEC_98
  1929. cmp cx, CBR_56000 ;Q: above supported?
  1930. endif ; NEC_98
  1931. ja SetCom310 ; Y: return error
  1932. push bx
  1933. mov bx, cx
  1934. sub bx, CBR_110
  1935. shl bx, 1
  1936. mov ax, cs:[bx+BaudRateByIndexTable] ; get divisor
  1937. pop bx
  1938. jmp SetCom310 ; Y: return error
  1939. SetCom300 endp
  1940. page
  1941. ;----------------------------Private-Routine----------------------------;
  1942. ;
  1943. ; SetCom400
  1944. ;
  1945. ; Check the line configuration (Parity, Stop bits, Byte size)
  1946. ;
  1947. ; Entry:
  1948. ; ES:BX --> DCB
  1949. ; Returns:
  1950. ; ES:BX --> DCB
  1951. ; 'C' clear if OK
  1952. ; AL = Line Control Register
  1953. ; AH = RxMask
  1954. ; DI[15:8] = Flags mask (to remove parity checking)
  1955. ; DI[7:0] = Error mask (to remove parity error)
  1956. ; Error Returns:
  1957. ; 'C' set if error
  1958. ; AX = error code
  1959. ; Registers Destroyed:
  1960. ; AX,CX,DI,FLAGS
  1961. ; History:
  1962. ;-----------------------------------------------------------------------;
  1963. ;------------------------------Pseudo-Code------------------------------;
  1964. ; {
  1965. ; }
  1966. ;-----------------------------------------------------------------------;
  1967. assumes ds,Data
  1968. assumes es,nothing
  1969. SetCom400 proc near
  1970. mov ax,wo es:[bx.DCB_ByteSize] ;al = byte size, ah = parity
  1971. cmp ah,SpaceParity ;Parity out of range?
  1972. ja SetCom470 ; Yes, return error
  1973. mov di,0FF00h+ACE_OR+ACE_PE+ACE_FE+ACE_BI
  1974. or ah,ah ;Is parity "NONE"?
  1975. jnz SetCom410 ; No, something is there for parity
  1976. xor di,(fParity*256)+ACE_PE ;Disable parity checking
  1977. SetCom410:
  1978. cmp al,8 ;Byte size out of range?
  1979. ja SetCom460 ; Yes, error
  1980. SetCom420:
  1981. sub al,5 ;Shift byte size to bits 0&1
  1982. .errnz ACE_WLS-00000011b ;Word length must be these bits
  1983. jc SetCom460 ;Byte size is illegal, return error
  1984. add ah,ah ;Map parity to ACE bits
  1985. jz SetCom430 ;0=>0, 1=>1, 2=>3, 3=>5, 4=>7
  1986. dec ah
  1987. SetCom430:
  1988. shl ah,1 ;Align with 8250 parity bits
  1989. shl ah,1
  1990. shl ah,1
  1991. or al,ah ;Add to byte size
  1992. .errnz NoParity-0
  1993. .errnz OddParity-1
  1994. .errnz EvenParity-2
  1995. .errnz MarkParity-3
  1996. .errnz SpaceParity-4
  1997. .errnz ACE_PEN-00001000b
  1998. .errnz ACE_PSB-00110000b
  1999. .errnz ACE_EPS-00010000b
  2000. .errnz ACE_SP-00100000b
  2001. or al,ACE_2SB ;Assume 2 stop bits
  2002. mov ah,es:[bx.DCB_StopBits] ;Get # of stop bits 0=1,1/2= .GT. 1
  2003. or ah,ah ;Out of range?
  2004. js SetCom470 ; Yes, return error
  2005. jz SetCom440 ;One stop bit
  2006. sub ah,2
  2007. jz SetCom450 ;Two stop bits
  2008. jns SetCom470 ;Not 1.5, return error
  2009. test al,ACE_WLS ;1.5 stop bits, 5 bit words?
  2010. jnz SetCom470 ; No, illegal
  2011. .errnz OneStopBit-0
  2012. .errnz One5StopBits-1
  2013. .errnz TwoStopBits-2
  2014. .errnz ACE_5BW
  2015. SetCom440:
  2016. and al,NOT ACE_2SB ;Show 1 (or 1.5) stop bit(s)
  2017. ; From the byte size, get a mask to be used for stripping
  2018. ; off unused bits as the characters are received.
  2019. SetCom450:
  2020. push dx
  2021. mov cl,es:[bx.DCB_ByteSize] ;Get data byte size
  2022. mov dx,00FFh ;Turn into mask by shifting bits
  2023. shl dx,cl
  2024. mov ah,dh ;Return mask in ah
  2025. pop dx
  2026. clc ;Show all is fine
  2027. ret
  2028. SetCom460:
  2029. mov ax,IE_ByteSize ;Show byte size is wrong
  2030. stc ;Show error
  2031. ret
  2032. SetCom470:
  2033. mov ax,IE_Default ;Show something is wrong
  2034. stc ;Show error
  2035. ret
  2036. SetCom400 endp
  2037. page
  2038. ;----------------------------------------------------------------------------
  2039. ; SuspendOpenCommPorts:
  2040. ;
  2041. ; This routine is called from 286 Winoldaps to simply deinstall the comm port
  2042. ; hooks.
  2043. ;----------------------------------------------------------------------------
  2044. cProc SuspendOpenCommPorts,<FAR,PUBLIC,PASCAL>
  2045. cBegin nogen
  2046. assumes cs,Code
  2047. assumes ds,Data
  2048. %OUT not masking IRQ's
  2049. ; Nothing to do under 3.1!
  2050. ret
  2051. cEnd nogen
  2052. ;----------------------------------------------------------------------------;
  2053. ; ReactivateOpenCommPorts: ;
  2054. ; ;
  2055. ; This routine reinstalls the comm hooks in real mode and reads the 8250 ;
  2056. ; data and status registers to clear pending interrupts. ;
  2057. ;----------------------------------------------------------------------------;
  2058. cProc ReactivateOpenCommPorts,<FAR,PASCAL,PUBLIC>,<si,di>
  2059. cBegin
  2060. call Rotate_PIC ;make comm ports highest priority
  2061. mov cx, MAXCOM+1
  2062. mov di,dataOffset COMptrs
  2063. rcp_loop:
  2064. mov si, [di]
  2065. mov dx, Port[si]
  2066. or dx, dx
  2067. jz @f
  2068. call InitAPort ;read comm port regs to clr pending ints
  2069. @@:
  2070. add di, 2
  2071. loop rcp_loop
  2072. cEnd
  2073. ;----------------------------------------------------------------------------;
  2074. ; InitAPort: ;
  2075. ; ;
  2076. ; reads the data,status & IIR registers of a port (has to be 8250!) ;
  2077. ; ;
  2078. ; If the port has an out queue pending, then this woutine will also start ;
  2079. ; the transmit process by faking a comm interrupt. ;
  2080. ;----------------------------------------------------------------------------;
  2081. public InitAPort
  2082. InitAPort proc near
  2083. add dl,ACE_RBR ;dx=receive buffer register
  2084. in al,dx ;read the data port
  2085. ifdef NEC_98
  2086. iodelay ;1994.08.01 KBNES
  2087. else ; NEC_98
  2088. jmp short $+2 ;i/o delay
  2089. endif ; NEC_98
  2090. add dl,ACE_LSR - ACE_RBR ;get to the status port
  2091. in al,dx ;read it too.
  2092. ifdef NEC_98
  2093. iodelay ;1994.08.01 KBNES
  2094. else ; NEC_98
  2095. jmp short $+2 ;i/o delay
  2096. endif ; NEC_98
  2097. add dl,ACE_IIDR - ACE_LSR ;get to the line status register
  2098. in al,dx ;read it once more
  2099. ifdef NEC_98
  2100. iodelay ;1994.08.01 KBNES
  2101. else ; NEC_98
  2102. jmp short $+2 ;i/o delay
  2103. endif ; NEC_98
  2104. add dl,ACE_MSR - ACE_IIDR ;get to the modem status register
  2105. in al,dx ;read it once more
  2106. ifdef NEC_98
  2107. iodelay ;1994.08.01 KBNES
  2108. else ; NEC_98
  2109. jmp short $+2 ;i/o delay
  2110. endif ; NEC_98
  2111. add dl,ACE_RBR - ACE_MSR ;get to the receive buffer register
  2112. in al,dx ;read it once more
  2113. ifdef NEC_98
  2114. iodelay ;1994.08.01 KBNES
  2115. else ; NEC_98
  2116. jmp short $+2 ;i/o delay
  2117. endif ; NEC_98
  2118. call UnmaskIRQ
  2119. ; now if the port has characters pending to be sent out then we must fake a
  2120. ; comm interrupt.
  2121. cmp [si].QOutCount,0 ;characters pending to be sent ?
  2122. jz @f ;no.
  2123. FCLI ;disable interrupts
  2124. call FakeCOMIntFar ;fake an interrupt
  2125. FSTI ;renable interrupts
  2126. @@:
  2127. ret
  2128. InitAPort endp
  2129. page
  2130. ;----------------------------Public Routine-----------------------------;
  2131. ;
  2132. ; $DCBPtr - Return Pointer To DCB
  2133. ;
  2134. ; Returns a long pointer to the DCB for the requested device.
  2135. ;
  2136. ; Entry:
  2137. ; AH = Device ID
  2138. ; Returns:
  2139. ; DX:AX = pointer to DCB.
  2140. ; Error Returns:
  2141. ; DX:AX = 0
  2142. ; Registers Preserved:
  2143. ; SI,DI,DS
  2144. ; Registers Destroyed:
  2145. ; BX,CX,ES,FLAGS
  2146. ; History:
  2147. ;-----------------------------------------------------------------------;
  2148. ;------------------------------Pseudo-Code------------------------------;
  2149. ; {
  2150. ; }
  2151. ;-----------------------------------------------------------------------;
  2152. assumes ds,Data
  2153. assumes es,nothing
  2154. public $DCBPTR
  2155. $DCBPTR proc near
  2156. push si
  2157. xor dx,dx
  2158. call GetDEB ;Get pointer to DEB
  2159. mov ax,dx
  2160. jc DCBPtr10 ;Jump if invalid device
  2161. mov ax,si ;else return value here
  2162. mov dx,ds
  2163. DCBPtr10:
  2164. pop si
  2165. ret
  2166. $DCBPTR endp
  2167. page
  2168. ;----------------------------Private-Routine----------------------------;
  2169. ;
  2170. ; GetDEB - Get Pointer To Device's DEB
  2171. ;
  2172. ; Returns a pointer to appropriate DEB, based on device number.
  2173. ;
  2174. ; Entry:
  2175. ; AH = cid
  2176. ; Returns:
  2177. ; 'C' clear
  2178. ; 'S' set if LPT device
  2179. ; DS:SI --> DEB is valid cid
  2180. ; AH = cid
  2181. ; Error Returns:
  2182. ; 'C' set if error (cid is invalid)
  2183. ; AX = 8000h
  2184. ; Registers Preserved:
  2185. ; BX,CX,DX,DI,DS,ES
  2186. ; Registers Destroyed:
  2187. ; AX,SI,FLAGS
  2188. ; History:
  2189. ;-----------------------------------------------------------------------;
  2190. ;------------------------------Pseudo-Code------------------------------;
  2191. ; {
  2192. ; }
  2193. ;-----------------------------------------------------------------------;
  2194. assumes ds,Data
  2195. assumes es,nothing
  2196. public GetDEB ;Public for debugging
  2197. GetDEB proc near
  2198. push cx
  2199. mov cl, ah
  2200. and cx, (NOT LPTx AND 0FFh)
  2201. test ah, ah ;Q: LPT id?
  2202. ifdef NEC_98
  2203. js short GetDEB30 ; Y: error if LPT
  2204. else ; NEC_98
  2205. js short GetDEB10 ; Y:
  2206. endif ; NEC_98
  2207. .errnz LPTx - 80h
  2208. cmp ah, MAXCOM ;Q: Within range?
  2209. ja GetDEB30 ; N: return invalid ID
  2210. shl cx, 1
  2211. mov si, cx
  2212. mov si, [si+COMptrs]
  2213. ifndef NEC_98
  2214. jmp short GetDEB20
  2215. GetDEB10:
  2216. cmp ah, LPTx+MAXLPT ;Q: Within range?
  2217. ja GetDEB30 ; N: return invalid ID
  2218. mov si, DataOFFSET LPT1
  2219. jcxz GetDEB20
  2220. GetDEB15:
  2221. add si, SIZE LptDEB
  2222. loop GetDEB15
  2223. GetDEB20:
  2224. endif ; NEC_98
  2225. pop cx
  2226. or ah, ah ; clear Carry & set S, if LPT port
  2227. ret
  2228. GetDEB30:
  2229. pop cx
  2230. mov ax,8000h ;Set error code
  2231. stc ;Set 'C' to show error
  2232. ret
  2233. GetDEB endp
  2234. page
  2235. CvtHex proc near
  2236. ; assume DS=SS
  2237. push si
  2238. mov cl, 4
  2239. mov si, di
  2240. xor dx, dx
  2241. cld
  2242. ch_lp:
  2243. lodsb
  2244. sub al, '0' ;Q: char < '0'
  2245. jb ch_exit ; Y: return
  2246. cmp al, 9 ;Q: char <= '9'
  2247. jbe ch_got_digit ; Y: move digit into result
  2248. sub al, 'A' - '0' ;Q: char < 'A'
  2249. jb ch_exit ; Y: return
  2250. add al, 10
  2251. cmp al, 15 ;Q: char <= 'F'
  2252. jbe ch_got_digit ; Y: move hex char into result
  2253. sub al, 10 + 'a' - 'A' ;Q: char < 'a'
  2254. jb ch_exit ; Y: return
  2255. add al, 10
  2256. cmp al, 15 ;Q: char > 'f'
  2257. ja ch_exit ; Y: return
  2258. ch_got_digit:
  2259. shl dx, cl
  2260. or dl, al
  2261. jmp ch_lp
  2262. ch_exit:
  2263. mov ax, dx
  2264. pop si
  2265. ret
  2266. CvtHex endp
  2267. .286
  2268. ; attempt to read base from SYSTEM.INI
  2269. GetComBase proc near
  2270. push ds ; save our DS
  2271. sub sp, 6
  2272. mov di, sp
  2273. mov byte ptr ss:[di], 0
  2274. push ds
  2275. push DataOFFSET lpCommSection
  2276. push ds
  2277. push DataOFFSET lpCommBase
  2278. push ss ; temp buffer
  2279. push di
  2280. push ss ; default = temp buffer
  2281. push di
  2282. push 5
  2283. push ds
  2284. push DataOFFSET lpSYSTEMINI
  2285. mov cx, ss ; temporarily assign DS=SS
  2286. mov ds, cx ; to allow KERNEL to thunk
  2287. assumes ds,nothing
  2288. call GetPrivateProfileString ; our segment in real mode
  2289. or ax, ax
  2290. jz short gcb_exit
  2291. call CvtHex ; DS still equal to SS
  2292. gcb_exit:
  2293. add sp, 6
  2294. pop ds ; restore our DS
  2295. assumes ds,Data
  2296. ret
  2297. GetComBase endp
  2298. GetPortIRQ proc near
  2299. push ds ; save our DS
  2300. push ds
  2301. push DataOFFSET lpCommSection
  2302. push ds
  2303. push DataOFFSET lpCommIrq
  2304. push bx
  2305. mov bl, [si.DCB_Id]
  2306. cmp bl, 4
  2307. jb @f
  2308. mov bl, 4
  2309. @@:
  2310. xor bh, bh
  2311. mov bl, [bx+default_table]
  2312. mov cx, bx
  2313. pop bx
  2314. push cx ; default
  2315. push ds
  2316. push DataOFFSET lpSYSTEMINI
  2317. mov cx, ss ; temporarily assign DS=SS
  2318. mov ds, cx ; to allow KERNEL to thunk
  2319. assumes ds,nothing
  2320. call GetPrivateProfileInt ; our segment in real mode
  2321. pop ds ; restore our DS
  2322. assumes ds,Data
  2323. ret
  2324. GetPortIRQ endp
  2325. GetPortFlags proc near
  2326. mov al, [si.DCB_Id]
  2327. .erre MAXCOM LT 9 ;only single digit port numbers supported
  2328. add al, '1'
  2329. mov [CommFIFOX], al
  2330. mov [CommDSRx], al
  2331. call GetPortFIFO
  2332. call GetPortDSR
  2333. ret
  2334. GetPortFlags endp
  2335. GetPortFIFO proc near
  2336. push ds ; save our DS
  2337. push ds
  2338. push DataOFFSET lpCommSection
  2339. push ds
  2340. push DataOFFSET lpCommFifo
  2341. push 2
  2342. push ds
  2343. push DataOFFSET lpSYSTEMINI
  2344. mov cx, ss ; temporarily assign DS=SS
  2345. mov ds, cx ; to allow KERNEL to thunk
  2346. assumes ds,nothing
  2347. call GetPrivateProfileInt ; our segment in real mode
  2348. pop ds ; restore our DS
  2349. assumes ds,Data
  2350. cmp ax, 1
  2351. ja short gpf_exit ; just check at open
  2352. jb short gpf_no_fifo ; force OFF, if = 0
  2353. or EFlags[si], fFIFOchkd ; flag as checked, to force ON
  2354. jmp short gpf_exit
  2355. gpf_no_fifo:
  2356. or EFlags[si], fNoFIFO OR fFIFOchkd ; force OFF
  2357. gpf_exit:
  2358. ret
  2359. GetPortFIFO endp
  2360. GetPortDSR proc near
  2361. push ds ; save our DS
  2362. push ds
  2363. push DataOFFSET lpCommSection
  2364. push ds
  2365. push DataOFFSET lpCommDSR
  2366. push 0
  2367. push ds
  2368. push DataOFFSET lpSYSTEMINI
  2369. mov cx, ss ; temporarily assign DS=SS
  2370. mov ds, cx ; to allow KERNEL to thunk
  2371. assumes ds,nothing
  2372. call GetPrivateProfileInt ; our segment in real mode
  2373. pop ds ; restore our DS
  2374. assumes ds,Data
  2375. or ax, ax
  2376. jz short gpd_exit
  2377. or EFlags[si], fUseDSR
  2378. gpd_exit:
  2379. ret
  2380. GetPortDSR endp
  2381. ; FindCOMPort
  2382. ;
  2383. ; DS:SI -> DEB
  2384. ;
  2385. PUBLIC FindCOMPort
  2386. FindCOMPort proc near
  2387. ;
  2388. ; Examine BIOS data area to get base I/O addresses for COM and LPT ports
  2389. ;
  2390. push bx
  2391. push cx
  2392. push es
  2393. ifndef NEC_98
  2394. mov ax, __0040H
  2395. mov es, ax
  2396. assumes es,nothing
  2397. endif ; NEC_98
  2398. mov al, [si.DCB_Id]
  2399. mov ah, al
  2400. .erre MAXCOM LT 9 ;only single digit port numbers supported
  2401. add ah, '1'
  2402. mov [CommBaseX], ah
  2403. mov [CommIRQX], ah
  2404. mov [CommFIFOX], ah
  2405. mov [CommDSRx], ah
  2406. ifdef NEC_98
  2407. mov ax,238h ;I/O Base Addr Set
  2408. mov dx,5 ;IRQ Set
  2409. else ; NEC_98
  2410. cmp al, 4
  2411. jae fcp_not_phys_com
  2412. xor ah, ah
  2413. shl ax, 1
  2414. mov bx, ax
  2415. mov ax, es:[bx+RS232B]
  2416. or ax, ax
  2417. jnz fcp_got_com_base
  2418. fcp_not_phys_com:
  2419. call GetComBase
  2420. or ax, ax
  2421. jnz fcp_got_com_base
  2422. mov bl, [si.DCB_Id]
  2423. cmp bl, 2
  2424. jne fcp_invalid ; jump, if base = 0 & com port <> com3
  2425. mov ax, 3E8h ; default COM3 to 3E8h
  2426. fcp_got_com_base:
  2427. push ax
  2428. call GetPortIRQ
  2429. mov dx, ax
  2430. pop ax
  2431. or dl, dl ;Q: non-zero IRQ?
  2432. jz fcp_invalid ; N:
  2433. cmp dl, 15 ;Q: IRQ in range?
  2434. ja fcp_invalid ; N:
  2435. xor dh, dh
  2436. endif ; NEC_98
  2437. push ax
  2438. push dx
  2439. call GetPortFIFO
  2440. call GetPortDSR
  2441. pop dx
  2442. pop ax
  2443. clc
  2444. fcp_exit:
  2445. pop es
  2446. pop cx
  2447. pop bx
  2448. ret
  2449. fcp_invalid:
  2450. or ax, -1
  2451. mov dx, ax
  2452. stc
  2453. jmp fcp_exit
  2454. FindCOMPort endp
  2455. .8086
  2456. page
  2457. ;--------------------------Private Routine-----------------------------;
  2458. ;
  2459. ; Rotate the PIC interrupt priorities so the communication ports are
  2460. ; highest priority.
  2461. ;
  2462. ; NOTE: Only rotates priorities on master PIC.
  2463. ;
  2464. ;-----------------------------------------------------------------------;
  2465. assumes ds,Data
  2466. assumes es,nothing
  2467. public Rotate_PIC
  2468. Rotate_PIC proc near
  2469. ifndef NEC_98
  2470. push ax
  2471. push cx
  2472. push di
  2473. mov al, 8 ; 0 - 7 rotated
  2474. mov cx, MAXCOM+1
  2475. mov di, DataOFFSET IRQhooks
  2476. rp_loop:
  2477. mov ah, [di.IRQn]
  2478. cmp ah, 0 ;End of hooked IRQ list?
  2479. je rp_set
  2480. cmp [di.VecN], 0FFh ;Hooked?
  2481. je rp_next
  2482. cmp ah, 8 ;If on slave PIC, treat as IRQ2
  2483. jb @f
  2484. mov ah, 2
  2485. @@:
  2486. cmp ah, al
  2487. jae rp_next
  2488. mov al, ah ;AL = lowest hooked comm IRQ
  2489. rp_next:
  2490. add di, SIZE IRQ_Hook_Struc
  2491. loop rp_loop
  2492. rp_set:
  2493. dec al ;Setting IRQ(n-1) as the lowest
  2494. and al, 07h ; priority makes IRQn the highest
  2495. or al, 0C0h
  2496. out INTA0, al
  2497. pop di
  2498. pop cx
  2499. pop ax
  2500. endif ; NEC_98
  2501. ret
  2502. Rotate_PIC endp
  2503. ifdef DEBUG
  2504. ifdef NEC_98
  2505. public InitCom20, InitCom40, InitCom50, InitCom59
  2506. else ; NEC_98
  2507. public InitCom10, InitCom20, InitCom40, InitCom50, InitCom59
  2508. endif ; NEC_98
  2509. public InitCom60, InitCom70, InitCom80, InitCom90, InitCom100
  2510. public TermCom10, TermCom15, TermCom20, TermCom30
  2511. public TermCom60, Terminate5, Terminate10, Terminate20, Terminate30
  2512. public Terminate45, Terminate49, Terminate50
  2513. public SetQue10
  2514. ifdef NEC_98
  2515. public SetCom5, SetCom20, SetCom210, SetCom220, SetCom230
  2516. else ; NEC_98
  2517. public SetCom5, SetCom10, SetCom20, SetCom210, SetCom220, SetCom230
  2518. endif ; NEC_98
  2519. public SetCom240, SetCom310, SetCom410, SetCom420, SetCom430
  2520. public SetCom440, SetCom450, SetCom460, SetCom470
  2521. ifdef NEC_98
  2522. public GetDEB30
  2523. else ; NEC_98
  2524. public GetDEB10, GetDEB20, GetDEB30
  2525. endif ; NEC_98
  2526. public DCBPtr10
  2527. endif
  2528. sEnd code
  2529. page
  2530. createSeg _INIT,init,word,public,CODE
  2531. sBegin init
  2532. assumes cs,init
  2533. ;------------------------------------------------------------------------------
  2534. ;------------------------------------------------------------------------------
  2535. ifndef NEC_98
  2536. IBMmodel proc near
  2537. push ax
  2538. push bx
  2539. push es
  2540. mov ah, 0c0h
  2541. int 15h
  2542. jc IBMmodel_exit
  2543. assumes es,nothing
  2544. cmp by es:[bx+2], 0f8h ; PS/2 80
  2545. je IBMmodel_exit ; return carry clear
  2546. cmp by es:[bx+2], 0fch ; AT or PS/2 50 or 60
  2547. jne OldBios ; assume OldBios
  2548. cmp by es:[bx+3], 04h ; PS/2 50
  2549. je IBMmodel_exit ; return carry clear
  2550. cmp by es:[bx+3], 05h ; PS/2 60
  2551. je IBMmodel_exit ; return carry clear
  2552. OldBios:
  2553. stc
  2554. IBMmodel_exit:
  2555. pop es
  2556. pop bx
  2557. pop ax
  2558. ret
  2559. IBMmodel endp
  2560. endif ; NEC_98
  2561. cProc LoadLib, <FAR,PUBLIC,NODATA>,<si,di>
  2562. cBegin
  2563. ifndef NEC_98
  2564. push ds
  2565. mov ax, __F000H
  2566. mov ds, ax
  2567. assumes ds, ROMBios
  2568. mov al, [MachineID]
  2569. pop ds
  2570. assumes ds,Data
  2571. mov [$MachineID], al
  2572. call IBMmodel ;Q: PS/2?
  2573. jc @F ; N:
  2574. mov [default_table+2], 3 ; Y: change COM3 default IRQ to 3
  2575. @@:
  2576. push ds
  2577. mov ax, __0040H
  2578. mov ds, ax
  2579. assumes ds,nothing
  2580. cmp word ptr ds:[RS232B], 2F8h ;Q: COM2 base in COM1 slot?
  2581. pop ds
  2582. assumes ds,Data
  2583. jne @F ; N: leave IRQ default as 4
  2584. mov [default_table], 3 ; Y: change IRQ default to 3
  2585. @@:
  2586. endif ; NEC_98
  2587. mov [fVPICD], -1 ; assume no
  2588. xor di, di
  2589. mov es, di
  2590. mov ax, GET386API
  2591. mov bx, VPICD
  2592. int MULTIPLEX
  2593. mov wo [lpfnVPICD], di
  2594. mov wo [lpfnVPICD+2], es
  2595. mov ax, es
  2596. or ax, di
  2597. jz short no_VPICD ; jump if no bimodel services available
  2598. ;
  2599. ; version check VPICD
  2600. ;
  2601. mov ax, VPICD_API_Get_Ver
  2602. call [lpfnVPICD]
  2603. %OUT version check VPICD
  2604. mov [fVPICD], 1 ; flag services are available
  2605. IFDEF No_DOSX_Bimodal_Services
  2606. jmp short skip_dosx_stuff
  2607. no_VPICD:
  2608. mov ax, __WinFlags
  2609. and al, WF_PMODE or WF_WIN286
  2610. cmp al, WF_PMODE or WF_WIN286
  2611. jne skip_dosx_stuff
  2612. .286
  2613. mov ax, Int31_Get_Version SHL 8
  2614. int 31h
  2615. test bl, 10b ;Q: processor goes to real mode
  2616. ; for int reflection?
  2617. jz skip_dosx_stuff ; N:
  2618. mov [Using_DPMI], 0FFh ; Y: flag use of DPMI
  2619. mov ax, ds
  2620. cCall GetSelectorBase,<ax> ;DX:AX = segment of selector
  2621. shr ax, 4
  2622. shl dl, 4
  2623. or ah, dl ;AX now points to interrupt *segment*
  2624. push ax ;save on stack
  2625. mov ax, _INTERRUPT ;write data SEGMENT into _INTERRUPT
  2626. cCall AllocCStoDSAlias,<ax> ; code segment -- requires a data alias
  2627. mov es, ax
  2628. pop ax
  2629. mov es:[RM_IntDataSeg],ax
  2630. push ds
  2631. push es
  2632. mov ax, ds
  2633. mov es, ax
  2634. mov ax, _INTERRUPT
  2635. mov ds, ax
  2636. mov ax, (Int31_Trans_Serv SHL 8) + Trans_Call_Back
  2637. mov si, IntCodeOFFSET Entry_From_RM
  2638. mov di, DataOFFSET RM_Call_Struc
  2639. int 31h
  2640. pop es
  2641. pop ds
  2642. mov ax, 0
  2643. jnc @f
  2644. jmp short LoadExit
  2645. @@:
  2646. mov wo es:[RM_CallBack], dx
  2647. mov wo es:[RM_CallBack+2], cx
  2648. cCall FreeSelector,<es> ;don't need CS alias any longer
  2649. .8086
  2650. skip_dosx_stuff:
  2651. ELSE
  2652. no_VPICD:
  2653. ENDIF
  2654. ifndef NEC_98
  2655. ;
  2656. ; find base values for LPT ports
  2657. ;
  2658. mov cx, __0040h
  2659. mov es, cx
  2660. mov cx, MAXLPT+1
  2661. mov si, DataOFFSET LPT1
  2662. ll_initl_lp:
  2663. mov bx, [si.BIOSPortLoc]
  2664. or bx, bx
  2665. jz ll_not_phys_lpt
  2666. mov ax, es:[bx]
  2667. or ah, ah ;Q: lpt redirected, or 0?
  2668. jz ll_not_phys_lpt ; Y:
  2669. cmp bx, LPTB ;Q: first LPT?
  2670. je ll_got_lpt_base ; Y:
  2671. cmp ax, es:[bx-2] ;Q: base same as previous (redirected)?
  2672. jne ll_got_lpt_base ; N: must be real
  2673. ll_not_phys_lpt:
  2674. %OUT attempt to read base from SYSTEM.INI
  2675. ll_got_lpt_base:
  2676. mov [si.Port], ax
  2677. loop ll_initl_lp
  2678. endif ; NEC_98
  2679. ;
  2680. ; create system timer for signalling chars in receive buffer
  2681. ;
  2682. ifndef WOW
  2683. mov ax, 100 ; create 100msec timer
  2684. push ax
  2685. mov ax, _INTERRUPT
  2686. push ax
  2687. mov ax, IntCodeOFFSET TimerProc
  2688. push ax
  2689. call CreateSystemTimer ; ax = 0, if failed
  2690. %OUT should I display an error message here?
  2691. endif
  2692. assumes es,nothing
  2693. LoadExit:
  2694. cEnd
  2695. sEnd init
  2696. End LoadLib