[comp.sys.ibm.pc] Emulex DCP-88/VM under OS/2

nick@motto.UUCP (Nick Woodbridge) (01/06/89)

		*** Dual Ported Memory Device Drivers ****

	I want to run a synchronous I/O board under OS/2,and the board uses
a dual-ported memory window configurable from 0 to 960K to communicate with
the main processor.   Does anyone have any experience of writing OS/2 device
drivers to handle this type of peripheral board?
	If so can you provide any software?
	The board in question is the Emulex DCP-88/VM board with four
synchronous ports.

	I would also like to hear from anyone who knows of other multi-port 
RS-232C synchronous AT compatible boards that are available.

	Our application is to run the HDLC protocol on the link.So in addition
to all the above,does anyone know of OS/2 software packages to handle HDLC?   

Nicholas Woodbridge
Motorola Canada, Ltd.
416-499-1441 ext. 3161
uunet!mnetor!motto!nick

wei@hpctdls.HP.COM (Bill Ives) (01/10/89)

    I have had experience writting such a driver for OS/2 to 
    communicate with another processor accross a dual-port
    memory area. Unfortunately I cannot give the code due to
    its propriatary nature, but I can give you some hints to
    make it easier for you to develop your own code.  First, this
    type of DD is the easiest since its not interrupt driven --
    thus I was able to ignor all device help routines associated 
    with request packets.

    Some initial requirements:

    To make OS/2 ignor your segment of shared memory at boot time
    it must be non-contiguous with the rest of memory -- it can
    still use partial address decoding though.

    Your device driver must be included in a device statement in
    config.os2 file. 

    Within you device driver, you should define it as a character
    device not a block device -- this make everything else easier.
    The device strategy routine should only have to route the
    open, close , and devIOCTL calls.  The open and close correspond
    to DosOpen and DosClose calls respectively.  The devIOCTL 
    cooresponds to DosDevIOCTL call, which takes at most two
    32bit parameters which your routines can define. Normally, these
    can be pointers to parameter buffers.

    With the DD, only keep physical addresses - as these must be
    converted to valid descriptors each time your called and freed
    afterward -- see documentation on devHelp routines PhysToVirt and
    VirtToPhys to do this.  Since your writing a shared memory driver
    the device initialization routine can use your physical address to
    obtain a virtual address -- and then it can initialize it appropriately.
    Remember, if there is any chance for contention in the shared memory
    you should set up a ram semaphore located within the shared memory 
    (so that the other side can access it.).  This last point is a matter
    of how you set up the protocol.

    Whenever your strategy routine encounters the devIOCTL call ( presumably
    to do reads/writes to the memory ) you should validate the
    virtual addresses passed to you from the caller with VerifyAccess devHlp
    routine -- this will help with those general protection faults.

    The last area of concern is that of the return code passed back
    in AX when exiting the DD.  You should return device failure 0CH
    for any errors and an Okay return code otherwise. Some sample code
    is shown below:


    ; To assemble and create SYS file do:
    ;   MASM SHAREMEM
    ;   LINK SHAREMEM,SHAREMEM.SYS,,DOSCALLS,SHAREMEM;
    maxcmd equ 25  ; max allowed command code.
    

    DGROUP   group  _DATA
    _DATA    segment word public 'DATA'
    header   dd  -1   ; DD link to next DD
             dd 88C0h ; device attr word
             dd Strat ; strategy routine entry point
             dw 0     ; reserved 
             db 'SMEM0000' ; logical device name
             db 8 dub (0) ; reserved
     devhlp  dd  ?  ; DevHlp entry point

     ; Strategy routine dispatch table for
     ; request packet command code.
     dispch dw Init ; 0 = init driver
            dw Ignor; 1   media check
      ... etc ....
            dw DevOpen ; 13 = device open
            dw DevClose; 14 = device close
       ... etc ...
            dw GenIOCTL ; 16 = generic ICTL
       ... etc ...
            dw Error ; 26 = not used

       .. other global data goes here..

     _DATA   ends


     ;  macros and stuff goes here....

     _TEXT segment word public 'CODE'
           assume  cs:_TEXT,ds:DGROUP,es:NOTHING

     Strat  proc far  ; dd strategy routin called by os/2 kernel
                      ;  es:bx = addr of request packet.

          mov di,es:[bx+2]  ; get cmd code
          and di,0ffh
          cmp di,maxcmd     ; supported by this driver
          jle strat1        ; jump if okay
          call Error
          jmp  strat2
      strat1: add di,di  ; cmd code * 2
              call word ptr [di+dispch]  ; branch to routine
      strat2: mov  es:[bx+3],ax ; ax into request packet retcode field
          ret
      Strat endp


      ;  retcodes  0100h if done with no error
      ;            0000h if thread should be blocked pending interrupt
      ;            81xxh if done and error detected ( xx=error code )


      DevOpen  proc near  ; function 13 = device open
              .. do open of shared memory.. i.e. initialization etc.
      DevOpen  endp

      DevClose proc near
      DevClose endp

      GenIOCTL proc near 
               push es
               push bx
               ... get user specified params and read/write
                   shared memory appropriately.
               on error mov ax,810ch
               on okay  mov ax,0100h
               pop bx
               pop es
               ret  
      GenIOCTL endp

      Error proc near  ; bad cmd code
            mov ax,8103h   ; unknown command error.
            ret
      Error endp

      Init proc near
           .... do initialization of device
                and shrink the SYS image down
                by writing the end of the code and data
                segs into the request packet like:
          mov word ptr es:[bx+14],offset _TEXT:Init
          mov word ptr es:[bx+16] offset DGROUP:thelastdiscardablevarindataseg
          ....
          ret
       Init endp
       _TEXT ends
             end