home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9203 / driver / drvframe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-06  |  8.0 KB  |  218 lines

  1. /* DRVFRAME.C - Rahmen für einen Zeichentreiber */
  2. /* HINWEIS: Benötigt das DOSLIB.OBJ , das zuvor mit TASM /MX DOSLIB
  3.    übersetzt werden muß
  4. */
  5. #include <stdio.h>
  6. #include <dos.h>
  7. #include <ctype.h>
  8. #include <stdlib.h>
  9. #include <conio.h>     /* <- *nicht* für Ausgaben innerhalb der Funktionen! */
  10. #include <ctype.h>
  11. #include "drvlib.inc"
  12. #include "doslib.h"
  13.  
  14. /* ------------- Der Treiber selbst ----------------------- */
  15. typedef struct   /* Kopf des Parameterblocks (REQUESTHEADER) */
  16.   { unsigned char DSize;    /* Größe des gesamten Blocks */
  17.     unsigned char DUnit;    /* Geräte-Kennziffer (relativ) */
  18.     unsigned char DFunc;    /* Funktionsnummer (0x00) */
  19.     unsigned DStatus;       /* Status als Ergebnis */
  20.     unsigned char DResvd[8];
  21.   } DrvBlock;
  22.  
  23. DrvBlock far *ParmBlock; /* Adresse des Parameterblocks,
  24.                 via "Strategie" gesetzt */
  25. typedef struct   /* Parameterblock für "Init" */
  26.  { unsigned char DSize;    /* Größe des gesamten Blocks */
  27.    unsigned char DUnit;    /* Geräte-Kennziffer (relativ) */
  28.    unsigned char DFunc;    /* Funktionsnummer (0x00) */
  29.    unsigned DStatus;       /* Status als Ergebnis */
  30.    unsigned char DResvd[8];
  31.     /* --- Funktionsabhängige Felder --- */
  32.    unsigned char DUnits;        /* Anzahl Laufwerke (nur für Block) */
  33.    void far *DEndAddr;          /* Endadresse, vom Treiber gesetzt */
  34.    char far *DCmdLine;          /* Adresse der "Kommandozeile" */
  35.    unsigned char DFirstDrv;     /* Kennziffer erstes Laufwerk (nur Block) */
  36.    unsigned DMsgFlag;           /* für Fehlermeldungen des Treibers */
  37.  } DrvInitBlock, far *DrvInitPtr;
  38.  
  39. #define DriverSize 0x400 /* Annahme: Treiber braucht 0x400 Bytes Platz */
  40. void DriverInit(void)   /* Treiberfunktion 0x00 */
  41. { char far *Cmd;
  42.   DrvInitPtr p;
  43.  
  44.   cputs("Funktion 0x00 (Init) - Parameter: ");
  45.   p = (DrvInitPtr)ParmBlock;  Cmd = p->DCmdLine;
  46.   while (*Cmd != 13)
  47.    { putch(*Cmd++);
  48.    }
  49.   cputs("\r\n");
  50.   /* Annahme: DriverInit ist die erste Routine des Treibers */
  51.   p->DEndAddr = MK_FP(FP_SEG(DriverInit),FP_OFF(DriverInit)+DriverSize+1);
  52.   p->DStatus = 0;  /* Error-Bit zurück */
  53. }
  54.  
  55. typedef struct   /* Parameterblock für "Write" */
  56.  { unsigned char DSize;    /* Größe des gesamten Blocks */
  57.    unsigned char DUnit;    /* Geräte-Kennziffer (relativ) */
  58.    unsigned char DFunc;    /* Funktionsnummer (0x08) */
  59.    unsigned DStatus;       /* Status als Ergebnis */
  60.    unsigned char DResvd[8];
  61.     /* --- Funktionsabhängige Felder --- */
  62.    unsigned char DMediaID;    /* Media-ID (nur Block) */
  63.    void far *DBuffer;         /* Quelladresse im Hauptspeicher */
  64.    unsigned DBytesOrSec;      /* Anzahl Datenbytes/Sektoren */
  65.    unsigned DStartSec;        /* erster Sektor (nur Block) */
  66.    void far *DVolID;          /* wird vom Treiber gesetzt (nur Block) */
  67.    long DStartLong;           /* Startsektor mit 32 Bit (nur Block) */
  68.  } DrvWriteBlock, far *DrvWritePtr;
  69.  
  70. void DriverWrite(void)    /* Treiberfunktion 0x08 */
  71. { unsigned Count;
  72.   char far *p;
  73.   DrvWritePtr Params;
  74.  
  75.   Params = (DrvWritePtr)ParmBlock;
  76.   p = Params->DBuffer;     /* Startadresse */
  77.   for (Count = 0; Count < Params->DBytesOrSec; Count++)
  78.    { _AL = p[Count];
  79.      __emit__(0xCD,0x29);  /* Ausgabe via Interrupt 0x29 */
  80.    }
  81.  
  82.   /* Params->DBytesorSec = <Anzahl geschriebener Bytes, redundant */
  83.   Params->DStatus = 0;  /* "Error" und "Busy"-Bit löschen */
  84. }
  85.  
  86. void far DoStrategy(void)  /* Strategie-Routine */
  87. {
  88.   __emit__(0x50,0x53,    /* push ax..dx - diese vier Register werden */
  89.        0x51,0x52);   /* von SwapValInCS bzw. MK_FP gebraucht! */
  90.   SwapValInCS(_DS);    /* SWAP von DS mit Turbo-DS */
  91.   __emit__(0x8E,0xD8);        /* asm mov ds,ax */
  92.   ParmBlock = MK_FP(_ES,_BX);
  93.   SwapValInCS(_DS);    /* TURBO-DS speichern, DS wieder setzen */
  94.   __emit__(0x8E,0xD8);  /* asm mov ds,ax */
  95.   __emit__(0x5A,0x59,0x5B,0x58);  /* pop dx..ax - Register zurück */
  96. }
  97.  
  98. void far DoInterrupt(void)      /* Interrupt-Routine */
  99. {     /* <- keine lokalen Variablen!! */
  100.   __emit__(0x50,0x53,0x51,      /* push ax/bx/cx/dx/si/di/es - ließe */
  101.        0x52,0x56,0x57,0x06  /* sich eleganter mit PUSHA/PUSH ES machen */
  102.       );
  103.   SwapValInCS(_DS);     /* SWAP DS/Turbo-DS */
  104.   __emit__(0x8E,0xD8);  /* asm mov ds,ax */
  105.  
  106.   switch(ParmBlock->DFunc)
  107.    { case 0 : DriverInit();
  108.           break;
  109.      case 8 : DriverWrite();
  110.           break;
  111.     default:
  112.        cprintf("Unbekannte Treiberfunktion: %d\n",ParmBlock->DFunc);
  113.        ParmBlock->DStatus = 0x8003;  /* "Error"-Bit setzen, Fehlercode */
  114.        break;
  115.    }
  116.  
  117.   ParmBlock->DStatus |= 0x100;  /* "Done"-Bit setzen */
  118.   SwapValInCS(_DS);             /* DS-Register wieder tauschen */
  119.   __emit__(0x8E,0xD8,           /* asm mov ds,ax */
  120.        0x07,0x5F,0x5E,0x5A, /* pop es/di/si/dx/cx/bx/ax, d.h. POPA/POP ES */
  121.        0x59,0x5B,0x58
  122.       );
  123. }
  124.  
  125. /* -------------------------------------------------------- */
  126. /* Reserviert einige über das Codesegment adressierbare Bytes
  127.    und liefert die Adresse dieses Bereichs zurück */
  128. void far *ReserveCS(void)
  129. { char far *StrPtr;
  130.  
  131.   for (StrPtr = MK_FP(_CS,0); FP_OFF(StrPtr) < 32766 &&
  132.      strcmp(StrPtr, "ReserveCS: Fehler!"); StrPtr++)
  133.         ;
  134.   if (FP_OFF(StrPtr) == 32766)
  135.    { cprintf("ReserveCS: Fehler!\n");
  136.      exit(1);
  137.    }
  138.   return StrPtr;
  139. }
  140.  
  141. /* Baut den durch CHARACS spezifizierten Treiber in die Kette ein */
  142. void LinkDriver(DriverPointer Characs, DrvInitPtr InitParams)
  143. { DriverPointer NULDev, NULNext;
  144.  
  145.   NULDev = GetFirstHeader();  /* Gerätetreiber NUL ermitteln */
  146.   NULNext = NULDev->DNext;    /* Zeiger auf den Nachfolger */
  147.   NULDev->DNext = Characs;  /* NUL -> NULNext wird zu */
  148.   Characs->DNext = NULNext; /* NUL -> Characs -> NULNext */
  149.   /* Direkter Aufruf der Strategie- und Interrupt-Routine
  150.     mit dem Initialisierungsblock */
  151.   CallStrategy(Characs, InitParams);
  152.   CallInterrupt(Characs);
  153. }
  154.  
  155. /* Baut den Treiber wieder aus der Kette aus */
  156. void UnlinkDriver(DriverPointer Characs)
  157. { DriverPointer NULDev = GetFirstHeader();
  158.  
  159.   NULDev->DNext = Characs->DNext;  /* NUL -> Characs -> Next */
  160. }                                  /* wird zu NUL -> Next */
  161.  
  162. DriverPointer BuildCharDriver(unsigned Attrib, char *DrvName)
  163. { DriverPointer DrvHead;
  164.   int x;
  165.  
  166.   SwapValInCS(_DS);      /* Turbo-Datensegment speichern */
  167.   DrvHead = ReserveCS();   /* Platz im Datensegment */
  168.   DrvHead->DAttr = Attrib;  /* Attribute des Treibers */
  169.   DrvHead->DStrat = FP_OFF(DoStrategy);
  170.   DrvHead->DIntr = FP_OFF(DoInterrupt);
  171.   for (x = 0; x < 8; x++) DrvHead->NameOrUnits[x] = ' ';
  172.   for (x = 0; x < strlen(DrvName); x++)
  173.      DrvHead->NameOrUnits[x] = toupper(DrvName[x]);
  174.   DrvHead->DNext = MK_FP(0xFFFF,0xFFFF);
  175.   return DrvHead;
  176. }
  177.  
  178. unsigned DrvAttrib = 0x8000;   /* zu setzendes Attribut */
  179. char DrvName[] = "DEMO";       /* zu setzender Name */
  180. char CmdLine[] =               /* "Kommandozeile" aus CONFIG.SYS */
  181.      "Parameter_1 Parameter_2\r\n";
  182.  
  183. main()
  184. { DriverPointer OurDriver;
  185.   DrvInitBlock InitParams;    /* Parameter zur Initialisierung */
  186.   /* - - - - - - - - - - - - */
  187.   FILE *fp;      /* nur zur Demonstration */
  188.  
  189.   OurDriver = BuildCharDriver(DrvAttrib,DrvName);
  190.   memset(&InitParams,0,sizeof(InitParams));
  191.   InitParams.DSize = sizeof(DrvInitBlock);
  192.   InitParams.DFunc = 0x00;
  193.   InitParams.DCmdLine = CmdLine;
  194.   InitParams.DEndAddr = MK_FP(0xA000,0);
  195.  
  196.   LinkDriver(OurDriver,&InitParams);
  197.  
  198.   /* - - - - - - - - - - - - - - - - - - - - - */
  199.   printf("Treiber %s eingebaut und initialisiert.\n",DrvName);
  200.   printf("Treiberkopf: 0x%Fp, Init-Routine 0x%Fp, EndAdresse 0x%Fp\n",
  201.        OurDriver,DriverInit,InitParams.DEndAddr);
  202.   printf("Zurückgelieferter Status: 0x%04X\n",InitParams.DStatus);
  203.  
  204.   printf("Öffnen von %s als Datei für Schreibaktionen: ",DrvName);
  205.   if ((fp = fopen(DrvName,"w")) == NULL)
  206.     printf("DOS-Fehlercode %d\n", errno);
  207.    else
  208.     { printf("OK!\n");
  209.       fprintf(fp,"Ein via Write über das Dateisystem ausgegebener Text.\n");
  210.       fclose(fp);
  211.     }
  212.   /* - - - - - - - - - - - - - - - - - - - - - - - */
  213.   UnlinkDriver(OurDriver);
  214.   printf("Treiber %s wieder ausgebaut.\n",DrvName);
  215.  
  216.   return 0;
  217. }
  218.