•  Back 
  •  Treibertypen 
  •  Index 
  •  Tree View 
  •  Cross references 
  •  Help page 
  •  Show info about hypertext 
  •  View a new file 
Topic       : TOS - das Betriebssystem
Author      : 
Version     : tos.hyp (5. März 2013)
Subject     : Programmieren/Atari
Nodes       : 3001
Index Size  : 93602
HCP-Version : 5
Compiled on : Atari
@charset    : atarist
@lang       : 
@default    : Titel
@help       : 
@options    : +g -i -s +x +zz -t4
@width      : 70
View Ref-File15.6.4.2  GDPS, virtuelle Speicherverwaltung                       TOS

#define VOR              1
#define ZURUECK         -1
#define MITTE            0

/********************************************************************/
/*                        Scannerstrukturen                         */
/********************************************************************/
typedef struct                   /* Übergabestruktur für Scanner    */
{
   void  *next;                  /* Zeiger auf den nächsten Treiber */
   char  kennung[4];             /* Magic GDPS als Treiberkennung   */
   int   version;                /* Versionsnummer, derzeit < 200   */
   int   typ;                    /* Treiberart, 0 für Scanner       */
   char  *info;                  /* Zeiger auf Treiberinfo und die  */
   char  *copyright;             /* Copyrightmeldung                */
   int   gerbesch;               /* Gerätebeschreibungsflags        */
   int   farben;                 /* Anzahl der Farben 0=SW          */
   int   deep;                   /* mögliche Bittiefen              */
   int   free;                   /* Flag ob Scanner frei ist        */
   int   befehl;                 /* Kommando an Scanner             */
   void  *command;               /* Zeiger auf die Kommandostruktur */
} SCANHEADER;

typedef struct                 /* Kommandostruktur für GDPI-Scanner */
{
   int   result;                 /* Ergebnis das Treiber meldet     */
   int   modi;                   /* Erlaubte Scanmodi               */
   int   tiefe;                  /* Tiefe des Bildes in Bit/Pixel   */
   void  *vspeicher;             /* Dahin soll das Bild gehen       */
   long  vmaxlen;                /* verfügbarer Speicher            */
   int   bytebreite;             /* Breite einer Zeile in Bytes     */
   int   hoehe;                  /* Hoehe des Bildes in Zeilen      */
   int   mmbreite;               /* Breite und Höhe in 1/10 Milli-  */
   int   mmhoehe;                /* metern                          */
   int   xdpi;                   /* Auflösung in x und y-Richtung   */
   int   ydpi;
   int   modulo;                 /* 2=>Bild wird Wordbündig         */
   int   start_x;                /* linke obere Ecke x in 1/10mm    */
   int   start_y;                /* linke obere Ecke y in 1/10mm    */
   long  ser_nr;                 /* Seriennummer                    */

/****
der nun folgende Teil ist nur beim Aufruf des Scanners mit
den Befehlen der 0x2XX Serie definiert
******/
   int     add_bits;              /* Angabe, wieviele Bits zusätzlich*/
                                  /* z.B. besitzt CRANACH Studio     */
                                  /* zu jedem Bild 2 Masken. Wird    */
                                  /* eine Bitmap gescant, so benötigt*/
                                  /* das Programm nicht nur 1 BIT pro*/
                                  /* Pixel, sonder drei Bit          */
                                  /* Analog dazu müßten bei einem    */
                                  /* Grautonbild 8 + 2 = 10 Pixel    */
                                  /* berechnet werden. Sollte dieser */
                                  /* Wert nicht beachtet werden, so  */
                                  /* kann es nach dem Scannen passieren*/
                                  /* daß CRANACH Studio das Fenster  */
                                  /* nicht öffnen kann, da zwar für  */
                                  /* das gescannte Bild Speicher vor-*/
                                  /* handen ist, nicht aber für die  */
                                  /* notwendigen Masken.             */
                                  /* gebraucht werden, z.B. zwei     */
                                  /* zusätzliche Bits für die Maske  */
   void *Dchange_pointer;         /* Zeiger auf diese Funktion       */
   void *Dupdate;                 /* Zeiger auf jene Funktion;       */
   int  lesen;                    /* Lesebufferindex virtuell        */
   int  schreiben;                /* Schreibbufferindex virtuell         */
   int  virt_flag;                /* flag, ob virtuell gearbeitet wird   */
} SCANCOM;
SCANCOM scancom;

void *Dchange_pointer(
                        void *pointer,
                         int v_handle,
                         int richtung,
                         long *max_vor,
                         long *max_zurueck
                       );


void Dupdate(int v_handle);


Alle tms Produkte arbeiten mit einer virtuellen Speicherverwaltung.
Dies bedeutet, es muß auf nicht im RAM befindliche Speicherbereiche
zugegriffen werden. Die in tms- Produkte implementierte virtuelle
Speicherverwaltung wurde für die Belange von Bildern optimiert.

Allg. vorgehensweise: Der Treiber übergibt in scancom.schreiben eine
virtuelle Handle. Mit dieser Handle kann nun auf die virtuellen Daten
zugegriffen werden. Die Daten werden automatisch von der Platte,
wenn nötig, nachgeladen und gespeichert.

Eine mögliche Anwendung wäre:

UCHAR *real;
long max_vor, max_zurueck;

scancom->vspeicher zeigt auf den freien virtuellen Speicher.
Dieser ist wie ein normaler Speicher zu betrachten,
also z.B. freier Speicher von Adrr 16MB bis Adrr 50MB
mit scancom->vspeicher = Adrr 30MB
Da diese Adresse nicht wirklich existiert, muss der Pointer
auf einen realen Speicher abgebildet werden, und die Daten auf der
Platte geladen werden. das erledigt die Funktion Dchange_pointer.

 real = (UCHAR*)Dchange_pointer(
                                   scancom->vspeicher,
                                   scancom->schreiben,
                                   VOR,
                                   &max_vor,
                                   &max_zurueck
                                 );

real zeigt jetzt also auf einen RAM- Bereich.

scancom->schreiben ist die vom Programm übergebene Speicherhandle

VOR sagt der Speicherverwaltung, daß wir uns vor allem nach vorne
im Speicher bewegen werden. Somit können die Plattenzugriffe optimiert
werden.

max_vor liefert zurück, wieviele Bytes ab real im Speicher nach vorne
gelaufen werden darf.

max_zurück liefert zurück, wieviele Bytes ab real im Speicher nach
hinten gelaufen werden darf.

Werden diese Grenzen erreicht, so muß Dchange_pointer erneut aufgerufen
werden. Die Mindestlänge für max_vor und max_zurück:
                    VOR           ZURÜCK                    MITTE
max_vor:            32k             0k                       16k
max_zurück:         0k              32k                      16k

Der Ram Speicher ist in 6 Blöcke unterteilt, von denen jeder einen
unterschiedlichen oder aber auch einen Überlappenden Teil des virtuellen
Speichers abbilden kann. Um beim Überlappen von Blöcken zu gewährleisten,
das nach einer Speicheränderung alle Blöcke den aktuellen Speicherinhalt
wiedergeben, wird die Funktion Dupdate(scancom->schreiben) aufgerufen.
Diese aktualisiert die anderen Blöcke. Dupdate ist aber nur nötig bevor
auf einen anderen Block zugegriffen wird. Für einen Scannertreiber der nur
den Block scancom->schreiben benutzt reicht es deshalb am Schluss des
Scannens Dupdate(scancom->schreiben) aufzurufen.

Beispiel löschen von 10Mb ab Adresse 32MB

v_pointer=32Mb
size=10Mb

while(size>0)
{
        real=Dchange_pointer(
                              v_pointer,
                              scancom->schreiben,
                              VOR,
                              &max_vor,
                              &max_zurueck);
        if(max_vor<=size)
        {
                memset(real,0,max_vor);
                size-=max_vor;
                v_pointer+=max_vor;
        }
        else
        {
                memset(real,0,size);
                size=0;
                v_pointer+=size;
        }
}
Dupdate(scancom->schreiben);  !!!!!!!!!!!!!



****************************************************************************
Alte Programme rufen den Scanner mit dem Befehl 0x100 (und nicht 0x200)
auf. Diese Programme (z.B. tms CRANACH) nutzen noch keine virtuelle
Speicherverwaltung. Daher ist die Structure SCANCOM ab der gekennzeichneten
Stelle nicht definiert. Die Funktionen Dchange_pointer bzw. Dupdate
sollten dann durch dummy_Funktionen im Treiber ersetzt werden.

/********************************************************************/

mögliche Anwendung als ACC.

/********************************************************************/
/*    main()                                                        */
/*                                                                  */
/*    Kernstück des Programms.                                      */
/********************************************************************/

int main( void )
{
        int work_in[12],work_out[58],dummy;
        int buffer[20];

   appl_id = appl_init();

        /* öffnen eine eigenen Workstation */
        handle=graf_handle(&dummy,&dummy,&dummy,&dummy);
   for(dummy=0;dummy<10;work_in[dummy++]=1);
        work_in[10]=2;
        v_opnvwk(work_in,&handle,work_out);

   if(!rsrc_load("SCANNER.RSC"))
   {
      form_alert(0,NO_RSC_FILE);
      goto FOREVER;
   }

   if( appl_id != -1 )
   {
      if( !_app )
      {
         scanner_moeglichkeiten();
         menu_id = menu_register( appl_id, "  SCANNER" );
         event_loop();   /* hier wird auf den Aufruf des Treibers */
                         /* durch das Programm gewartet, der      */
                         /* Dialog wird geführt, das Bild gescannt*/
                         /* und die Werte in der
      }

   }
FOREVER: /* Initialisierung hat nicht geklappt */
   while(1)
        evnt_mesag((int*)buffer);
}

/********************************************************************/
/* Scanner initialisieren                                         */
/********************************************************************/

void scanner_moeglichkeiten()
{
        long
                **zeiger;
        long
                stack;

/********** Zeiger auf GDPS verbiegen *******************************/

        stack=Super(0);

        zeiger = (long **)0x41c;

        if(*(*zeiger+1)== 0x47445053l)
                header.next = *zeiger;
        else
                header.next = NULL;

        *zeiger = (void *)&header;

        Super((void *)stack);

/********************************************************************/

        sprintf(header.kennung,"GDPS");
        header.version          =100;
        header.typ              =0;           /* scanner */
        header.info             =info;
        header.copyright        =copyright;
        header.gerbesch         =1 | 2 | 4;   /* Gerätebeschreibungsflags */
        header.farben           =1;           /* Anzahl der Farben 0=SW   */
        header.deep             =1 | 16;      /* mögliche Bittiefen       */
        header.free             =0;
        header.befehl           =0;           /* Kommando an Scanner      */
        header.command          =&command;

}