home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / SETCOM40.ZIP / SETCOM40.ASM < prev    next >
Assembly Source File  |  1990-10-28  |  18KB  |  489 lines

  1.     TITLE    SETCOM40 Device Driver for OS/2
  2.     PAGE    60, 132
  3.     COMMENT +
  4.     File:        SETCOM40.ASM
  5.     File type:    Microsoft Macro Assembler (MASM) Version 5.1 or higher
  6.     Author:     John W. Cocula
  7.     Date:        October, 1990
  8.  
  9.     Purpose:
  10.     This device changes the BIOS COM ownership words if the BIOS
  11.         gets it wrong during POST.
  12.     +
  13.  
  14.     .286c
  15.     .sall
  16.  
  17.     DATA SEGMENT WORD PUBLIC 'DATA'
  18.     SUBTTL Device Driver Header
  19.     PAGE +
  20.  
  21. ; ***********************************************************************
  22. ; *                DEVICE HEADER                *
  23. ; ***********************************************************************
  24.  
  25. PtrToNextHeader dd    0FFFFFFFFh    ; Indicates loadable device driver
  26. DeviceAttribute dw    1000000010000000b
  27.                     ; Bit 15 - Character device
  28.                     ; Bits 9-7 - OS/2 device driver
  29. StrategyOffset    dw    CODE:Strategy    ; Offset to the Strategy routine
  30. IDCOffset    dw    0        ; unused
  31. DeviceName    db    'SETCOM$$'    ; Name of the device
  32. ReservedBlock2    db    8 dup (0)    ; Reserved words
  33.  
  34. ; ***********************************************************************
  35. ; *                DEVHLP SUPPORT                *
  36. ; ***********************************************************************
  37.  
  38.         .XLIST
  39. ;
  40. ; These constants define the DevHlp commands:
  41. ;
  42. ;DevHlp_SchedClockAddr EQU 0    ; 0h  Get system clock routine
  43. ;DevHlp_DevDone        EQU   1    ; 1h  Device I/O Complete
  44. ;DevHlp_Yield        EQU   2    ; 2h  Yield the CPU
  45. ;DevHlp_TCYield        EQU   3    ; 3h  Yield the CPU to time-critical
  46. ;DevHlp_Block        EQU   4    ; 4h  Block thread on event
  47. ;DevHlp_Run        EQU   5    ; 5h  Unblock thread
  48. ;DevHlp_SemRequest   EQU   6    ; 6h  Claim a semaphore
  49. ;DevHlp_SemClear     EQU   7    ; 7h  Release a semaphore
  50. ;DevHlp_SemHandle    EQU   8    ; 8h  Get a semaphore handle
  51. ;DevHlp_PushReqPacket EQU  9    ; 9h  Add request to list
  52. ;DevHlp_PullReqPacket EQU 10    ; Ah  Remove request from list
  53. ;DevHlp_PullParticular EQU 11    ; Bh  Remove a specific request from list
  54. ;DevHlp_SortReqPacket EQU 12    ; Ch  Insert request in sorted order to list
  55. ;DevHlp_AllocReqPacket EQU 13    ; Dh  Get a request packet
  56. ;DevHlp_FreeReqPacket EQU 14    ; Eh  Free request packet
  57. ;DevHlp_QueueInit    EQU  15    ; Fh  Initialize character queue
  58. ;DevHlp_QueueFlush   EQU  16    ;10h  Clear character queue
  59. ;DevHlp_QueueWrite   EQU  17    ;11h  Put a char in the queue
  60. ;DevHlp_QueueRead    EQU  18    ;12h  Get a char from the queue
  61. ;DevHlp_Lock        EQU  19    ;13h  Lock segment
  62. ;DevHlp_Unlock        EQU  20    ;14h  Unlock segment
  63. ;DevHlp_PhysToVirt   EQU  21    ;15h  Map physical address to virtual
  64. ;DevHlp_VirtToPhys   EQU  22    ;16h  Map virtual-to-physical address
  65. DevHlp_PhysToUVirt  EQU  23    ;17h  Map physical-to-user virtual
  66. ;DevHlp_AllocPhys    EQU  24    ;18h  Allocate physical memory
  67. ;DevHlp_FreePhys     EQU  25    ;19h  Free physical memory
  68. ;DevHlp_SetROMVector EQU  26    ;1Ah  Set software interrupt vector
  69. ;DevHlp_SetIRQ        EQU  27    ;1Bh  Set a hardware interrupt handler
  70. ;DevHlp_UnSetIRQ     EQU  28    ;1Ch  Reset a hardware interrupt handler
  71. ;DevHlp_SetTimer     EQU  29    ;1Dh  Set timer request handler
  72. ;DevHlp_ResetTimer   EQU  30    ;1Eh  Remove a timer handler
  73. ;DevHlp_MonitorCreate EQU 31    ;1Fh  Create a monitor
  74. ;DevHlp_Register     EQU  32    ;20h  Install a monitor
  75. ;DevHlp_DeRegister   EQU  33    ;21h  Remove a monitor
  76. ;DevHlp_MonWrite     EQU  34    ;22h  Pass data records to monitor
  77. ;DevHlp_MonFlush     EQU  35    ;23h  Remove all data from stream
  78. ;DevHlp_GetDOSVar    EQU  36    ;24h  Return pointer to DOS variable
  79. ;DevHlp_SendEvent    EQU  37    ;25h  Indicate an event
  80. ;DevHlp_ROMCritSection EQU 38    ;26h  ROM BIOS critical section
  81. ;DevHlp_VerifyAccess EQU  39    ;27h  Verify access to memory
  82. ;DevHlp_AllocGDTSelector EQU 45    ;2Dh  Allocate GDT selectors
  83. ;DevHlp_PhysToGDTSelector EQU 46 ;2Eh  Map physical to virtual address
  84. ;DevHlp_RealToProt   EQU  47    ;2Fh  Real Mode to Protect Mode
  85. ;DevHlp_ProtToReal   EQU  48    ;30h  Protect Mode to Real Mode
  86. ;DevHlp_EOI        EQU  49    ;31h  Issue an End-Of-Interrupt
  87. ;DevHlp_UnPhysToVirt EQU  50    ;32h  Mark PhysToVirt complete
  88. ;DevHlp_TickCount    EQU  51    ;33h  Modify timer
  89. ;DevHlp_GetLIDEntry  EQU  52    ;34h  Get Logical ID
  90. ;DevHlp_FreeLIDEntry EQU  53    ;35h  Release Logical ID
  91. ;DevHlp_ABIOSCall    EQU  54    ;36h  Invoke ABIOS function
  92. ;DevHlp_ABIOSCommonEntry EQU 55    ;37h  Invoke ABIOS Common Entry Point
  93.  
  94. ;
  95. ; This macro simplifies calling a DevHlp service by doing a load of the
  96. ; function code into DL and calling pfnDevHlp.
  97. ;
  98.  
  99. @DevHlp MACRO name
  100.     mov  dl, DevHlp_&name
  101.     call pfnDevHlp
  102.     ENDM
  103.  
  104.         .LIST
  105.  
  106.     SUBTTL Structures/Codes for Request Packets
  107.     PAGE +
  108. ; ***********************************************************************
  109. ; *             REQUEST PACKET STRUCTURE            *
  110. ; ***********************************************************************
  111.  
  112. PKTMAX        EQU    18        ; Maximum size of packet
  113.  
  114. PacketStruc    STRUC
  115.  PktLen     db    ?        ; Length in bytes of packet
  116.  PktUnit    db    ?        ; Subunit number of block device
  117.  PktCmd     db    ?        ; Command code
  118.  PktStatus    dw    ?        ; Status word
  119.  PktDOSLink    dd    ?        ; Reserved
  120.  PktDevLink    dd    ?        ; Device multiple-request link
  121.  PktData    db    PKTMAX dup (?)    ; Data pertaining to specific packet
  122. PacketStruc    ENDS
  123.  
  124. ; ***********************************************************************
  125. ; *           CODES FOR STATUS OF REQUEST PACKET            *
  126. ; ***********************************************************************
  127.  
  128. ; Bit positions in Status field:
  129. StatRecord    RECORD    StatError:1,StatDevError:1,StatRes:4,StatBusy:1,\
  130.             StatDone:1,StatErrCode:8
  131.  
  132. ; Error Codes:
  133. StatWrProtVio    EQU    00h        ; WRITE PROTECT VIOLATION
  134. StatUnknownCmd    EQU    03h        ; UNKNOWN COMMAND
  135. StatGenFailure    EQU    0Ch        ; GENERAL FAILURE
  136. StatCharIOIntd    EQU    11h        ; CHARACTER I/O INTERRUPTED
  137. StatMonNotSupp    EQU    12h        ; MONITORS NOT SUPPORTED
  138.  
  139. ; ***********************************************************************
  140. ; *           POINTER CONSTANTS FOR REQUEST PACKET         *
  141. ; ***********************************************************************
  142.  
  143. Packet        EQU    ES:[BX]
  144.  
  145. ; Offsets into packet for INIT and READ/WRITE commands:
  146.  
  147. InitpEnd    EQU    DWORD PTR PktData+1    ; Pointer to freemem after dev
  148. InitArgs    EQU    DWORD PTR PktData+5    ; Pointer to CONFIG.SYS args
  149.  
  150. ; ***********************************************************************
  151. ; *            DATA USED BY THE STRATEGY ROUTINE            *
  152. ; ***********************************************************************
  153.  
  154. fbError        db    0    ; Error flag used to signal to the Strategy
  155.                 ;  routine a return with error from another
  156.                 ;  subroutine.
  157.  
  158. END_OF_DATA    EQU  $
  159.  
  160. pfnDevHlp    dd    ?    ; Holds address of the DevHlp function entry
  161. ArgPtr        dd    ?    ; Holds address of CONFIG.SYS argument string
  162.  
  163. com1            dw      03F8h   ; default comm port values
  164. com2            dw      02F8h   ; default comm port values
  165.  
  166. InitBanner    db    13,10,'SETCOM40 Device Driver Version 1.0'
  167. Banner_strlen    EQU    $-InitBanner
  168. bad_string    db    13,10,'    Bad '
  169. bad_strlen    EQU    $-bad_string
  170. specified_string db    ' value specified.',13,10
  171. specified_strlen EQU    $-specified_string
  172. invparam_string db    13,10,'    Invalid parameter specified',13,10
  173. invparam_strlen EQU    $-invparam_string
  174. com1_string    db    'COM1='
  175. com1_strlen    EQU    $-com1_string
  176. com2_string    db    'COM2='
  177. com2_strlen    EQU    $-com2_string
  178.  
  179. DATA ENDS
  180.  
  181. CODE      SEGMENT  WORD PUBLIC 'CODE'
  182.       ASSUME   CS:CODE, DS:DATA, ES:NOTHING
  183.  
  184. ; ***********************************************************************
  185. ; *                STRATEGY ROUTINE                *
  186. ; *                                    *
  187. ; * Far procedure Strategy gets the request packet and based on its    *
  188. ; * command code branches to the appropriate subroutine. Upon return    *
  189. ; * from the subroutine, the request is signalled serviced with or    *
  190. ; * without error.                            *
  191. ; ***********************************************************************
  192.  
  193. Strategy PROC FAR
  194.     push    es        ; save the pointers to the request packet
  195.     push    bx
  196.     mov    al, BYTE PTR Packet.PktCmd
  197.     cmp    al, 0        ; Command code is moved into al
  198.                 ; If index larger than those supported
  199.     jne    UNSUPPORTED    ; Jump to indicate that the command is
  200.                 ;  unsupported
  201.     mov    fbError, 0    ; Zero out the fbError flag prior to the call
  202.  
  203.         call    INIT            ; Call only entry point supported.
  204.  
  205.     pop    bx        ; Restore the pointers to the request packet
  206.     pop    es
  207.     cmp    fbError, 0    ; Upon return, check if subroutine returned
  208.                 ;  an error
  209.     jz    ERROR_FREE    ; If no error, jump to signal devdone
  210.     or    Packet.PktStatus, MASK StatError + StatGenFailure
  211.                 ; Set the error condition in the Req Packet
  212.                 ; Set the error to General Failure
  213.     or    Packet.PktStatus, MASK StatDone
  214.     jmp    FIN
  215.  
  216. ERROR_FREE:
  217.     mov    Packet.PktStatus, MASK StatDone
  218.     jmp    FIN
  219.  
  220. UNSUPPORTED:
  221.     pop    bx        ; Retrieve the pushed values of bx and es
  222.     pop    es
  223.     or      Packet.PktStatus, MASK StatError + StatUnknownCmd
  224.  
  225. FIN:
  226.     ret
  227. Strategy ENDP
  228.  
  229.     SUBTTL Initialization Code
  230.     page +
  231.  
  232. END_OF_CODE  EQU $
  233.  
  234. ; ***********************************************************************
  235. ; * Initialization code is placed at the end of the code segment so it    *
  236. ; * can go away once initialization has been done.            *
  237. ; ***********************************************************************
  238.  
  239.     SUBTTL Initialization Code
  240.     PAGE +
  241.  
  242.     .XLIST            ; Suppress listing of files
  243.     INCL_VIO    EQU 1
  244.     INCLUDE OS2.INC
  245.     .LIST
  246.  
  247. @SayBad MACRO string, strlen
  248.     @VioWrtTTy bad_string, bad_strlen, 0
  249.     @VioWrtTTy string, strlen, 0
  250.     @VioWrtTTy specified_string, specified_strlen, 0
  251.     ENDM
  252.  
  253. INT_PASSED    EQU    0
  254. INT_ERROR    EQU    -1
  255.  
  256. ; ***********************************************************************
  257. ; *                 INIT ROUTINE                *
  258. ; *                                    *
  259. ; * INIT procedure is placed at the end of the code so it can go away    *
  260. ; * once initialization has been done.                    *
  261. ; ***********************************************************************
  262.  
  263. INIT PROC NEAR
  264. ; ========================================================================
  265. ; Save the pointer to the DevHlp routines passed in the request packet.
  266. ; ========================================================================
  267.     mov    ax, WORD PTR Packet.InitpEnd ; Save pointer to DevHlp
  268.     mov    WORD PTR pfnDevHlp, ax
  269.     mov    ax, WORD PTR Packet.InitpEnd+2
  270.     mov    WORD PTR pfnDevHlp+2, ax
  271.     mov    ax, WORD PTR Packet.InitArgs    ; Save the far pointer to
  272.     mov    WORD PTR ArgPtr, ax        ; the CONFIG.SYS arguments
  273.     mov    ax, WORD PTR Packet.InitArgs+2
  274.     mov    WORD PTR ArgPtr+2, ax
  275.     push    es            ; save ptr to request packet
  276.     push    bx
  277. ; ------------------------------------------------------------------------
  278. ; Say hi.
  279. ; ------------------------------------------------------------------------
  280.     @VioWrtTTy InitBanner, Banner_strlen, 0 ; Display opening banner
  281. ; ------------------------------------------------------------------------
  282. ; Parse the command-line arguments, if any.
  283. ; ------------------------------------------------------------------------
  284.     call    parse_args            ; Parse options in CONFIG.SYS
  285.     cmp    ax, INT_PASSED
  286.     jne    init_error
  287. ; ------------------------------------------------------------------------
  288. ; Get a pointer to the BIOS data area to write the values.
  289. ; ------------------------------------------------------------------------
  290.         mov     ax, 0                   ; BIOS data area 0040:0000
  291.         mov     bx, 0400h
  292.         mov     cx, 4                   ; four bytes long
  293.         mov     dh, 1                   ; get read/write data selector
  294.         @DevHlp PhysToUVirt
  295.         jc      init_error
  296. ; ========================================================================
  297. ; Set the COM ownership words in the BIOS data area.
  298. ; ========================================================================
  299.         mov     ax, com1
  300.         mov     WORD PTR es:[bx+0], ax  ; Set com1
  301.         mov     ax, com2
  302.         mov     WORD PTR es:[bx+2], ax  ; Set com2
  303. ; ------------------------------------------------------------------------
  304. ; Release the selector to the BIOS data area.
  305. ; ------------------------------------------------------------------------
  306.         mov     ax, es                  ; selector to free
  307.         mov     dh, 2                   ; release selector
  308.         @DevHlp PhysToUVirt
  309. ; ------------------------------------------------------------------------
  310. ; Set the ending offsets to unload initialization code and data.
  311. ; ------------------------------------------------------------------------
  312.     pop    bx
  313.     pop    es
  314.     lea    ax, END_OF_CODE        ; Place end of code segment into
  315.     mov    WORD PTR Packet.InitpEnd, ax ; request packet
  316.     lea    ax, END_OF_DATA        ; Place end of data segment into
  317.     mov    WORD PTR Packet.InitpEnd+2, ax ; request packet
  318.     jmp    init_done
  319. init_error:
  320.     pop    bx            ; restore ptr to request packet
  321.     pop    es
  322.     mov    fbError, 1
  323.     mov    WORD PTR Packet.InitpEnd, 0
  324.     mov    WORD PTR Packet.InitpEnd+2, 0
  325. init_done:
  326.     ret
  327. INIT ENDP
  328.  
  329.     SUBTTL Parse command line arguments
  330.     PAGE +
  331.  
  332. ; ***********************************************************************
  333. ; *           CONFIG.SYS COMMAMD LINE PARSING            *
  334. ; *                                    *
  335. ; * The "command line" in CONFIG.SYS can be parsed by obtaining a read- *
  336. ; * only pointer to the start of the line after the DEVICE= string.    *
  337. ; * The function parse_args returns INT_ERROR if there was an error on    *
  338. ; * the command line, and INIT takes this to mean that the driver    *
  339. ; * should not be loaded. INT_PASSED is returned on success.        *
  340. ; *                                    *
  341. ; * Example:                                *
  342. ; * DEVICE=\DEV\SETCOM40.SYS /COM1=3F8 /COM2=2F8                        *
  343. ; ***********************************************************************
  344.  
  345. parse_args PROC NEAR
  346.     push    es
  347.     push    di
  348.  
  349.     ; Register usage:
  350.     ; DS:SI        -- source string pointer
  351.     ; ES:DI        -- destination string pointer (preserved)
  352.     ; AX        -- holds '/' and ES temporarily
  353.     ; BX        -- holds DI temporarily
  354.     ; CX        -- string comparison lengths
  355.     ; DX        -- remaining command line to process
  356.  
  357.     les    di, ArgPtr    ; point after '='
  358. ;
  359. ; DEVICE=\DEV\SETCOM40.SYS /COM1=3F8 /COM2=2F8
  360. ;        ^---this is pointed to by ES:DI now
  361. ;
  362.     push    di        ; Save DI index.
  363.     cld            ; Process strings forward.
  364.     mov    al, 0        ; ASCII 00h, 0Dh or 0Ah will terminate line.
  365.     mov    cx, 80             ; Search no more than 80 characters (arbitrary)
  366.     repne    scasb        ; Scan, leaving DI pointing after it.
  367.     mov    dx, di        ; Points to char after EOL.
  368.     dec    dx        ; Point it TO the EOL.
  369.     pop    di        ; Restore DI index.
  370. arg_loop:
  371.     cmp    di, dx        ; See if over end of line.
  372.     jl    ok_to_check    ; Not over edge, continue.
  373.     jmp    arg_ok        ; Must be finished.
  374. ok_to_check:
  375.     mov    cx, dx
  376.     sub    cx, di        ; Length of line in CONFIG.SYS
  377.     mov    al, '/'        ; Search for a '/' after driver name.
  378.     repne    scasb        ; Scan.
  379.     cmp    cx, 0        ; See if there really WAS a '/'.
  380.     jg    found_slash    ; Yes, continue processing.
  381.     jmp    arg_ok        ; No, must be done.
  382. found_slash:
  383.     ;
  384.     ; /COM1=hhh
  385.     ;
  386.     mov    bx, di        ; Save starting address to compare.
  387.     mov    si, OFFSET com1_string     ; See if option is 'COM1='.
  388.     mov    cx, com1_strlen ; Load string length.
  389.     repe    cmpsb        ; Compare.
  390.     jcxz    is_com1     ; Jump if string matched 'COM1='.
  391.     jmp    @F
  392. is_com1:
  393.     mov    bh, 3        ; Get the three hex digits of the
  394.     call    htoi        ; I/O port address.
  395.     cmp    ax, INT_ERROR    ; See if error occurred.
  396.     je    bad_com1    ; If so, uh oh.
  397.     mov    com1, ax        ; Save it.
  398.     jmp    arg_loop    ; Get more options, if any.
  399. bad_com1:
  400.     @SayBad com1_string, com1_strlen
  401.     mov    ax, INT_ERROR    ; Return error code.
  402.     jmp    arg_done    ; Get the hello out.
  403. @@:
  404.     ;
  405.     ; /COM2=hhh
  406.     ;
  407.     mov    di, bx        ; No, restore index.
  408.     mov    si, OFFSET com2_string   ; See if the option is 'COM2='.
  409.     mov    cx, com2_strlen    ; Load string length.
  410.     repe    cmpsb        ; Compare.
  411.     jcxz    is_com2        ; Jump if string matched 'COM2='.
  412.     jmp    @F
  413. is_com2:
  414.     mov    bh, 3        ; Get the three hex digits of the
  415.     call    htoi        ; I/O port address.
  416.     cmp    ax, INT_ERROR    ; See if error occurred.
  417.     je    bad_com2    ; If so, uh oh.
  418.     mov    com2, ax        ; Save it.
  419.     jmp    arg_loop    ; Get more options, if any.
  420. bad_com2:
  421.     @SayBad com2_string, com2_strlen
  422.     mov    ax, INT_ERROR    ; Return error code.
  423.     jmp    arg_done    ; Get the hello out.
  424. @@:
  425.     @VioWrtTTy invparam_string, invparam_strlen, 0
  426.     mov    ax, INT_ERROR    ; Not a valid option.
  427.     jmp    arg_done    ; pop and exit.
  428. arg_ok:
  429.     mov    ax, INT_PASSED    ; success
  430. arg_done:
  431.     pop    di
  432.     pop    es
  433.     ret
  434. parse_args endp
  435.  
  436.     SUBTTL ASCII to binary conversion routines
  437.     PAGE +
  438.  
  439. ;
  440. ; htoi converts a word represented in hexadecimal into binary.
  441. ;
  442. htoi proc near
  443.     ; PASSED:
  444.     ;     BH is number of digits (must be >= 1 and <= 4, not checked.)
  445.     ;     ES:[DI] points to string.
  446.     ; RETURNED:
  447.     ;     AX returns word value.
  448.     ;     ES:[DI] ends up pointing one char AFTER last one converted.
  449.     ; MODIFIED:
  450.     ;     CL holds digit temporarily during comparisons.
  451.     xor    ax, ax        ; Zero out AX register.
  452. next_hdigit:
  453.     mov    cl, BYTE PTR es:[di] ; Load digit into CL.
  454.     cmp    cl, '0'        ; See if it's >= '0'.
  455.     jge    test_h9        ; Why yes, it is.
  456.     jmp    bad_hdigit    ; It isn't, can't be any digit.
  457. test_h9:
  458.     cmp    cl, '9'        ; See if it's <= '9'.
  459.     jle    is_hdecimal    ; It's a normal decimal digit.
  460.     cmp    cl, 'A'        ; Is it a hexadecimal digit?
  461.     jge    test_F        ; Could be...see if it's <= 'F'.
  462.     jmp    bad_hdigit    ; Nope, you blew it; it's < 'A'.
  463. test_F:    cmp    cl, 'F'        ; Is it <= 'F'.
  464.     jg    bad_hdigit    ; Too big; you blew it.
  465.      sub    cl, 'A'-10    ; Convert from ASCII hex to a number.
  466.     shl    ax, 4        ; Shift over old digits.
  467.     and    cx, 00FFh    ; Make sure upper byte not OR'd in.
  468.     or    ax, cx        ; Add it in.
  469.     jmp    test_hnext    ; See if more digits to do.
  470. is_hdecimal:
  471.     sub    cl, '0'        ; Convert from digit to a number.
  472.     shl    ax, 4        ; Move over old digit(s).
  473.     and    cx, 00FFh    ; Make sure upper byte not OR'd in.
  474.     or    ax, cx        ; Add it in.
  475. test_hnext:
  476.     inc    di        ; Move to next digit.
  477.     dec    bh        ; Decrement counter.
  478.     jnz    next_hdigit    ; If any left, go back to top.
  479.     jmp    htoi_done    ; Otherwise, blow this popsicle stand.
  480. bad_hdigit:
  481.     mov    ax, INT_ERROR
  482. htoi_done:
  483.     ret
  484. htoi endp
  485.  
  486. CODE    ENDS
  487.  
  488.     END
  489.