by Michael Sinz (MKSoft Development) Copyright 1992-2001 - All Rights Reserved MMU.c |
by Michael Sinz MKSoft Development Copyright 1992-2001 All Rights Reserved Documentation Enforcer Archive Source code for the main Enforcer tool: Source code for the MMU tool: Source code for SegTracker: Source code for FindHit: Source code for RebootOff: Source code for Move4K: Source code for LawBreaker: | /* * Enforcer by * Michael Sinz * * Copyright 1992-2001 * All Rights Reserved * ***************************************************************************** * * * Permission is hereby granted to distribute the Enforcer archive * * containing the executables and documentation for non-commercial purposes * * so long as the archive and its contents are not modified in any way. * * * * Enforcer and related tools are not in the public domain. * * * * Enforcer and related tools may not be distributed for a profit. * * * ***************************************************************************** * ******* MMU ******************************************************************* * * NAME * MMU - A 68040/68060 MMU Mapping Tool * * SYNOPSIS * MMU is a tool for 68040/060 systems to display and/or change the MMU * configuration contained within. MMU will display the tables as * compressed as possible, noting address ranges that are mapped the * same and only displaying one line for the whole range. * * INPUTS * ADDRESS/K - Hex address to display (if not given, all) * SIZE/K - Hex address size of address range * READWRITE - Change address range to ReadWrite * READONLY - Change address range to ReadOnly * VALID - Change address range to VALID * INVALID - Change address range to INVALID * CACHE - Change address range to CACHE enable * NOCACHE - Change address range to CACHE disable * COPYBACK - Change address range to non-serialized * NOCOPYBACK - Change address range to serialized * GLOBAL - Change address range to GLOBAL * LOCAL - Change address range to LOCAL * SUPERVISOR - Change address range to SUPERVISOR-only * USER - Change address range to USER access * VERBOSE - Show the changes as they are made * NOSHOW - Do not show the whole table * * RESULTS * On my A3000 with a 68040 installed and Enforcer running, the * MMU output looks as follows: (No options) * *Current 68040 MMU table setup: *$00000000-$00000FFF->$00000000: Local, User, Invalid, Read-Only, Serialized *$00001000-$001FFFFF->$00001000: Global, User, Valid, Read/Write, Serialized *$00200000-$00BBFFFF->$07542000: Local, User, Invalid, Read-Only, Serialized *$00BC0000-$00BFFFFF->$00BC0000: Global, User, Valid, Read/Write, Serialized *$00C00000-$00D7FFFF->$07542000: Local, User, Invalid, Read-Only, Serialized *$00D80000-$00DFFFFF->$00D80000: Global, User, Valid, Read/Write, Serialized *$00E00000-$00E8FFFF->$07542000: Local, User, Invalid, Read-Only, Serialized *$00E90000-$00EAFFFF->$00E90000: Global, User, Valid, Read/Write, Serialized *$00EB0000-$00EFFFFF->$07542000: Local, User, Invalid, Read-Only, Serialized *$00F00000-$00FFFFFF->$00F00000: Global, User, Valid, Read-Only, Copyback *$01000000-$073FFFFF->$07542000: Local, User, Invalid, Read-Only, Serialized *$07400000-$07F7FFFF->$07400000: Global, User, Valid, Read/Write, Copyback *$07F80000-$FFFFFFFF->$07542000: Local, User, Invalid, Read-Only, Serialized * * WARNING * This tool is a hack and does not have any safeguards on the options. * Use at your own risk. * * SEE ALSO * "A master's secrets are only as good as the * master's ability to explain them to others." - Michael Sinz * * BUGS * None? * ******************************************************************************* */ #include <exec/types.h> #include <exec/execbase.h> #include <exec/tasks.h> #include <exec/memory.h> #include <exec/alerts.h> #include <exec/ports.h> #include <exec/libraries.h> #include <exec/semaphores.h> #include <dos/dos.h> #include <dos/dosextens.h> #include <dos/rdargs.h> #include <devices/timer.h> #include <workbench/startup.h> #include <workbench/workbench.h> #include <libraries/configvars.h> #include <clib/exec_protos.h> #include <pragmas/exec_pragmas.h> #include <clib/dos_protos.h> #include <pragmas/dos_pragmas.h> #include <clib/icon_protos.h> #include <pragmas/icon_pragmas.h> #include <clib/expansion_protos.h> #include <pragmas/expansion_pragmas.h> #include <strings.h> #define EXECBASE (*(struct ExecBase **)4) #define TEMPLATE "ADDRESS/K,SIZE/K,READWRITE/S,READONLY/S,VALID/S,INVALID/S,CACHE/S,NOCACHE/S,COPYBACK/S,NOCOPYBACK/S,GLOBAL/S,LOCAL/S,SUPERVISOR/S,USER/S,VERBOSE/S,NOSHOW/S" #define OPT_ADDRESS 0 #define OPT_SIZE 1 #define OPT_READWRITE 2 #define OPT_READONLY 3 #define OPT_VALID 4 #define OPT_INVALID 5 #define OPT_CACHE 6 #define OPT_NOCACHE 7 #define OPT_COPYBACK 8 #define OPT_NOCOPYBACK 9 #define OPT_GLOBAL 10 #define OPT_LOCAL 11 #define OPT_SUPERVISOR 12 #define OPT_USER 13 #define OPT_VERBOSE 14 #define OPT_NOSHOW 15 #define OPT_COUNT 16 ULONG __asm GetPageEntry(register __a6 struct ExecBase *,register __a0 ULONG); void __asm SetPageEntry(register __a6 struct ExecBase *,register __d0 ULONG,register __d1 ULONG); ULONG toLong(char *); void DisplayPage(struct Library *,ULONG); #define PAGE_SIZE 0x00001000L #define PAGE_MASK 0xFFFFF000L /* Important type bits... */ #define TYPE_BITS 0x000004E7L ULONG cmd(void) { struct ExecBase *SysBase; struct Library *DOSBase; struct Process *proc; struct RDArgs *rdargs=NULL; struct WBStartup *msg=NULL; struct RDArgs *myRDArgs=NULL; ULONG rc=RETURN_FAIL; LONG opts[OPT_COUNT]; SysBase = EXECBASE; proc=(struct Process *)FindTask(NULL); if (!(proc->pr_CLI)) { WaitPort(&(proc->pr_MsgPort)); msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort)); } if (DOSBase = OpenLibrary("dos.library",37)) { struct Library *Lib68040; struct Library *Lib68060; memset((char *)opts, 0, sizeof(opts)); /* Open 68060... If it fails, try 68040... */ Lib68060=OpenLibrary("68060.library",0); Lib68040=(Lib68060 ? NULL : OpenLibrary("68040.library",0)); /* * Do the option parsing * If from Workbench, use icon tool types * If from CLI, use ReadArgs */ if (msg) { struct Library *IconBase; struct WBArg *wbArg; /* * Started from Workbench so do icon magic... * * What we will do here is try all of the tooltypes * in the icon and keep only those which do not cause * errors in the RDArgs. */ if (wbArg=msg->sm_ArgList) if (IconBase=OpenLibrary("icon.library",0)) { struct DiskObject *diskObj; BPTR tmplock; /* * Use project icon if it is there... */ if (msg->sm_NumArgs > 1) wbArg++; tmplock=CurrentDir(wbArg->wa_Lock); if (diskObj=GetDiskObject(wbArg->wa_Name)) { char **ToolTypes; if (ToolTypes=diskObj->do_ToolTypes) { char *TotalString; ULONG totalSize=3; while (*ToolTypes) { totalSize+=strlen(*ToolTypes)+1; ToolTypes++; } if (TotalString=AllocVec(totalSize,MEMF_PUBLIC)) { char *CurrentPos=TotalString; ULONG currentLength; ToolTypes=diskObj->do_ToolTypes; do { *CurrentPos='\0'; if (*ToolTypes) strcpy(CurrentPos,*ToolTypes); currentLength=strlen(CurrentPos); CurrentPos[currentLength+0]='\n'; CurrentPos[currentLength+1]='\0'; if (rdargs) FreeArgs(rdargs); rdargs=NULL; memset((char *)opts, 0, sizeof(opts)); if (myRDArgs) FreeDosObject(DOS_RDARGS,myRDArgs); if (myRDArgs=AllocDosObject(DOS_RDARGS,NULL)) { myRDArgs->RDA_Source.CS_Buffer=TotalString; myRDArgs->RDA_Source.CS_Length=strlen(TotalString); if (rdargs=ReadArgs(TEMPLATE, opts, myRDArgs)) { CurrentPos[currentLength]=' '; CurrentPos+=currentLength+1; } } } while (*ToolTypes++); FreeVec(TotalString); } } FreeDiskObject(diskObj); } CurrentDir(tmplock); CloseLibrary(IconBase); } rc=RETURN_OK; } else { /* * Started from CLI so do standard ReadArgs */ if (!(rdargs = ReadArgs(TEMPLATE, opts, NULL))) PrintFault(IoErr(),NULL); else if (SetSignal(0,0) & SIGBREAKF_CTRL_C) PrintFault(ERROR_BREAK,NULL); else rc=RETURN_OK; } if (RETURN_OK==rc) if (Lib68040 || Lib68060) { if (GetPageEntry(SysBase,~0)) { /* * Do the stuff here... */ if (opts[OPT_ADDRESS]) { ULONG Address; Address=toLong((char *)opts[OPT_ADDRESS]); if (opts[OPT_SIZE]) { ULONG Size; ULONG Page; Size=toLong((char *)opts[OPT_SIZE]); Size += Address; Address &= PAGE_MASK; Forbid(); while (Address < Size) { Page=GetPageEntry(SysBase,Address); if (opts[OPT_READWRITE]) Page &= ~0x00000004; if (opts[OPT_READONLY]) Page |= 0x00000004; if (opts[OPT_VALID]) Page = (Page & ~0x00000003) | 0x00000001; if (opts[OPT_INVALID]) Page = (Page & ~0x00000003) | 0x00000000; if (opts[OPT_CACHE]) Page &= ~0x00000040; if (opts[OPT_NOCACHE]) Page |= 0x00000040; if (opts[OPT_COPYBACK]) Page |= 0x00000020; if (opts[OPT_NOCOPYBACK]) Page &= ~0x00000020; if (opts[OPT_GLOBAL]) Page |= 0x00000400; if (opts[OPT_LOCAL]) Page &= ~0x00000400; if (opts[OPT_SUPERVISOR]) Page |= 0x00000080; if (opts[OPT_USER]) Page &= ~0x00000080; SetPageEntry(SysBase,Address,Page); if (opts[OPT_VERBOSE]) if (!msg) { ULONG tmp[2]; tmp[0]=Address; tmp[1]=Page & PAGE_MASK; VPrintf("Entry for $%08lx -> $%08lx: ",(LONG *)tmp); DisplayPage(DOSBase,Page); } Address+=PAGE_SIZE; if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C) { PrintFault(ERROR_BREAK,NULL); Size=0; } } Permit(); } } if (!opts[OPT_NOSHOW]) if (!msg) { ULONG LastPage; ULONG LastAddr=NULL; ULONG Page; ULONG Addr; ULONG flag; ULONG range=0xFFFFFFFFL; if (Lib68040) PutStr("\nCurrent 68040 MMU table setup:\n"); if (Lib68060) PutStr("\nCurrent 68060 MMU table setup:\n"); if (opts[OPT_ADDRESS]) LastAddr=toLong((char *)opts[OPT_ADDRESS]) & PAGE_MASK; if (opts[OPT_SIZE]) range=toLong((char *)opts[OPT_SIZE]); LastPage=GetPageEntry(SysBase,LastAddr); Addr=LastAddr+PAGE_SIZE; while (range) { Page=GetPageEntry(SysBase,Addr); flag=FALSE; if (range<=PAGE_SIZE) flag=TRUE; else if ((Page & TYPE_BITS) != (LastPage & TYPE_BITS)) flag=TRUE; else if ((Page & PAGE_MASK) != (LastPage & PAGE_MASK)) { if (((Page & PAGE_MASK) - (LastPage & PAGE_MASK)) != (Addr - LastAddr)) flag=TRUE; } if (flag) { ULONG tmp[3]; tmp[0]=LastAddr; tmp[1]=0xFFFFFFFFL; if (Addr+PAGE_SIZE) tmp[1]=Addr-1; tmp[2]=LastPage & PAGE_MASK; VPrintf("$%08lx-$%08lx -> $%08lx: ",(LONG *)tmp); DisplayPage(DOSBase,LastPage); LastPage=Page; LastAddr=Addr; } Addr+=PAGE_SIZE; if (range>PAGE_SIZE) range-=PAGE_SIZE; else range=0; if (SetSignal(0L,0L) & SIGBREAKF_CTRL_C) { PrintFault(ERROR_BREAK,NULL); Addr=0; range=0; } } } } else if (!msg) PutStr("Requires 68040 or 68060 with active 4K MMU\n"); } else if (!msg) PutStr("Requires a 68040 and 68040.library\n or a 68060 and 68060.library\n"); if (rdargs) FreeArgs(rdargs); if (myRDArgs) FreeDosObject(DOS_RDARGS,myRDArgs); CloseLibrary(Lib68060); CloseLibrary(Lib68040); CloseLibrary(DOSBase); } else { if (!msg) if (DOSBase=OpenLibrary("dos.library",0)) { Write(Output(),"Requires Kickstart 2.04 (37.175) or later.\n",43); CloseLibrary(DOSBase); } } if (msg) { Forbid(); ReplyMsg((struct Message *)msg); } return(0); } void DisplayPage(struct Library *DOSBase,ULONG Page) { if (Page & 0x400) PutStr("Global, "); else PutStr(" Local, "); if (Page & 0x80) PutStr("Super, "); else PutStr("User, "); if (Page & 1) PutStr(" Valid, "); else PutStr("Invalid, "); if (Page & 0x04) PutStr("Read-Only, "); else PutStr("Read/Write, "); switch (Page & 0x60) { case 0x00: PutStr(" Cache"); break; case 0x20: PutStr(" Copyback"); break; case 0x40: PutStr("Serialized"); break; case 0x60: PutStr(" Nocache"); break; } PutStr("\n"); } ULONG toLong(char *hex) { ULONG val=0; ULONG c; if (*hex=='$') hex++; /* Support $hex */ while (*hex) { c=(ULONG)*hex; if ((c>='a') && (c<='f')) c-=32; c-='0'; if (c>9) { c-=7; if (c<10) c=16; } if (c<16) { val=(val << 4) + c; hex++; } else val=0; } return(val); } | ||