home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / pascal / 4571 < prev    next >
Encoding:
Internet Message Format  |  1992-07-27  |  7.2 KB

  1. Path: sparky!uunet!munnari.oz.au!ariel!ucsvc.ucs.unimelb.edu.au!lugb!lux!9125113g
  2. From: 9125113g@lux.latrobe.edu.au (Mitch Davis)
  3. Newsgroups: comp.lang.pascal
  4. Subject: Re: how to write drivers?
  5. Message-ID: <1992Jul27.152842.7935@lugb.latrobe.edu.au>
  6. Date: 27 Jul 92 15:28:42 GMT
  7. References: <dedmunds.711612389@sfu.ca>
  8. Sender: news@lugb.latrobe.edu.au (USENET News System)
  9. Organization: La Trobe University
  10. Lines: 226
  11.  
  12. In article <dedmunds.711612389@sfu.ca> dedmunds@selkirk.sfu.ca (Darran Edward Edmundson) writes:
  13. >Can someone explain in some detail how drivers are written and used
  14. >within a program?
  15.  
  16. I'm having to assume that you mean device drivers.  Many moons ago, in
  17. the Fidonet International Pascal Conference, someone stated that "C was
  18. better than Pascal because you could write device drivers in C".
  19.  
  20. Well, much to our amazement, Duncan Murdoch managed to produce such a
  21. beast, and here it is:
  22.  
  23. On: Tue 28 May 91 11:18p
  24. By: Dj Murdoch
  25. To: All
  26. Re: **** Device driver in TP *****
  27. -----------------------------------------------------------------------------
  28. They said it couldn't be done!  (In fact, I think I was one of the 
  29. naysayers...)
  30.  
  31. "TP can't create the special format of file that's needed for a device
  32. driver."
  33.  
  34. Wrong!!
  35.  
  36. I've written a simple device driver in TP, and it works.  From some
  37. things I've heard, it won't work in all versions of DOS (it's an .EXE 
  38. format device driver, not a .BIN format one).  There are tons of 
  39. restrictions on what you can do in it - DOS isn't reentrant, and the 
  40. TP system library isn't designed to do things while DOS is active, so 
  41. I don't even let it get initialized, etc., etc.
  42.  
  43. It's still a bit of a mess, but here it is, for your enjoyment and
  44. edification:
  45.  
  46.  a character device driver that keeps a buffer of 255 characters, called
  47. TPDEVICE.
  48.  
  49. To try it out, compile it (you'll need OPro or TPro; sorry, but stack
  50. swapping is essential, and I wouldn't want to try to write code to do 
  51. it myself), put it into your CONFIG.SYS (on a floppy disk, please!) as
  52.  
  53.   device=tpdev.exe
  54.  
  55. and then reboot.   Hopefully you won't crash, but if you do, you'll have
  56. to reboot from a different disk and remove it from CONFIG.SYS.
  57.  
  58. Then you can try
  59.  
  60.   COPY TPDEVICE CON
  61.  
  62. to see the initialization message, and
  63.  
  64.   ECHO This is a line for the buffer >TPDEVICE
  65.  
  66. to replace it with a new one.
  67.  
  68. Enjoy!!
  69.  
  70. I'll be uploading TPDEV.ZIP to 1:221/177 (519-578-9314), in case the
  71. file gets too mangled in transmission to be recompiled, or you want to 
  72. try it out without having TPRO or OPRO.  First call downloads accepted.
  73.  
  74. ----------------------------
  75.   { DOS character device driver written entirely in TP 6 }
  76.   { Written by D.J. Murdoch for the public domain, May 1991 }
  77.   {$S-,F-}{ Stack checking wouldn't work here, and we assume near calls }
  78.   {$M $1000,0,0}   { We can't use the heap and don't use the stack.
  79.                      This setting doesn't really matter though, since 
  80.                      you normally won't run TPDEV }
  81.  
  82.   program tpdev;
  83.  
  84.   uses opint;  { OPro interrupt services, needed for stack switching }
  85.  
  86.   procedure strategy_routine(bp:word); interrupt; forward;
  87.   procedure interrupt_routine(bp:word); interrupt; forward;
  88.  
  89.   procedure header;  { Here's the trick:  an assembler routine in the
  90.                        main program, guaranteed to be linked first in
  91.                        the .EXE file!! }
  92.   assembler;
  93.   asm
  94.     dd $FFFFFFFF    { next driver }
  95.     dw $8000        { attributes of simple character device }
  96.     dw offset strategy_routine
  97.     dw offset interrupt_routine
  98.     db 'TPDEVICE'
  99.   end;
  100.  
  101.   const
  102.     stDone = $100;
  103.     stBusy = $200;
  104.  
  105.     cmInit = 0;
  106.     cmInput= 4;
  107.     cmInput_no_wait = 5;
  108.     cmInput_status = 6;
  109.     cmInput_flush = 7;
  110.     cmOutput = 8;
  111.     cmOutput_Verify = 9;
  112.     cmOutput_status = 10;
  113.     cmOutput_flush = 11;
  114.  
  115.   type
  116.     request_header = record
  117.       request_length : byte;
  118.       subunit: byte;
  119.       command_code : byte;
  120.       status : word;
  121.       reserved: array[1..8] of byte;
  122.       case byte of
  123.       cmInit : (num_units : byte;
  124.                 first_free : pointer;
  125.                 args : ^char;
  126.                 drive_num : byte;
  127.                );
  128.       cmInput :  { also used for output }
  129.                  (media_descriptor : byte;
  130.                  buffer : pointer;
  131.                  byte_count : word);
  132.       cmInput_no_wait : (next_char : char);
  133.     end;
  134.  
  135.   var
  136.     local_stack : array[1..4000] of byte;
  137.     end_of_stack : byte;
  138.     request : ^request_header;
  139.     line : string;
  140.  
  141.   procedure handler(var regs : intregisters);
  142.   { This routine is called by the strategy routine, and handles all requests.
  143.     The data segment is okay, and we're running on the local_stack so we've got
  144.    plenty of space, but remember:
  145.      ****** The initialization code for SYSTEM and all other units hasn't
  146.             ever been called!!  ******** }
  147.   begin
  148.     with request^ do
  149.     begin
  150.       case command_code of
  151.       cmInit: begin
  152.                 first_free := ptr(dseg,ofs(saveint75)+4);{ Last thing in the
  153.                                                            data segment in TP6}
  154.                                                          { No heap!! }
  155.                 status := stDone;
  156.                 line := 'TPDRIVER successfully initialized.';
  157.               end;
  158.       cmInput: begin
  159.                  if byte_count > length(line) then
  160.                    byte_count := length(line);
  161.                  move(line[1],buffer^,byte_count);
  162.                  line := copy(line,byte_count+1,255);
  163.                  status := stDone;
  164.                end;
  165.       cmInput_no_wait:
  166.                begin
  167.                  if length(line) > 0 then
  168.                  begin
  169.                    next_char := line[1];
  170.                    status := stDone;
  171.                  end
  172.                  else
  173.                    status := stBusy;
  174.                end;
  175.       cmInput_Status,cmOutput_Status,cmInput_Flush,cmOutput_Flush:
  176.                status := stDone;
  177.  
  178.       cmOutput,cmOutput_Verify:
  179.                begin
  180.                  if byte_count + length(line) > 255 then
  181.                    byte_count := 255 - length(line);
  182.                  move(buffer^,line[length(line)+1],byte_count);
  183.                  line[0] := char(byte(byte_count+length(line)));
  184.                  status := stDone;
  185.                end;
  186.       end;
  187.     end;
  188.   end;
  189.  
  190.   procedure RetFar; assembler;
  191.   { Replacement for the IRET code that ends the interrupt routines below }
  192.   asm
  193.     mov sp,bp
  194.     pop bp
  195.     pop es
  196.     pop ds
  197.     pop di
  198.     pop si
  199.     pop dx
  200.     pop cx
  201.     pop bx
  202.     pop ax
  203.     retf
  204.   end;
  205.  
  206.   procedure strategy_routine(bp:word);
  207.   var
  208.     regs : intregisters absolute bp;
  209.   begin
  210.     with regs do
  211.       request := ptr(es,bx);
  212.     RetFar;
  213.   end;
  214.  
  215.   procedure interrupt_routine(bp:word);
  216.   var
  217.     regs : intregisters absolute bp;
  218.   begin
  219.     SwapStackandCallNear(Ofs(handler),@end_of_stack,regs);
  220.     RetFar;
  221.   end;
  222.  
  223.   begin
  224.     writeln('TPDEVICE - DOS device driver written *entirely* in Turbo Pascal.');
  225.     writeln('Install using DEVICE=TPDEV.EXE in CONFIG.SYS.');
  226.     request := @header;  { Need a reference to pull in the header. }
  227.   end.
  228.  
  229.  
  230. --- Msg V3.2
  231. @PATH: 221/177 12/12 13/13 124/4115 640/301 634/384
  232.  * Origin: Murdoch's Point: Waterloo, Ontario, Canada (1:221/177.40)
  233.  
  234. I hope this has helped you.  I'm sure Duncan (who is a regular in this
  235. newsgroup) will help you if you have problems.
  236.  
  237. Mitch.
  238.