Topic : TOS - The Operating System Author : Version : tos.hyp (December 19, 2008) Subject : Programmieren/Atari Nodes : 3010 Index Size : 93790 HCP-Version : 5 Compiled on : Atari @charset : atarist @lang : @default : Title @help : @options : +g -i -s +x +zz -t4 @width : 70 View Ref-File13.6.4.2 GDPS, virtual memory management TOS #define VOR 1 #define ZURUECK -1 #define MITTE 0 /********************************************************************/ /* Scanner structures */ /********************************************************************/ typedef struct /* Passing structure for scanner */ { void *next; /* Pointer to the next driver */ char ident[4]; /* Magic GDPS as driver identifier */ int version; /* Version number, currently < 200 */ int type; /* Driver type, 0 for scanner */ char *info; /* Pointer to driver info and to */ char *copyright; /* the Copyright message */ int devdescr; /* Device description flags */ int colours; /* Number of colours, 0=B/W */ int deep; /* Possible bit-depths */ int free; /* Flag whether scanner is free */ int scommand; /* Command to scanner */ void *command; /* Pointer to the command structure*/ } SCANHEADER; typedef struct /* Command structure for GDPI scanners*/ { int result; /* Result that reports drivers */ int modes; /* Permitted scan modes */ int depth; /* Image depth in bits/pixel */ void *vmemory: /* Where image should be placed */ long vmaxlen; /* Available memory */ int bytewidth; /* Width of a line in bytes */ int height; /* Height of the image in lines */ int mmwidth; /* Width (!U)and(!u) */ int mmheight; /* Height in 1/10 millimeters */ int xdpi; /* Resolution in X (!U)and(!u) */ int ydpi; /* Y direction */ int modulo; /* 2=>image becomes word-aligned */ int start_x; /* Top left corner X in 1/10 mm */ int start_y; /* Top left corner Y in 1/10 mm */ long ser_no; /* Serial number */ /**** The following part is defined only for calls of the scanners with the commands of the 0x2XX series ******/ int add_bits; /* Specifies how many additional */ /* bits are required. For instance */ /* CRANACH Studio has 2 masks for */ /* each image. If one scans a bit- */ /* map, the program requires not */ /* just 1 bit per pixel, but three */ /* bits. In a similar way, with a */ /* greyscale picture one has to */ /* calculate 8 + 2 = 10 pixels. If */ /* this value is not allowed for, */ /* then it may happen that after */ /* scanning CRANACH Studio can not */ /* open its window, because though */ /* memory is available for the */ /* scanned image, there is none */ /* for the required masks. */ /* One needs, for exampple, two */ /* additional bits for the mask. */ void *Dchange_pointer; /* Pointer to this function */ void *Dupdate; /* Pointer to that function */ int read; /* Virtual read buffer index */ int write; /* Virtual write buffer index */ int virt_flag; /* Flag whether working with */ /* virtual memory management(1=yes)*/ } SCANCOM; SCANCOM scancom; void *Dchange_pointer( void *pointer, int v_handle, int richtung, long *max_vor, long *max_zurueck ); void Dupdate(int v_handle); All tms products work with virtual memory management. This means that it does not have to access memory areas that are present in RAM. The virtual memory management implemented in tms products was optimized for the requirements of images. General procedure: The driver passes in scancom.write a virtual handle. With this handle one can then access the virtual data. The data are obtained automatically from the hard drive when required, and stored. One possible application would be: UCHAR *real; long max_forward, max_back; scancom->vmemory points to the free virtual memory. This is to be treated just like normal memory. so, say, free memory from addr 16MB to addr 50MB with scancom->vmemory = addr 30MB. As this address does not really exist, the pointer must be mapped to the real memory and the data loaded from the hard drive. This is achieved with the function Dchange_pointer. real = (UCHAR*)Dchange_pointer( scancom->vmemory, scancom->write, FORWARD, &max_forward, &max_back ); So real now points to an area of RAM. scancom->write is the memory handle passed by the program. FORWARD tells the memory management that we want to move as far as possible to the start of the memory. This optimizes disk accesses. max_forward returns how many bytes from real one may move forward in the memory. max_back returns how many bytes from real one may move backwards in the memory. If these limits are reached then Dchange_pointer must be called anew. The minimum lengths for max_forward and max_back are: FORWARD BACK MID max_forward: 32k 0k 16k max_back: 0k 32k 16k Der Ram Speicher ist in 6 Blöcke unterteilt, von denen jeder einen he RAM memory is subdivided into 6 blocks, which each can represent a separate or also an overlapping portion of the virtual memory. To guarantee with overlapping blocks that after a memory alteration all blocks will reproduce the current memory contents, call the function Dupdate(scancom->write). This updates the other blocks. However, one only needs to use Dupdate before accessing a different block. For a scanner driver that only uses the block scancom->write, it suffices therefore to call Dupdate(scancom->write) at the end of the scanning process. Sample code for the deletion of 10 MB as of address 32 MB: v_pointer=32MB size=10MB while(size>0) { real=Dchange_pointer( v_pointer, scancom->write, FORWARD, &max_forward, &max_back); if(max_forward<=size) { memset(real,0,max_forward); size-=max_forward; v_pointer+=max_forward; } else { memset(real,0,size); size=0; v_pointer+=size; } } Dupdate(scancom->write); !!!!!!!!!!!!! **************************************************************************** Old programs call the scanner with the command 0x100 (and not 0x200). These programs (e.g. tms CRANACH) also do not yet use virtual memory management. Therefore the SCANCOM structure is not defined from the position marked onwards. The functions Dchange_pointer or Dupdate should then be replaced in the driver by dummy functions. /********************************************************************/ Possible application as ACC: /********************************************************************/ /* main() */ /* */ /* Heart of the program */ /********************************************************************/ int main( void ) { int work_in[12],work_out[58],dummy; int buffer[20]; appl_id = appl_init(); /* Open an own 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(); /* Here one waits for the call of the */ /* driver by the program; the dialog is */ /* handled, the image is scanned and */ /* the values placed in vmemory */ } } FOREVER: /* Initialization has not worked */ while(1) evnt_mesag((int*)buffer); } /********************************************************************/ /* Initialize scanner */ /********************************************************************/ void scanner_moeglichkeiten() { long **zeiger; long stack; /********** Divert pointer to GDPS *******************************/ 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.ident,"GDPS"); header.version =100; header.type =0; /* Scanner */ header.info =info; header.copyright =copyright; header.devdescr =1 | 2 | 4; /* Device description flags */ header.colours =1; /* Number of colours, 0=B/W */ header.deep =1 | 16; /* Possible bit-depths */ header.free =0; header.scommand =0; /* Command to scanner */ header.command =&command; }