home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!munnari.oz.au!ariel!ucsvc.ucs.unimelb.edu.au!lugb!lux!9125113g
- From: 9125113g@lux.latrobe.edu.au (Mitch Davis)
- Newsgroups: comp.lang.pascal
- Subject: Re: how to write drivers?
- Message-ID: <1992Jul27.152842.7935@lugb.latrobe.edu.au>
- Date: 27 Jul 92 15:28:42 GMT
- References: <dedmunds.711612389@sfu.ca>
- Sender: news@lugb.latrobe.edu.au (USENET News System)
- Organization: La Trobe University
- Lines: 226
-
- In article <dedmunds.711612389@sfu.ca> dedmunds@selkirk.sfu.ca (Darran Edward Edmundson) writes:
- >Can someone explain in some detail how drivers are written and used
- >within a program?
-
- I'm having to assume that you mean device drivers. Many moons ago, in
- the Fidonet International Pascal Conference, someone stated that "C was
- better than Pascal because you could write device drivers in C".
-
- Well, much to our amazement, Duncan Murdoch managed to produce such a
- beast, and here it is:
-
- On: Tue 28 May 91 11:18p
- By: Dj Murdoch
- To: All
- Re: **** Device driver in TP *****
- -----------------------------------------------------------------------------
- They said it couldn't be done! (In fact, I think I was one of the
- naysayers...)
-
- "TP can't create the special format of file that's needed for a device
- driver."
-
- Wrong!!
-
- I've written a simple device driver in TP, and it works. From some
- things I've heard, it won't work in all versions of DOS (it's an .EXE
- format device driver, not a .BIN format one). There are tons of
- restrictions on what you can do in it - DOS isn't reentrant, and the
- TP system library isn't designed to do things while DOS is active, so
- I don't even let it get initialized, etc., etc.
-
- It's still a bit of a mess, but here it is, for your enjoyment and
- edification:
-
- a character device driver that keeps a buffer of 255 characters, called
- TPDEVICE.
-
- To try it out, compile it (you'll need OPro or TPro; sorry, but stack
- swapping is essential, and I wouldn't want to try to write code to do
- it myself), put it into your CONFIG.SYS (on a floppy disk, please!) as
-
- device=tpdev.exe
-
- and then reboot. Hopefully you won't crash, but if you do, you'll have
- to reboot from a different disk and remove it from CONFIG.SYS.
-
- Then you can try
-
- COPY TPDEVICE CON
-
- to see the initialization message, and
-
- ECHO This is a line for the buffer >TPDEVICE
-
- to replace it with a new one.
-
- Enjoy!!
-
- I'll be uploading TPDEV.ZIP to 1:221/177 (519-578-9314), in case the
- file gets too mangled in transmission to be recompiled, or you want to
- try it out without having TPRO or OPRO. First call downloads accepted.
-
- ----------------------------
- { DOS character device driver written entirely in TP 6 }
- { Written by D.J. Murdoch for the public domain, May 1991 }
- {$S-,F-}{ Stack checking wouldn't work here, and we assume near calls }
- {$M $1000,0,0} { We can't use the heap and don't use the stack.
- This setting doesn't really matter though, since
- you normally won't run TPDEV }
-
- program tpdev;
-
- uses opint; { OPro interrupt services, needed for stack switching }
-
- procedure strategy_routine(bp:word); interrupt; forward;
- procedure interrupt_routine(bp:word); interrupt; forward;
-
- procedure header; { Here's the trick: an assembler routine in the
- main program, guaranteed to be linked first in
- the .EXE file!! }
- assembler;
- asm
- dd $FFFFFFFF { next driver }
- dw $8000 { attributes of simple character device }
- dw offset strategy_routine
- dw offset interrupt_routine
- db 'TPDEVICE'
- end;
-
- const
- stDone = $100;
- stBusy = $200;
-
- cmInit = 0;
- cmInput= 4;
- cmInput_no_wait = 5;
- cmInput_status = 6;
- cmInput_flush = 7;
- cmOutput = 8;
- cmOutput_Verify = 9;
- cmOutput_status = 10;
- cmOutput_flush = 11;
-
- type
- request_header = record
- request_length : byte;
- subunit: byte;
- command_code : byte;
- status : word;
- reserved: array[1..8] of byte;
- case byte of
- cmInit : (num_units : byte;
- first_free : pointer;
- args : ^char;
- drive_num : byte;
- );
- cmInput : { also used for output }
- (media_descriptor : byte;
- buffer : pointer;
- byte_count : word);
- cmInput_no_wait : (next_char : char);
- end;
-
- var
- local_stack : array[1..4000] of byte;
- end_of_stack : byte;
- request : ^request_header;
- line : string;
-
- procedure handler(var regs : intregisters);
- { This routine is called by the strategy routine, and handles all requests.
- The data segment is okay, and we're running on the local_stack so we've got
- plenty of space, but remember:
- ****** The initialization code for SYSTEM and all other units hasn't
- ever been called!! ******** }
- begin
- with request^ do
- begin
- case command_code of
- cmInit: begin
- first_free := ptr(dseg,ofs(saveint75)+4);{ Last thing in the
- data segment in TP6}
- { No heap!! }
- status := stDone;
- line := 'TPDRIVER successfully initialized.';
- end;
- cmInput: begin
- if byte_count > length(line) then
- byte_count := length(line);
- move(line[1],buffer^,byte_count);
- line := copy(line,byte_count+1,255);
- status := stDone;
- end;
- cmInput_no_wait:
- begin
- if length(line) > 0 then
- begin
- next_char := line[1];
- status := stDone;
- end
- else
- status := stBusy;
- end;
- cmInput_Status,cmOutput_Status,cmInput_Flush,cmOutput_Flush:
- status := stDone;
-
- cmOutput,cmOutput_Verify:
- begin
- if byte_count + length(line) > 255 then
- byte_count := 255 - length(line);
- move(buffer^,line[length(line)+1],byte_count);
- line[0] := char(byte(byte_count+length(line)));
- status := stDone;
- end;
- end;
- end;
- end;
-
- procedure RetFar; assembler;
- { Replacement for the IRET code that ends the interrupt routines below }
- asm
- mov sp,bp
- pop bp
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- retf
- end;
-
- procedure strategy_routine(bp:word);
- var
- regs : intregisters absolute bp;
- begin
- with regs do
- request := ptr(es,bx);
- RetFar;
- end;
-
- procedure interrupt_routine(bp:word);
- var
- regs : intregisters absolute bp;
- begin
- SwapStackandCallNear(Ofs(handler),@end_of_stack,regs);
- RetFar;
- end;
-
- begin
- writeln('TPDEVICE - DOS device driver written *entirely* in Turbo Pascal.');
- writeln('Install using DEVICE=TPDEV.EXE in CONFIG.SYS.');
- request := @header; { Need a reference to pull in the header. }
- end.
-
-
- --- Msg V3.2
- @PATH: 221/177 12/12 13/13 124/4115 640/301 634/384
- * Origin: Murdoch's Point: Waterloo, Ontario, Canada (1:221/177.40)
-
- I hope this has helped you. I'm sure Duncan (who is a regular in this
- newsgroup) will help you if you have problems.
-
- Mitch.
-