few@gupta.portal.com (Frank Whaley) (04/05/91)
The attached shar file comprises a demonstration of building MS-DOS Installable Device Drivers with C (currently Turbo C and Microsoft C). I once had a much larger package designed for the days of crude compilers. Things have improved so I have constructed a new package that does more in less space. Frank Whaley Software Engineer Gupta Technologies few@gupta.com Water separates the people of the world; Wine unites them. ----- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # mono.c # idd.h # iddstart.asm # tc.bat # msc.bat # This archive created: Thu Apr 4 07:55:21 1991 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'mono.c' then echo shar: "will not over-write existing file 'mono.c'" else sed 's/^X//' << \SHAR_EOF > 'mono.c' X/* X * mono.c - monochrome screen device driver X * X * This code provides a device driver for a device named "MON" X * which can be opened and written to like any character device. X * Output is directed to the monochrome display. This device X * was once handy for debugging a graphics program. Now it is X * just an example of how to build Installable Device Drivers X * with C. For practice, try expanding MON into CON, and provide X * a replacement for ANSI.SYS. X * X * Note that drivers that provide interrupt handlers must be built X * with Turbo C in the 'tiny' (-mt) model. The -mt switch causes X * interrupt functions to use the code segment variable DGROUP@ X * for finding the local data segment, instead of making a reference X * to the group DGROUP which requires a fixup. X */ X X#include "idd.h" X X#define VidSeg (word far *)0xB0000000 /* addr of monochrome video RAM */ X#define Attr 0x0700 /* video attribute mask */ X#define Blank (Attr + ' ') /* a blank */ X Xint row; /* current row number */ Xint col; /* current column number */ X Xword far *VidAddr; /* -> current display character */ X X /* forward declarations */ Xvoid cls(void); Xvoid output(Request far *req); Xvoid putone(char c); Xvoid scrollUp(void); Xvoid wordCopy(word far *from, word far *to, int len); Xvoid wordSet(word far *ptr, int len, word value); X X/* X * IDDmain - Installable Device Driver entry point X */ Xvoid XIDDmain(req, end) XRequest far *req; /* -> request header */ Xdword end; /* -> end of driver memory */ X{ X /* switch on command code */ X switch ( req->commandCode ) X { X case INIT: X cls(); X ((InitParms far *)req)->endAddr = end; X req->status = Done; X break; X X case OUTPUT: X case OUTVERIFY: X output(req); X /*FALLTHRU*/ X case OUTSTATUS: X case OUTFLUSH: X req->status = Done; X break; X X default: /* oops */ X req->status = (Error + Done + UnknownCommand); X break; X } X} X X/* X * output - handle output request X */ Xvoid Xoutput(Request far *req) X{ X InOutParms far *iop = (InOutParms far *)req; X byte far *ta; /* -> transfer addr */ X int ctr; /* byte count */ X char c; X X ta = (byte far *)iop->transfer; X ctr = iop->count; X X while ( ctr-- ) X switch ( c = *ta++ ) X { X case '\r' : X VidAddr -= col; X col = 0; X break; X X case '\n' : X VidAddr += 80; X if ( ++row > 24 ) X scrollUp(); X break; X X case '\b' : X if ( col ) X { X col--; X VidAddr--; X } X break; X X case '\t' : X do X putone(' '); X while ( col & 7 ); X break; X X case 0x1A : X cls(); X break; X X default : X putone(c); X break; X } X} X X/* X * cls - clear the screen X */ Xvoid Xcls() X{ X /* fill the screen with blanks */ X wordSet(VidSeg, 2000, Blank); X X row = col = 0; X VidAddr = VidSeg; X} X X/* X * scrollUp - scroll screen up one line X */ Xvoid XscrollUp() X{ X /* move up */ X wordCopy(VidSeg + 80, VidSeg, 1920); X /* clear last line */ X wordSet(VidSeg + 1920, 80, Blank); X X VidAddr -= 80; X row = 24; X} X X/* X * putone - display one character, scrolling at line-wrap X */ Xvoid Xputone(char c) X{ X *VidAddr++ = Attr + c; X X if ( ++col > 79 ) X { X VidAddr += (80 - col); X col = 0; X if ( ++row > 24 ) X scrollUp(); X } X} X X/* X * wordCopy - copy a range of words X */ Xvoid XwordCopy(word far *from, word far *to, int len) X{ X while ( len-- ) X *to++ = *from++; X} X X/* X * wordSet - set a range of words X */ Xvoid XwordSet(word far *ptr, int len, word value) X{ X while ( len-- ) X *ptr++ = value; X} X X/* END of mono.c */ SHAR_EOF fi if test -f 'idd.h' then echo shar: "will not over-write existing file 'idd.h'" else sed 's/^X//' << \SHAR_EOF > 'idd.h' X/* X * idd.h - Installable Device Driver header X */ X X /* magic Intel types */ Xtypedef unsigned char byte; Xtypedef unsigned int word; Xtypedef void far * dword; X X /* status word bits */ X#define Error 0x8000 X#define Busy 0x0100 X#define Done 0x0080 X X /* media descriptor byte bits */ X#define TwoSided 1 X#define EightSector 2 X#define Removable 4 X X /* error return codes */ X#define WriteProtect 0 X#define UnknownUnit 1 X#define DeviceNotReady 2 X#define UnknownCommand 3 X#define CRCError 4 X#define BadLength 5 X#define SeekError 6 X#define UnknownMedia 7 X#define SectorNotFound 8 X#define NoPaper 9 X#define WriteFault 10 X#define ReadFault 11 X#define GeneralFailure 12 X X /* function numbers */ X#define INIT 0 X#define MEDIACHECK 1 X#define BUILDBPB 2 X#define IOCTLIN 3 X#define INPUT 4 X#define NDINPUT 5 X#define INPUTSTATUS 6 X#define INPUTFLUSH 7 X#define OUTPUT 8 X#define OUTVERIFY 9 X#define OUTSTATUS 10 X#define OUTFLUSH 11 X#define IOCTLOUT 12 X#define DEVOPEN 13 X#define DEVCLOSE 14 X#define REMMEDIA 15 X X /* structures */ X Xtypedef struct X{ X byte length; X byte unitCode; X byte commandCode; X word status; X byte reserved[8]; X} Request; X Xtypedef struct X{ X Request reqHdr; /* Request Header */ X byte nUnits; /* number of units */ X dword endAddr; /* Ending Address */ X dword bpbArray; /* ptr to BPB array */ X} InitParms; X Xtypedef struct X{ X Request reqHdr; /* Request Header */ X byte mediaDesc; /* Media Descriptor */ X byte returnCode; /* Return Code */ X} MediaParms; X Xtypedef struct X{ X Request reqHdr; /* Request Header */ X byte mediaDesc; /* Media Descriptor */ X dword transfer; /* Transfer Address */ X dword bpbTable; /* ptr to BPB table */ X} BPBParms; X Xtypedef struct X{ X Request reqHdr; /* Request Header */ X byte mediaDesc; /* Media Descriptor */ X dword transfer; /* Transfer Address */ X word count; /* Byte/Sector Count */ X word start; /* Starting Sector Number */ X} InOutParms; X Xtypedef struct X{ X Request reqHdr; /* Request Header */ X byte Byte; /* Byte Read From Device */ X} ndInputParms; X Xtypedef struct X{ X Request reqHdr; X} StatusParms; X Xtypedef struct X{ X Request reqHdr; X} FlushParms; X Xtypedef struct X{ X word BytesPerSector; X byte SecsPerAllocUnit; X word ReservedSectors; X byte FATCount; X word RootDirEntries; X word SectorsPerLogical; X byte MediaDesc; X word SecsPerFAT; X} BPB; X Xtypedef struct X{ X byte BootJump[3]; X byte Name[8]; X BPB BootBPB; X word SecsPerTrack; X word HeadCount; X word HiddenCount; X} BootSector; X X/* END of idd.h */ SHAR_EOF fi if test -f 'iddstart.asm' then echo shar: "will not over-write existing file 'iddstart.asm'" else sed 's/^X//' << \SHAR_EOF > 'iddstart.asm' X PAGE 60, 132 XTITLE IDDStart - Installable Device Driver Header X X;-----------------------------------------------------------------------| X; Sample Installable Device Driver Header | X;-----------------------------------------------------------------------| X X; Segment declarations XIGROUP Group _TEXT, TAIL XDGROUP Group _DATA, CONST, c_common, _BSS, DTAIL X X_TEXT Segment Para Public 'CODE' X Assume CS:_TEXT X_TEXT EndS XTAIL Segment 'CODE' XTAIL EndS X_DATA Segment Para Public 'DATA' X Assume DS:_DATA X_DATA EndS XCONST Segment Byte Public 'CONST' XCONST EndS Xc_common Segment Byte Public 'BSS' Xc_common EndS X X_TEXT Segment X X;-----------------------------------------------------------------------| X; External declarations of driver functions | X;-----------------------------------------------------------------------| X X Extrn _IDDmain:Near X X ; where do we begin... X ORG 0 X XIDDStart Proc Far X X;-----------------------------------------------------------------------| X; Device Header | X;-----------------------------------------------------------------------| X X DD -1 ; -> next device (init to -1) X; CONFIGURE: the following value must be set specifically for your driver X DW 8000H ; character only X DW Strategy ; -> device strategy X DW Interrupt ; -> device interrupt X; CONFIGURE: the following value must be set specifically for your driver X DB "MON " ; driver name X X;-----------------------------------------------------------------------| X; Code Segment Variables | X;-----------------------------------------------------------------------| X Public DGROUP@ XDGROUP@ DW 0 ; our data segment Xrequest DD (?) ; copy of request hdr ptr XssEntry DW (?) ; entry SS XspEntry DW (?) ; entry SP X X PAGE X;-----------------------------------------------------------------------| X; Device Strategy | X; | X; ENTRY : ES:BX -> Request Header | X; | X; EXIT : all registers preserved | X; | X;-----------------------------------------------------------------------| X XStrategy: X ; save request hdr ptr X MOV Word Ptr CS:request,BX X MOV Word Ptr CS:request + 2,ES X RET X X PAGE X;-----------------------------------------------------------------------| X; Device Interrupt | X; | X; ENTRY : anything | X; | X; EXIT : all registers preserved | X; | X;-----------------------------------------------------------------------| X XInterrupt: X ; save the world X PUSH DS ; (+1) X PUSH ES ; (+2) X PUSH AX ; (+3) X PUSH BX ; (+4) X PUSH CX ; (+5) X PUSH DX ; (+6) X PUSH SI ; (+7) X PUSH DI ; (+8) X PUSH BP ; (+9) X X MOV CS:ssEntry,SS ; save entry SS X MOV CS:spEntry,SP ; and SP X X ; one-time compute of DS X MOV AX,CS:DGROUP@ X TEST AX,AX X JNE haveDS X X MOV AX,Offset IGROUP:TAIL ; compute our DS X X MOV CL,4 X SHR AX,CL X MOV CX,CS X ADD AX,CX X MOV CS:DGROUP@,AX X XhaveDS: X MOV BX,Offset DGROUP:locStk ; set our DS, SS, BP, and SP X MOV DS,AX X ;CLI ; very old chips need this X MOV SS,AX X MOV SP,BX X ;STI X MOV BP,BX X X ; call IDDmain(Request far *req, void far *end) X PUSH DS X MOV AX,Offset DGROUP:DTAIL X PUSH AX X PUSH Word Ptr CS:request + 2 X PUSH Word Ptr CS:request X CALL _IDDmain X X SUB SP,8 X X ; restore entry registers X MOV SS,CS:ssEntry X MOV SP,CS:spEntry X POP BP ; (+8) X POP DI ; (+7) X POP SI ; (+6) X POP DX ; (+5) X POP CX ; (+4) X POP BX ; (+3) X POP AX ; (+2) X POP ES ; (+1) X POP DS ; (+0) X RET X XIDDStart EndP X X_TEXT EndS X X PAGE X;-----------------------------------------------------------------------| X; Data Segment | X;-----------------------------------------------------------------------| X X_DATA Segment X X Public __acrtused X__acrtused EQU 9876H X X_DATA EndS X X_BSS Segment Word Public 'BSS' X DB 2048 Dup (?) ; our stack XlocStk Label Word X_BSS EndS X XDTAIL Segment Word 'BSS' XDTAIL EndS X X END IDDStart ; of IDDStart.asm SHAR_EOF fi if test -f 'tc.bat' then echo shar: "will not over-write existing file 'tc.bat'" else sed 's/^X//' << \SHAR_EOF > 'tc.bat' X: TC.BAT - build MONO.SYS with Turbo C 2.0 X: Note that TASM can't seem to build a version of iddstart.obj that X: doesn't require fixups. We may be doing an Evil Thing, but this X: is MS-DOS. Xmasm /mx/t iddstart; Xtcc -c mono.c Xtlink iddstart+mono,mono/x/c Xdel iddstart.obj Xdel mono.obj Xexe2bin mono.exe mono.sys Xdel mono.exe SHAR_EOF chmod +x 'tc.bat' fi if test -f 'msc.bat' then echo shar: "will not over-write existing file 'msc.bat'" else sed 's/^X//' << \SHAR_EOF > 'msc.bat' X: MSC.BAT - build MONO.SYS with Microsoft C (5.1 or 6.0) Xmasm /mx/t iddstart; Xcl -Gs -Zp -c mono.c Xlink iddstart+mono,mono; Xdel iddstart.obj Xdel mono.obj Xexe2bin mono.exe mono.sys Xdel mono.exe SHAR_EOF chmod +x 'msc.bat' fi exit 0 # End of shell archive -- Frank Whaley Software Engineer Gupta Technologies few@gupta.com
tommyp@ida.liu.se (Tommy Pedersen) (04/16/91)
Sorry, this is not an additional comment! But I saw this issue being brought up by Kraig Eno and Frank Whaley in the Expired list on my node, so if any of you two guys would like to email me your contributions you would make me very happy. And please if someone else has saved these, please send them to me. Thanks in advance, /Tommy Pedersen ________________________________________________________________ |E-mail: tommyp@isy.liu.se || Telephone: +46 13 282369 | |S-mail: Tommy Pedersen || FAX: +46 13 289282 | | Dept. of EE ||______________________________| | Linkoping University || | | S-581 83 Linkoping || | | SWEDEN || | |________________________________||______________________________|