/********************************************************* ** IndirectTest ** ** ** ** Test indirect page descriptors of the MuLib ** ** Release 1.01 ** ** ** ** © 19.03.2000 Thomas Richter ** *********************************************************/ /// Includes #include #include #include #include #include #include #include #include #include #include /// /// Defines /// /// Protos int __saveds main(void); int RunTests(void); void DumpData(UBYTE *src,ULONG size); /// /// Statics char version[]="$VER: IndirectTest 1.01 (19.03.2000) © THOR"; struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct MMUBase *MMUBase; /// ///main int __saveds main(void) { int rc=25; /* ** Since we want to link without startup code, ** we need to open the system libraries here... */ SysBase = *((struct ExecBase **)(4L)); /* ** Open DOS and MMU **/ if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37L)) { if (MMUBase = (struct MMUBase *)OpenLibrary("mmu.library",42L)) { rc = RunTests(); CloseLibrary((struct Library *)MMUBase); } else { Printf("IndirectTest failed: This program requires the mmu.library V42 or better.\n"); rc = 10; } /* ** Everything above 64 is a system ** error code we print over the console. */ if (rc>64) { PrintFault((LONG)rc,"IndirectTest failed"); rc = 10; } CloseLibrary((struct Library *)DOSBase); } return rc; } /// /// RunTests int RunTests(void) { struct MMUContext *ctx; struct MinList *ctxl; ULONG pagesize; ULONG *descriptor,*descriptorp; ULONG values[2]; ULONG props[2]; UBYTE *page,*pagep[2]; int rc=25; /* ** Get the context we're currently using ** and its page size ** furthermore, allocate a page. */ ctx = CurrentContext(NULL); pagesize = GetPageSize(ctx); page = AllocAligned(pagesize*2,MEMF_PUBLIC|MEMF_CLEAR,pagesize); if (page) { /* ** Now allocate memory for the descriptor ** this must be long-word aligned, hence ** an AllocMem is fine here. ** However, we need to know the physical location ** of the descriptor. */ descriptor = AllocMem(sizeof(ULONG),MEMF_PUBLIC); if (descriptor) { /* ** Compute physical locations ** We do not assume that PhysicalLocation() ** truncates the address. All values are ** long/page aligned longs/pages, hence never cross a ** page boundary. */ descriptorp = descriptor; PhysicalLocation(ctx,(void **)&descriptorp,&pagesize); /* And now for the pages */ pagep[0] = page; props[0] = PhysicalLocation(ctx,(void **)&pagep[0],&pagesize); pagep[1] = page+pagesize; props[1] = PhysicalLocation(ctx,(void **)&pagep[1],&pagesize); if (pagep[0] && pagep[1] && descriptorp) { /* ** Lock the context and make a backup of it. ** */ LockMMUContext(ctx); if (ctxl=GetMapping(ctx)) { /* ** Pre-calculate the values for the descriptors. ** The first descriptor maps the page to its TRUE physical ** location, the second one to the ROM, writeprotecting ** it. ** Note that we need to use the physical addresses here. ** ** MAPP_ROM protection must be archived by setting this ** property bit "one level up". ** ** We furthermore set USED and MODIFIED to avoid unnecessary ** MMU writebacks, and transfer the old properties back ** into the descriptor properties ** ** Note that this call returns BAD_DESCRIPTOR in case ** of an error, not NULL. */ values[0] = BuildIndirect(ctx,(ULONG)(pagep[0]),props[0]|MAPP_USED|MAPP_MODIFIED); values[1] = BuildIndirect(ctx,(ULONG)(pagep[1]),props[1]|MAPP_USED|MAPP_WRITEPROTECTED); if ((values[0] != BAD_DESCRIPTOR) && (values[1] != BAD_DESCRIPTOR)) { /* ** Install the descriptor ** The first parameter is the physical address ** of the descriptor, the second the ** logical address of the page ** and the last the descriptor to install */ SetIndirect(descriptorp,(ULONG)page,values[0]); /* ** Now install this descriptor ** We set this to MAPP_ROM because we want emulated ** ROM writeprotection. ** This is ignored if the descriptor itself is ** not write protected anyhow. ** We need the physical location of the descriptor ** here. */ if (SetProperties(ctx,MAPP_ROM|MAPP_INDIRECT,MAPP_ROM|MAPP_INDIRECT, (ULONG)page,pagesize, MAPTAG_DESCRIPTOR,descriptorp, TAG_DONE)) { if (RebuildTree(ctx)) { /* Everything's fine. ** copy some dummy data into the page */ memset(page,'*',(size_t)pagesize); /* now print parts of it */ DumpData(page,0x10); /* ** install the other descriptor */ SetIndirect(descriptorp,(ULONG)page,values[1]); /* ** Dump it again. Should be all zero now. */ DumpData(page,0x10); /* Try to write to it. This should ** fail quietly. */ *page = 'A'; /* And dump it again */ DumpData(page,0x10); /* ** install the old descriptor ** again */ SetIndirect(descriptorp,(ULONG)page,values[0]); /* ** Now reset the context data. ** Disable the MAPP_ROM and MAPP_INDIRECT ** features. This call shouldn't fail or ** we are in trouble */ if (SetProperties(ctx,0,MAPP_ROM|MAPP_INDIRECT, (ULONG)page,pagesize,TAG_DONE)) { /* Restore the former MMU tree */ if (RebuildTree(ctx)) { /* ** everything is fine now. */ rc = 0; } } if (rc) { /* ** We're now in trouble. ** The old context couldn't be restored. ** Therefore, we do not release the descriptors ** such that the accesses are at least right, ** and restore the high-level by SetPropertyList() ** below. This will cause a mild memory leak, ** but the system will be fine. */ Printf("IndirectTest: Can't restore the context.\n"); descriptor = NULL; } } else Printf("IndirectTest: Building the context failed.\n"); } else Printf("IndirectTest: Can't install the new descriptor.\n"); /* ** In case of an error, we restore now the high ** level of the context. ** This is all we could do. ** The high-level looks then fine again, ** and the low level contains either an ** indirect descriptor which we can't get ** rid of, but which maps ok, or is ** unchanged. The system will be fine ** in both cases. */ if (rc) { SetPropertyList(ctx,ctxl); } } else Printf("Can't build the new descriptors.\n"); /* Release the mapping */ ReleaseMapping(ctx,ctxl); } else rc = ERROR_NO_FREE_STORE; /* ** Release the MMU Context lock */ UnlockMMUContext(ctx); } else Printf("IndirectTest: Can't perform the logical to physical translation.\n"); /* ** now release the descriptor */ if (descriptor) { FreeMem(descriptor,sizeof(ULONG)); } } else rc = ERROR_NO_FREE_STORE; /* of if descriptor */ FreeMem(page,pagesize*2); } else rc = ERROR_NO_FREE_STORE; /* of if page */ return rc; } /// /// DumpData void DumpData(UBYTE *src,ULONG size) { /* ** A pretty dumb memory dump */ Printf("Memory contents at 0x%08lx : ",src); while(size) { Printf("%02lx ",*src); src++; size--; } Printf("\n"); } ///