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