home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / labhelp.zip / labhelp / labhelp.asm next >
Assembly Source File  |  1993-01-29  |  22KB  |  508 lines

  1. ;**********************************************************************
  2. ;* MODULE NAME :  labhelp.asm             AUTHOR:  Michael Thompson   *
  3. ;* DATE WRITTEN:  11-29-92                                            *
  4. ;*                                                                    *
  5. ;* DESCRIPTION:                                                       *
  6. ;*                                                                    *
  7. ;*  This device driver currently provides programs with direct access *
  8. ;*  to OS/2 physical memory.  It is a complete violation of the OS/2  *
  9. ;*  spirit of protected memory, but in lab situations, it is often    *
  10. ;*  necessary to directly access board memory (i.e. D/A and A/D       *
  11. ;*  converters).  This routine will probably be expanded to provide   *
  12. ;*  low level system services for lab applications.                   *
  13. ;*                                                                    *
  14. ;* Access to physical memory is gained by passing a structure to the  *
  15. ;* IOCTL code with category 0x81 and functions 0x41 and 0x42.         *
  16. ;* The parmameter block should contain three unsigned long values     *
  17. ;*      0x00 Starting physical address requested                      *
  18. ;*      0x04 Length of block desired (only low 16 bits significant)   *
  19. ;*      0x08 empty pointer.  Filled with a _Seg16 pointer in users    *
  20. ;*           LDT to the physical memory block                         *
  21. ;* 
  22. ;* Development of this code made possible by random code fragments    *
  23. ;* purloined from numerous device drivers.  Thanks especially to all  *
  24. ;* on IBM BBS and the comp.os.os2.programmer netnews for ideas.       *
  25. ;**********************************************************************
  26. .286P
  27.  
  28.         page    60,132
  29.         title   _DD   Lab Control/Help Device Driver
  30.  
  31.         INCLUDE  devhlp.inc             ; DEFINITION OF DEVICE HELP CALLS
  32.  
  33. ;*********************************************************************
  34. ;*----------------------------- EQUATES -----------------------------*
  35. ;*********************************************************************
  36.  
  37. RP_StatusError          equ     80h     ; RP_Status error bit
  38. RP_StatusDone           equ     01h     ; RP_Status done bit
  39. cr                      equ     0dh     ; ASCII code for carraige return
  40. lf                      equ     0ah     ; ASCII code for line feed
  41. stdout                  equ     1       ; File handle for standard output
  42.  
  43. ;**********************************************************************
  44. ;*------------------------------ MACROS ------------------------------*
  45. ;**********************************************************************
  46.  
  47. Read8253IntoCx  MACRO                      ; Put 8253 counter 0 value in cx
  48.  
  49.  
  50. ENDM
  51.  
  52. ;**********************************************************************
  53. ;*---------------------------- STRUCTURES ----------------------------*
  54. ;**********************************************************************
  55. RequestPacket           struc           ; Request Packet header
  56.   RP_Length        db    ?    ; Request Packet length
  57.   RP_Unit        db    ?    ; unit CSEG (Block devices only)
  58.   RP_Command        db    ?       ; Command CSEG
  59.   RP_ErrorCode        db    ?       ; Command Error Code
  60.   RP_Status        db    ?       ; Command Status Code
  61.   RP_Rsvd        dd    ?       ; Reserved for DOS
  62.   RP_Q_Link        dd    ?       ; Queue Linkage - not used here
  63. RequestPacket        ends
  64.  
  65. RequestPktInit        struc        ; Initialization Request Packet
  66.             db 13 dup(?)    ; Common header information
  67.   RPI_NumberUnits    db    ?    ; number of units (not used)
  68.   RPI_CodeSegLen    dw      ?       ;     Code segment length (output)
  69.   RPI_DataSegLen    dw      ?       ;     Data segment length (output)
  70.   RPI_CommandLine    dd    ?    ; Pointer to command line
  71.   RPI_Drive        db    ?    ; Block devices only
  72. RequestPktInit        ends
  73.  
  74. RequestPktIOCtl        struc        ; Generic IOCtl request packet
  75.             db    13 dup(?)
  76.   RPC_categ        db    ?    ; category CSEG
  77.   RPC_funct        db    ?    ; function CSEG
  78.   RPC_parm        dd    ?    ; addr of parms (offset and selector)
  79.   RPC_buff        dd    ?    ; addr of buffer (offset and selector)
  80. RequestPktIOCtl        ends
  81.  
  82. ;**********************************************************************
  83. ;*----------------------------- EXTERNS ------------------------------*
  84. ;**********************************************************************
  85.  
  86.         extrn  DosWrite:far
  87.  
  88. ;**********************************************************************
  89. ;*-------------------------- DATA SEGMENT ----------------------------*
  90. ;**********************************************************************
  91.  
  92. DGROUP          group   _DATA
  93.  
  94. _DATA        SEGMENT word public  'DATA'
  95.  
  96. ;*---------------------- Device Driver Header ------------------------*
  97. MemoryHeader        label    byte        ; Device Driver header
  98.   NextDeviceDriver    dd    -1        ; Last driver in chain
  99.   DeviceAttribute    dw    8880h        ; Char,Open/Close,OS/2 1.1
  100.   StrategyOffset    dw    Strategy    ; Offset of Strategy Routine
  101.             dw    -1        ; IDC - not used here
  102.   DeviceName        db    'LABHELP$'    ; Driver Device-Name
  103.             db    8 dup(0)    ; Reserved
  104.  
  105. ;*-------------- List of strategy entry addresses --------------------*
  106. CmdList        label word
  107.         dw      Initialize    ;  0 = Initialize driver
  108.                 dw      Error        ;  1 = Media Check
  109.                 dw      Error        ;  2 = Build BPB
  110.                 dw      Error        ;  3 = Not used
  111.         dw    Unsupported    ;  4 = Read from device
  112.                 dw      Unsupported    ;  5 = Non-destructive read
  113.                 dw      Unsupported    ;  6 = Return input status
  114.                 dw      Unsupported    ;  7 = Flush input buffers
  115.                 dw      Unsupported    ;  8 = Write to device
  116.                 dw      Unsupported    ;  9 = Write with verify
  117.                 dw      Unsupported    ; 10 = Return output status
  118.                 dw      Unsupported    ; 11 = Flush output buffers
  119.                 dw      Error        ; 12 = Not used
  120.                 dw      Open        ; 13 = Device open
  121.                 dw      Close        ; 14 = Device close
  122.         dw    Error        ; 15 = Remove media
  123.         dw    IOCtl        ; 16 = Generic ioctl
  124. MaxCmd        equ    ( $ - CmdList ) / TYPE CmdList
  125.  
  126. ;*------------ Data areas used by Strategy and Interrupt -------------*
  127.   DevHlpPtr        dd    ?        ; Pointer to Device Helper
  128.   UserCount        dw    0        ; Number of active users
  129.   HaveTimer        dw    0        ; 0==>can access timer
  130.   Last8253        dw    ?        ; 8253 ticks at last interrupt
  131.  
  132. ; TimeTicks must match parms structure in IOCTL call
  133.   TimerTicksStruct    dd    840        ; ns/tick
  134.   TimerTicks        dd    0        ; Number of timer ticks
  135.             dd    0        ; 64 bit integer
  136.  
  137. DSEG_END    label    byte            ; last byte of device driver
  138.  
  139. ;*------------ Data areas used by Initialization only ----------------*
  140. BytesWritten    dw    ?        ; Used for DosWrite calls
  141. CopyRightMsg    db      cr, lf
  142.                 db      'Lab Control Device Driver (LABHELP$) - Version 1.0', cr, lf
  143.         db    '  Providing unsafe accsex to OS/2 memory and system utilities', cr, lf
  144.                 db      '  Courtesy of Michael Thompson, CGS, Ltd. (1992)', cr, lf, lf
  145. CopyRightMsgLen equ     $ - CopyRightMsg
  146.  
  147. _DATA        ends
  148.  
  149. i8253CountRegister      equ     40h     ; 8253 Counter Register
  150. i8253CtrlByteRegister   equ     43h     ; 8253 Control Byte Register
  151. i8253CmdReadCtrZero     equ     0       ; Latch Command
  152. i8253CmdInitCtrZero     equ     34h     ; LSB first, MSB second, Rate generator
  153.  
  154. NanosInATick            equ     840     ; Number of nanoseconds in 1 8253 tick
  155. MillionDividedBy64      equ     15625   ; 1,000,000 divided by 64
  156.  
  157. ;**********************************************************************
  158. ;*-------------------------- CODE SEGMENT ----------------------------*
  159. ;**********************************************************************
  160.  
  161. _TEXT        SEGMENT word public  'CODE'
  162.  
  163.         assume  cs:_TEXT, ds:DGROUP
  164.  
  165. ;*---------------------------- Strategy ------------------------------*
  166. ;*  STRATEGY ENTRY POINT.                                             *
  167. ;*                                                                    *
  168. ;*  INPUT: ES:BX = address of request packet                          *
  169. ;*                                                                    *
  170. ;*  OUTPUT: nothing                                                   *
  171. ;*--------------------------------------------------------------------*
  172. Strategy    PROC    far
  173.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  174.  
  175. ;    INT     3
  176.  
  177.     mov    es:[bx].RP_Errorcode, 0            ; clear error code
  178.     mov    es:[bx].RP_Status, RP_StatusDone    ; clear status also
  179.  
  180.     mov    al,es:[bx].RP_Command    ; route control based on command CSEG
  181.     cmp    al, MaxCmd        ; Command within jump table?
  182.     jbe    valid
  183.      call    Error
  184.      ret
  185.  
  186. valid:    cbw                ; Convert to word
  187.     mov    si,ax            ; Move into register
  188.     shl    si,1            ; multiply by 2 so it is a word offset
  189.     call    CmdList[si]        ; Call command routine
  190.     ret
  191.  
  192. Strategy        ENDP
  193.  
  194. ;*---------------------------- Unsupported ---------------------------*
  195. ;*  Handle a required but unsupported request                         *
  196. ;*                                                                    *
  197. ;*  Input: ES:BX = address of request packet                          *
  198. ;*                                                                    *
  199. ;*  OUTPUT: status byte set                                           *
  200. ;*--------------------------------------------------------------------*
  201. Unsupported    PROC    near    
  202.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  203.  
  204.         or    es:[bx].RP_Status, RP_StatusDone    ; Indicate DONE
  205.         ret
  206.  
  207. Unsupported    ENDP
  208.  
  209. ;*------------------------------ Open --------------------------------*
  210. ;*  Handle an open request.                                           *
  211. ;*                                                                    *
  212. ;*  Input: ES:BX = address of request packet                          *
  213. ;*                                                                    *
  214. ;*  Output: status byte set                                           *
  215. ;*--------------------------------------------------------------------*
  216. Open            PROC    near
  217.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  218.  
  219.         inc     [UserCount]                ; Add another user
  220.         or    es:[bx].RP_Status, RP_StatusDone    ; Indicate DONE
  221.         ret
  222.  
  223. Open            ENDP
  224.  
  225. ;*------------------------------ Close -------------------------------*
  226. ;*  Handle a close request.                                           *
  227. ;*                                                                    *
  228. ;*  Input: ES:BX = address of request packet                          *
  229. ;*                                                                    *
  230. ;*  Output: status byte set                                           *
  231. ;*--------------------------------------------------------------------*
  232. Close           PROC    near
  233.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  234.  
  235.     cmp     UserCount, 0        ; If no users, don't do anything
  236.         jz      NoUsers
  237.      dec     [UserCount]        ; Decrement number of users
  238. NoUsers:
  239.         or    es:[bx].RP_Status, RP_StatusDone  ; Indicate DONE
  240.         ret
  241.  
  242. Close           ENDP
  243.  
  244. ;*------------------------------ IOCtl -------------------------------*
  245. ;*  Handle a generic IOCtl request.                                   *
  246. ;*                                                                    *
  247. ;*  Input: ES:BX = address of request packet                          *
  248. ;*                                                                    *
  249. ;*  Output: status byte set                                           *
  250. ;*                                                                    *
  251. ;* Currently implemented via category 0x81 only                  *
  252. ;*    Function: 0x41h - return _SEG16 pointer to physical memory      *
  253. ;*    Function: 0x42h - return timer structure                        *
  254. ;*--------------------------------------------------------------------*
  255. IOCtl        PROC    near
  256.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  257.  
  258.     cmp    es:[bx].RPC_categ, 81h        ; Is it mine?
  259.     jz    lp0                ; Start checking if okay
  260. notme:     or    es:[bx].RP_Status, RP_StatusError + RP_StatusDone
  261.      mov    es:[bx].RP_ErrorCode, 13h
  262.      ret
  263.  
  264. lp0:    cmp    es:[bx].RPC_funct, 41h        ; Request for memory access?
  265.     jnz    lp1
  266.      call    GetPhyMem
  267.      ret
  268. lp1:    cmp    es:[bx].RPC_funct, 42h        ; Request for time information?
  269.     jnz    lp2
  270.      call    GetLocalTime
  271.      ret
  272. lp2:    jmp    notme
  273.  
  274. IOCtl        ENDP
  275.  
  276. ;*--------------------------- GetPhyMem ------------------------------*
  277. ;*  Handle request for access to physical memory                      *
  278. ;*                                                                    *
  279. ;*  Input: ES:BX = address of request packet                          *
  280. ;*                                                                    *
  281. ;*  Output: status byte set                                           *
  282. ;*--------------------------------------------------------------------*
  283. GetPhyMem    PROC    near
  284.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  285.  
  286.     push    bx            ; Save these so can recover later
  287.     push    es
  288. ;
  289.     push    ds
  290.     assume    ds:nothing
  291.     lds    si,es:[bx].RPC_parm
  292.     mov    bx,ds:[si]        ; Get low order address
  293.     mov    ax,ds:[si+2]        ; Get high order address
  294.     mov    cx,ds:[si+4]        ; Get length of access desired
  295.     mov    dh,1            ; Make segment R/W
  296.     pop    ds
  297.     assume    ds:DGROUP
  298. ;
  299.     mov    dl,DevHlp_PhysToUVirt    ; Convert physical to user LDT
  300.     call    [DevHlpPtr]        ; Get segment, etc.
  301.     mov    ax,es            ; Change LDT from ES:BX to
  302.     mov    cx,bx            ; LDT access via AX:CX now
  303. ;
  304.     pop    es            ; Restore header address
  305.     pop    bx
  306.  
  307.     push    ds            ; Save DS since will trash
  308.     lds    si,es:[bx].RPC_parm    ; Address of the parms
  309.     assume    ds:nothing
  310.     mov    ds:[si+8], cx        ; Save offset of LDT selector
  311.     mov    ds:[si+10], ax        ; Save segment of LDT selector
  312.     pop    ds            ; Restore DS again
  313.     assume    ds:DGROUP
  314. ;
  315.         or    es:[bx].RP_Status, RP_StatusDone  ; Indicate DONE
  316.         ret
  317.  
  318. GetPhyMem    ENDP
  319.  
  320. ;*--------------------------- GetLocalTime ---------------------------*
  321. ;*  Handle request for timer information                              *
  322. ;*                                                                    *
  323. ;*  Input: ES:BX = address of request packet                          *
  324. ;*                                                                    *
  325. ;*  Output: status byte set                                           *
  326. ;*--------------------------------------------------------------------*
  327. GetLocalTime    PROC    near
  328.         assume  cs:_TEXT,ds:DGROUP,es:nothing
  329.  
  330.     cmp    [HaveTimer],00        ; If not zero, no timer access
  331.     jz    OkayTimer
  332.      mov     es:[bx].RP_ErrorCode, 3    ; OS/2 Unknown Command RC
  333.      or      es:[bx].RP_Status, RP_StatusError + RP_StatusDone
  334.          ret
  335.  
  336. OkayTimer:
  337.     push    es
  338.      les    di,es:[bx].RPC_parm    ; Minimize time interrupts off
  339.      mov    si,offset TimerTicksStruct
  340.      movsw                ; Move 2 words for ns/tick first
  341.      movsw
  342.      cli
  343.      call    UpdateTimeStamp    ; Update running time stamp
  344.      movsw                ; Move 4 words (quicker than CX)
  345.      movsw
  346.      movsw
  347.      movsw
  348.      sti                ; Absolute minimum possible
  349.     pop    es            ; Restore header address
  350.  
  351.         or    es:[bx].RP_Status, RP_StatusDone  ; Indicate DONE
  352.         ret
  353.  
  354. GetLocalTime    ENDP
  355.  
  356. ;*------------------------------ Error -------------------------------*
  357. ;*  Handle an request I should never receive.                         *
  358. ;*                                                                    *
  359. ;*  INPUT: ES:BX = address of request packet                          *
  360. ;*                                                                    *
  361. ;*  OUTPUT: status byte set                                           *
  362. ;*--------------------------------------------------------------------*
  363. Error           PROC    near
  364.  
  365.         mov     es:[bx].RP_ErrorCode, 3        ; OS/2 Unknown Command RC
  366.                         ; Indicate DONE and ERROR
  367.         or      es:[bx].RP_Status, RP_StatusError + RP_StatusDone
  368.         ret
  369.  
  370. Error           ENDP
  371.  
  372. ;*---------------------------- Interrupt -----------------------------*
  373. ;*  DEVICE DRIVER TIME-INTERRUPT ROUTINE. CALLED ON EACH OS/2 CLOCK   *
  374. ;*  TICK (MC146818 CHIP) VIA THE SetTimer DevHlp.                     *
  375. ;*                                                                    *
  376. ;*  OUTPUT: Updated time stamp                                        *
  377. ;*--------------------------------------------------------------------*
  378. Interrupt       PROC    far
  379.  
  380.         pushf                           ; Save registers
  381.     call    UpdateTimeStamp        ; Does interrupts itself
  382.     popf
  383.         ret
  384.  
  385. Interrupt       ENDP
  386.  
  387. ;*------------------------- UpdateTimeStamp --------------------------*
  388. ;*  Update the running timestamp.  Routine goes off to 8253 and gets  *
  389. ;*  the current timer count, and adds delta to its running total. The *
  390. ;*  dword TimerTicks contains a cummulative sum of timer ticks since  *
  391. ;*  the start of the whole shooting shebang.                          *
  392. ;*                                                                    *
  393. ;*  INPUT: nothing                                                    *
  394. ;*                                                                    *
  395. ;*  OUTPUT: Updates [TimerTicks], [Last8253]                          *
  396. ;*                                                                    *
  397. ;*  NOTE: The 8253 counter counts from 65536 to zero                  *
  398. ;*                                                                    *
  399. ;*  Registers: <none>                                                 *
  400. ;*--------------------------------------------------------------------*
  401. UpdateTimeStamp PROC    near
  402.  
  403.         push    ax            ; Limit use to only AX and CX
  404.         push    cx
  405.  
  406.         ;*******************************************************************
  407.         ;* Number of ticks since the last timestamp update:                *
  408.         ;*                                                                 *
  409.         ;*     if( Last8253 >= cx )                                        *
  410.         ;*         Delta = (Last8253 - cx) * NanosIn1Tick                  *
  411.         ;*     else                                                        *
  412.         ;*         NanosecsDelta = (0xFFFF - cx + Last8253)                *
  413.         ;*                                                                 *
  414.         ;* where cx is the current 8253 tick count                         *
  415.         ;*******************************************************************
  416.  
  417.     mov     al,i8253CmdReadCtrZero    ; Request Counter Latch
  418.     out     i8253CtrlByteRegister,al
  419.     in      al,i8253CountRegister    ; Get LSB and save it
  420.     mov     cl,al
  421.     in      al,i8253CountRegister    ; Get MSB and save it
  422.     mov     ch,al
  423.  
  424.     mov     ax, [Last8253]        ; Get prior tick count
  425.     cmp     ax, cx            ; If it has wrapped (i.e. gone to zero
  426.     jae     NoWrap            ;   and started again from 65536):
  427. Wrap:     sub    ax,cx            ; Fast way for handling wrap
  428.      dec    ax            ; ax+0x1000-cx
  429.      jmp    short Update
  430. NoWrap:    sub    ax,cx            ; Difference since last timer tick
  431.  
  432. Update:    mov    [Last8253], cx        ; Save tick count for next interrupt
  433.     xor    cx,cx            ; Clear so can add later
  434.     add    word ptr [TimerTicks], ax
  435.     adc    word ptr [TimerTicks+2], cx
  436.     adc    word ptr [TimerTicks+4], cx
  437.     adc    word ptr [TimerTicks+6], cx
  438.  
  439.         pop     cx
  440.         pop     ax
  441.     ret
  442.  
  443. UpdateTimeStamp ENDP
  444.  
  445. ;*---------------------------- Initialize ----------------------------*
  446. ;*  Device driver intialization routine (discarded by OS2 after use)  *
  447. ;*                                                                    *
  448. ;*  INPUT: ES:BX = address of init packet                             *
  449. ;*                                                                    *
  450. ;*  Actions: (1) save devhlp address                                  *
  451. ;*           (2) output successful load message                       *
  452. ;*           (3) return appropriate end of segment informatino        *
  453. ;*                                                                    *
  454. ;*  OUTPUT: nothing                                                   *
  455. ;*                                                                    *
  456. ;*--------------------------------------------------------------------*
  457. CSEG_END    label    byte            ; last byte of device driver
  458.  
  459. Initialize      PROC    near
  460.             assume  cs:_TEXT,ds:DGROUP
  461.  
  462.         mov     ax, word ptr es:[bx].RPI_CodeSegLen    ; Save pointer to 
  463.         mov     word ptr [DevHlpPtr], ax        ; Device Helper routine
  464.         mov     ax, word ptr es:[bx].RPI_DataSegLen
  465.         mov     word ptr [DevHlpPtr+2],ax
  466.  
  467.     mov    es:[bx].RPI_CodeSegLen, offset CSEG_END    ; End of code seg
  468.     mov    es:[bx].RPI_DataSegLen, offset DSEG_END    ; End of data seg
  469.     or    es:[bx].RP_Status, RP_StatusDone    ; Indicate DONE
  470.  
  471. ; Do initial sign-on message.  Init is done at ring three, and some of the
  472. ; API's can be safely called from here
  473.     push    es
  474.     push    bx
  475.     .386P
  476.         push    stdout                          ; Write copyright info
  477.         push    ds
  478.         push    offset ds:CopyRightMsg
  479.         push    CopyRightMsgLen
  480.         push    ds
  481.         push    offset BytesWritten
  482.         call    DosWrite
  483.     .286P
  484.     pop    bx
  485.     pop    es
  486.  
  487. ; Initialize the timer/counter for my usage
  488.     cli                                     ; Disable interrupts
  489.     mov     al, i8253CmdInitCtrZero         ; Set 8253 counter 0 to mode 2
  490.     out     i8253CtrlByteRegister, al       ;     ( Rate generator )
  491.     xor     ax, ax                          ; Init Count Register to zero
  492.     out     i8253CountRegister, al          ;   by writing 0 to LSB
  493.     out     i8253CountRegister, al          ;   and MSB
  494.     sti                                     ; Enable interrupts
  495.  
  496.     mov    ax, offset Interrupt        ; Our timer hook address
  497.     mov    dl, DevHlp_SetTimer        ; SetTimer function
  498.     call    [DevHlpPtr]            ; Call Device Helper routine
  499.     jnc    NoErr
  500.      mov    [HaveTimer], 0FFh;        ; Remember we have no timer 
  501. NoErr:    ret
  502.  
  503. Initialize      ENDP
  504.  
  505. _TEXT        ENDS
  506.  
  507. END
  508.