home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
- ** MuFastZero **
- ** **
- ** A MMU library compatible zeropage remapper **
- ** Version 1.10 29.08.1999 © THOR-Software, by Thomas Richter **
- *****************************************************************/
-
- /// Includes
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/ports.h>
- #include <exec/execbase.h>
- #include <dos/dos.h>
- #include <mmu/mmubase.h>
- #include <mmu/context.h>
- #include <mmu/mmutags.h>
- #include <workbench/startup.h>
-
- #include <proto/exec.h>
- #include <proto/mmu.h>
- #include <proto/dos.h>
- #include <proto/icon.h>
-
- #include <string.h>
- ///
- /// Defines
- #define STRINGDATE "29.8.99"
- #define STRINGVERSION "40.10"
- #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_COPYBACK|MAPP_NONSERIALIZED|MAPP_IMPRECISE)
-
- #define TEMPLATE "ON=FASTZERO/S,OFF=NOFASTZERO/S,FASTEXEC/S,FORCENATIVE/S,MOVESSP=FASTSSP/S,STACKSIZE/K/N"
-
- #define OPT_ON 0
- #define OPT_OFF 1
- #define OPT_FASTEXEC 2
- #define OPT_FORCENATIVE 3
- #define OPT_FASTSSP 4
- #define OPT_STACKSIZE 5
- #define OPT_WINDOW 6
- #define OPT_COUNT 7
- ///
- /// Statics
- struct MMUBase *MMUBase;
- struct DosLibrary *DOSBase;
- struct ExecBase *SysBase;
- struct Library *IconBase;
-
- void *_cw_to;
- void *_cw_from;
- ULONG _cw_size;
- ///
- /// Protos
- int __asm __saveds main(void);
- int BuildFastZero(LONG fastexec);
- int RemoveFastZero(void);
- ULONG ChipLowEnd(void);
- int KillFastZero(void);
- struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
- BOOL SetPages(struct MMUContext *ctx,ULONG props,ULONG lower,ULONG size,ULONG pagesize,ULONG dest);
- void CopyMMULess(void *to,void *from,ULONG size);
- ULONG __CopyWO();
- int MoveSSP(LONG size);
- void SuperStackSwap(UBYTE *newstack,ULONG size);
- ///
- /// Strukturen
- struct FastZeroPort {
- struct MsgPort frp_Port;
- UWORD frp_cludgefill;
- void *frp_Logical; /* Logical position this is remapped to */
- void *frp_Physical; /* Physical location of the RAM used for remapping */
- ULONG frp_Lower; /* where remapping was started */
- ULONG frp_Size; /* size of the allocated memory */
- struct Library *frp_Base; /* Keep the library open */
- struct MemHeader *frp_LowMemHeader;
- ULONG frp_CacheFlags; /* Keeps the caching mode for the remapping destination */
- char frp_Name[32]; /* keeps the name of the port */
- };
-
- /* This is the port build by MuMove4k */
-
- struct MuMove4KPort {
- struct MsgPort mrp_Port;
- UWORD mrp_cludgefill;
- void *mrp_private;
- struct MemHeader *mrp_LowMemHeader;
- ULONG mrp_UpperEnd;
- };
- ///
-
- char version[]="$VER: MuFastZero " STRINGVERSION " (" STRINGDATE ") © THOR";
-
- /// main
- int __asm __saveds main(void)
- {
- LONG args[OPT_COUNT];
- struct RDArgs *rd,*myrd;
- struct Process *proc;
- int rc=20;
- LONG err;
- struct WBStartup *msg;
- BPTR oldout;
- struct MsgPort *oldconsole;
- LONG stack;
-
-
- SysBase=*((struct ExecBase **)(4L));
-
- memset(args,0,sizeof(LONG)*OPT_COUNT);
- /* Wait for the workbench startup, if any */
- proc=(struct Process *)FindTask(NULL);
-
- if (!(proc->pr_CLI)) {
- WaitPort(&(proc->pr_MsgPort));
- msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
- } else msg=NULL;
-
- if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
- if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",0L)) {
-
- myrd=NULL; /* reset the temporary ReadArgs */
- oldout=NULL;
- oldconsole=NULL;
- if (msg) {
- oldout=SelectOutput(NULL);
- oldconsole=SetConsoleTask(NULL);
- rd=ReadTTArgs(msg,args,&myrd);
- } else rd=ReadArgs(TEMPLATE,args,NULL);
-
- if (rd) {
- if (!GetMMUType()) {
- Printf("MuFastZero requires a working MMU.\n");
- err=10;
- } else {
- /* Argument parser worked, call main routine */
- err=0;
-
- if (args[OPT_FORCENATIVE])
- err=KillFastZero();
-
- if (err<10 && ((args[OPT_ON]) || ((!args[OPT_OFF]) && (!args[OPT_FASTSSP]))))
- err=BuildFastZero(args[OPT_FASTEXEC]);
-
- if (err<10 && args[OPT_OFF])
- err=RemoveFastZero();
-
- if (err<10 && args[OPT_FASTSSP]) {
- if (args[OPT_STACKSIZE]) {
- stack=*(LONG *)args[OPT_STACKSIZE];
- } else stack=0;
- err=MoveSSP(stack);
- }
- }
-
- FreeArgs(rd);
- if (myrd) FreeDosObject(DOS_RDARGS,myrd);
- if (msg) Close(SelectOutput(NULL));
- } else err=IoErr();
-
- if (msg) {
- SelectOutput(oldout);
- SetConsoleTask(oldconsole);
- }
-
- if (err<64) {
- rc=err;
- err=0;
- } else {
- if (!msg) PrintFault(err,"MuFastZero failed");
- rc=10;
- }
- SetIoErr(err);
-
- CloseLibrary((struct Library *)MMUBase);
- } else PrintFault(ERROR_OBJECT_NOT_FOUND,"MuFastZero requires the mmu.library");
- CloseLibrary((struct Library *)DOSBase);
- }
-
- return rc;
- }
- ///
- /// ReadTTArgs
- struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
- {
- struct WBArg *wbarg;
- struct DiskObject *dop;
- char **tt; /* ToolTypes array */
- char *wbstr; /* Our self-made workbench argument string */
- char *here;
- BPTR oldlock;
- ULONG len;
- struct RDArgs *rd=NULL,*myrd=NULL;
- LONG err=0;
- BPTR newout;
-
- if (IconBase=OpenLibrary("icon.library",37L)) {
- if (wbarg=msg->sm_ArgList) {
- /* use a project icon if there is one... */
- if (msg->sm_NumArgs > 1) wbarg++;
-
- /* go into the directory */
- oldlock=CurrentDir(wbarg->wa_Lock);
-
- if (dop=GetDiskObject(wbarg->wa_Name)) {
- if (tt=dop->do_ToolTypes) {
- /* Read a special tool type for the output window */
-
- /* Calc the size of the argument string */
-
- len = 3; /* reserve space for SPC,LF,NUL */
- while (*tt) {
- len += strlen(*tt)+1; /* string, plus space */
- tt++;
- }
-
- if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
- /* Now copy the arguments into this string, one by one
- and check whether the argument string is still valid. */
-
- tt=dop->do_ToolTypes;
- here=wbstr;
- do{
- *here='\0'; /* terminate string */
- /* Check whether this tool type is
- commented out. Just ignore it in this case */
- if (*tt) {
- if (**tt=='(' || **tt==';')
- continue;
-
- strcpy(here,*tt); /* Add TT string */
- }
- len=strlen(here);
- here[len]='\n';
- here[len+1]='\0'; /* terminate string */
-
- /* Now try to ReadArg' this string */
-
- /* release old arguments left over from last loop */
- if (rd) FreeArgs(rd);
- if (myrd) FreeDosObject(DOS_RDARGS,myrd);
- rd=NULL;
- memset(args,0,sizeof(LONG)*OPT_COUNT);
-
- if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
- /* Allocate and setup the ReadArgs source */
- myrd->RDA_Source.CS_Buffer=wbstr;
- myrd->RDA_Source.CS_Length=strlen(wbstr);
-
- if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
- /* Is this still valid? */
- here[len]=' ';
- here+=len+1;
- /* if so, accept this argument and go on */
- } else {
- err=IoErr();
- if (err==ERROR_NO_FREE_STORE) break;
- else err=0; /* Ignore unknown or invalid arguments silently */
- }
- } else {
- err=ERROR_NO_FREE_STORE;
- break;
- }
- }while(*tt++);
-
- FreeVec(wbstr);
- } else err=ERROR_NO_FREE_STORE;
- } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
- FreeDiskObject(dop);
- } else err=IoErr();
- CurrentDir(oldlock);
- } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
- CloseLibrary(IconBase);
- } else err=ERROR_OBJECT_NOT_FOUND; /* This should not happen */
-
- /* Open an output stream */
-
- if (err==0) {
- if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
- SelectOutput(newout);
- /* Hack in the output console. Well, well... */
- SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
- } else err=IoErr();
- }
-
- if (err) {
- if (rd) FreeArgs(rd);
- if (myrd) FreeDosObject(DOS_RDARGS,myrd);
- SetIoErr(err);
- rd=NULL;
- myrd=NULL;
- }
-
- *tmp=myrd;
- return rd;
- }
- ///
- /// SetPages
- BOOL SetPages(struct MMUContext *ctx,ULONG props,ULONG lower,ULONG size,ULONG pagesize,ULONG dest)
- {
- ULONG pages,i;
- ULONG base;
-
- pages=size/pagesize;
- base=0;
- for(i=0;i<pages;i++) {
- if (!SetPageProperties(ctx,props,~0L,lower+base,MAPTAG_DESTINATION,dest+base,TAG_DONE))
- return FALSE;
- base+=pagesize;
- }
-
- return TRUE;
- }
- ///
- /// BuildFastZero
- int BuildFastZero(LONG fastexec)
- {
- void *mem=NULL,*pmem=NULL;
- ULONG pagesize,size,psize,align;
- ULONG lower;
- struct FastZeroPort *port;
- struct MuMove4KPort *mport;
- struct MMUContext *ctx,*sctx; /* default context, supervisorcontext */
- struct MinList *ctxl,*sctxl; /* Copies of the mappings currently active */
- int err=ERROR_NO_FREE_STORE;
- ULONG props,cacheflags;
- BOOL retry;
-
-
- Forbid(); /* Shut up PatchWork */
-
- /* If this is already installed, warn and return. */
-
- if (FindPort("« MuFastZero »")) {
- Permit();
- Printf("MuFastZero already running.\n");
- return 5;
- }
-
- Permit();
-
- ctx=DefaultContext(); /* get the default context */
- sctx=SuperContext(ctx); /* get the supervisor context for this one */
-
- /* Read the size */
- pagesize=GetPageSize(ctx);
-
- if (GetPageSize(sctx)!=pagesize) {
- Printf("Supervisor and user page size are different,\n"
- "MuFastZero can't be installed.\n");
- return 10;
- }
-
- size=pagesize;
- if (size>ChipLowEnd()) {
- size=0;
- }
- align=RemapSize(ctx);
-
- if (fastexec) {
- Forbid();
- mport=(struct MuMove4KPort *)FindPort("« MuMove4K »");
- if (mport) {
- size=mport->mrp_UpperEnd;
- }
- Permit();
- if (mport==NULL) {
- Printf("MuMove4K is not installed, can't remap ExecBase.\n");
- return 10;
- }
- } else mport=NULL;
-
- if (size==0) {
- Printf("The MMU page size is too large for MuFastZero.\n");
- return 10;
- }
-
- port=AllocMem(sizeof(struct FastZeroPort),MEMF_CLEAR|MEMF_PUBLIC);
- if (port) {
-
- /* Lock the context, make sure nobody is messing with the memory */
- LockContextList(); /* We've to lock the list first, we want to lock more than one */
- LockMMUContext(ctx);
- LockMMUContext(sctx);
- err=0;
-
- /* Read the properties of the zeropage. If this is either invalid
- or already remapped, don't touch. */
-
- lower=0;
-
- do {
-
- retry=FALSE;
- props=GetPageProperties(ctx,lower,TAG_DONE);
- props|=GetPageProperties(sctx,lower,TAG_DONE);
-
- if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
- (props & MAPP_SUPERVISORONLY)) {
-
- if (fastexec && (size>pagesize)) {
- size-=pagesize;
- lower+=pagesize;
- retry=TRUE;
- } else {
- Printf("The zero page is invalidated and can't be remapped.\n");
- err=10;
- }
- }
- } while(retry);
-
- if ((props & MAPP_REMAPPED) && (err==0)) {
- Printf("The zero page is already remapped.\n");
- err=10;
- }
-
- if (err==0L) {
-
- /* We request FAST here, explicitly. Taking chip memory for the
- image doesn't make sense, this isn't fast either... */
-
- mem=AllocAligned(size+lower,MEMF_PUBLIC|MEMF_FAST|MEMF_CLEAR,align);
- if (mem) {
- psize=size+lower;
- pmem=mem;
- PhysicalLocation(ctx,&pmem,&psize);
- if (psize!=size+lower) {
- Printf("The allocated memory is fragmentated, unsupported by MuFastZero.\n");
- err=10;
- }
- } else err=ERROR_NO_FREE_STORE;
- }
-
- if (err==0L) {
-
- cacheflags=GetProperties(ctx,(ULONG)mem,TAG_DONE) & CACHEFLAGS;
-
- /* Make a copy of the software levels to be able to restore
- them later in case of an error. */
-
- if (ctxl=GetMapping(ctx)) {
- if (sctxl=GetMapping(sctx)) {
-
- /* Modify both contexts such that the zeropage is SINGLE.
- This operation is very costy, but it doesn't matter
- except for speed penalties if this is not un-done */
-
- err=ERROR_NO_FREE_STORE;
- props=MAPP_SINGLEPAGE;
-
- if (SetProperties(ctx,props,props,lower,size,TAG_DONE)) {
- if (RebuildTree(ctx)) {
- if (SetProperties(sctx,props,props,lower,size,TAG_DONE)) {
- if (RebuildTree(sctx)) {
-
- /* Copy the zeropage over */
- Disable();
-
- /* Fill in SysBase at location 4 */
- ((ULONG *)mem)[1]=(ULONG)SysBase;
- memcpy((char *)mem+lower,(char *)lower,(size_t)size);
-
- /* The new property flags, or in the cache flags */
- props=MAPP_REMAPPED|MAPP_SINGLEPAGE|cacheflags;
- CacheClearU();
-
- /* Map in the properties immediately. This should always work,
- except the parameters are invalid - which they aren't.
- This extra step is required because all other calls might
- break the Disable() above. */
- if (SetPages(ctx,props,lower,size,pagesize,(ULONG)pmem+lower)) {
- if (SetPages(sctx,props,lower,size,pagesize,(ULONG)pmem+lower)) {
-
- /* Tell the contexts to relocate the zero page even in case MuForce
- is installed later, i.e. the software emulation should read
- the data from the relocated position, not from the original. */
-
- SetMMUContextData(ctx,MCXTAG_ZEROBASE,pmem,TAG_DONE);
- SetMMUContextData(sctx,MCXTAG_ZEROBASE,pmem,TAG_DONE);
-
- /* Now make the modifications in the abstraction level. */
- if (SetProperties(ctx,props,~0L,lower,size,MAPTAG_DESTINATION,(ULONG)pmem+lower,TAG_DONE)) {
- if (SetProperties(sctx,props,~0L,lower,size,MAPTAG_DESTINATION,(ULONG)pmem+lower,TAG_DONE)) {
-
- /* The modifications in the hardware level are actually already done.
- Calling RebuildTree isn't stricly required here, but we do it
- anyways to clear the dirty flags. This might or might not fail,
- but the resulting MMU trees are always what we want. In
- case it fails, the dirty flags are set. So what... */
-
- /* The RebuildTree's are below... */
-
- /* Everything worked fine so far.... */
- port->frp_Port.mp_Node.ln_Type=NT_MSGPORT;
- port->frp_Port.mp_Node.ln_Name=port->frp_Name;
- strcpy(port->frp_Name,"« MuFastZero »");
- port->frp_Port.mp_Flags=PA_IGNORE;
- NewList(&(port->frp_Port.mp_MsgList));
-
- port->frp_Physical=pmem;
- port->frp_Logical=mem;
- port->frp_Size=size;
- port->frp_Lower=lower;
- port->frp_CacheFlags=cacheflags;
- if (mport) {
- port->frp_LowMemHeader=mport->mrp_LowMemHeader;
- port->frp_LowMemHeader->mh_Attributes=0x0000; /* remove the chip attribute */
- }
-
- port->frp_Base=OpenLibrary("mmu.library",0L);
- AddPort(&(port->frp_Port));
-
-
- /* We're done here. Fine. */
- err=0;
- mem=NULL;
- port=NULL;
-
- }
- }
-
- /* We can't set the software level. Urgh. At least, we can
- restore it how it looked like before. */
- }
- }
-
- /* We try to restore the hardware tables now. */
- if (err) {
- props=MAPP_CACHEINHIBIT|MAPP_SINGLEPAGE;
-
- if ((!SetPageProperties(ctx,props,~0L,0L,TAG_DONE)) ||
- (!SetPageProperties(sctx,props,~0L,0L,TAG_DONE))) {
- /* We can't restore the hardware tables either! */
- Alert(0xbe000101);
- /* Sorry, go guru. We can't do much more here... */
- }
- }
- Enable();
- }
- }
- }
- }
-
- /* We can't build the software level. In the one way or the other,
- just restore the previous software abstraction level. */
-
- if (err) {
- SetPropertyList(ctx,ctxl);
- SetPropertyList(sctx,sctxl);
- }
-
- /* The software level is now restored. The
- hardware level has been restored above.
- Now call RebuildTree() to clear the dirty
- flags.
- If this fails, tough luck. Both levels are
- actually fine, except for the busy flags. */
-
- RebuildTree(ctx);
- RebuildTree(sctx);
-
- ReleaseMapping(sctx,sctxl);
- }
- ReleaseMapping(ctx,ctxl);
- }
- }
-
- /* Release the locks */
- UnlockMMUContext(sctx);
- UnlockMMUContext(ctx);
- UnlockContextList();
-
- if (mem) FreeMem(mem,size+lower);
- if (port) FreeMem(port,sizeof(struct FastZeroPort));
- }
-
- return err;
- }
- ///
- /// RemoveFastZero
- int RemoveFastZero(void)
- {
- struct MMUContext *ctx,*sctx;
- struct MinList *ctxl,*sctxl;
- struct FastZeroPort *port;
- ULONG size,pagesize,lower;
- void *mem,*pmem;
- ULONG props,cacheflags;
- int err;
-
- Forbid(); /* Shut up PatchWork */
-
- /* If this is not installed, warn and return. */
-
- port=(struct FastZeroPort *)FindPort("« MuFastZero »");
-
- if (port==NULL) {
- Permit();
- Printf("MuFastZero not installed.\n");
- return 5;
- }
- /* Remove it, to ensure nobody else tries to remove it */
- RemPort(&(port->frp_Port));
- Permit();
-
- ctx=DefaultContext(); /* get the default context */
- sctx=SuperContext(ctx); /* get the supervisor context for this one */
-
- pagesize=GetPageSize(ctx);
- if (GetPageSize(sctx)!=pagesize) {
- Printf("Supervisor and user page size are different,\n"
- "MuFastZero can't be removed.\n");
- return 10;
- }
-
- LockContextList(); /* We've to lock the list first, we want to lock more than one */
- LockMMUContext(ctx);
- LockMMUContext(sctx);
-
- err=ERROR_NO_FREE_STORE;
-
- /* Make a copy of the mapping like it is now */
- if (ctxl=GetMapping(ctx)) {
- if (sctxl=GetMapping(sctx)) {
-
- /* Read the properties of the zeropage. If this is either invalid
- or already remapped, don't touch. */
-
- lower=port->frp_Lower;
- props=GetPageProperties(ctx,lower,TAG_DONE);
- props|=GetPageProperties(sctx,lower,TAG_DONE);
- err=0;
-
- if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
- (props & MAPP_SUPERVISORONLY)) {
- Printf("The zero page is now invalidated and can't be restored for that reason.\n");
- err=10;
- }
-
- if ((err==0) && ((props & MAPP_REMAPPED)==0)) {
- Printf("The zero page is no longer remapped to FastMem.\n");
- err=10;
- }
-
- /* If everything is fine so far, start removing things */
- if (err==0) {
- size=port->frp_Size;
- pmem=port->frp_Physical;
- mem=port->frp_Logical;
- lower=port->frp_Lower;
- cacheflags=port->frp_CacheFlags;
- Disable();
-
- err=ERROR_NO_FREE_STORE;
- props=MAPP_CACHEINHIBIT|MAPP_SINGLEPAGE; /* This is the only flag for chip memory */
-
- /* Now copy the data back to the zeropage */
- CopyMMULess((char *)lower,(char *)pmem+lower,size);
-
- /* First, try to modify the hardware tables. */
- if (SetPages(ctx,props,lower,size,pagesize,lower)) {
- if (SetPages(sctx,props,lower,size,pagesize,lower)) {
-
- /* read the data again from the real stuff */
- SetMMUContextData(ctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
- SetMMUContextData(sctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
-
- /* Restore the software level,singlepage is no longer required */
-
- props=MAPP_CACHEINHIBIT;
- if (SetProperties(ctx,props,~0L,lower,size,TAG_DONE)) {
- if (SetProperties(sctx,props,~0L,lower,size,TAG_DONE)) {
-
- if (port->frp_LowMemHeader) {
- /* No, neither public nor anything else */
- port->frp_LowMemHeader->mh_Attributes=MEMF_CHIP;
- }
-
- FreeMem(mem,size+lower);
- if (port->frp_Base)
- CloseLibrary(port->frp_Base);
-
- FreeMem(port,sizeof(struct FastZeroPort));
- err=0;
- }
- }
-
- /* We can't setup the software level. Urgh. At least,
- we should try to set things back how they used to be. */
- }
- }
-
-
- /* We try to restore the hardware tables now. */
- if (err) {
- props=MAPP_REMAPPED|MAPP_SINGLEPAGE|cacheflags;
- SetMMUContextData(ctx,MCXTAG_ZEROBASE,(ULONG)pmem+lower,TAG_DONE);
- SetMMUContextData(sctx,MCXTAG_ZEROBASE,(ULONG)pmem+lower,TAG_DONE);
-
- if ((!SetPages(ctx,props,lower,size,pagesize,(ULONG)pmem+lower)) ||
- (!SetPages(sctx,props,lower,size,pagesize,(ULONG)pmem+lower))) {
- /* We can't restore the hardware tables either! */
- Alert(0xbe000101);
- /* Sorry, go guru. We can't do much more here... */
- }
- }
- Enable();
-
- if (err) {
- SetPropertyList(ctx,ctxl);
- SetPropertyList(sctx,sctxl);
- /* More luck next time */
- AddPort(&(port->frp_Port));
- }
-
- /* The software level is now restored. The
- hardware level has been restored above.
- Now call RebuildTree() to clear the dirty
- flags.
- If this fails, tough luck. Both levels are
- actually fine, except for the busy flags. */
-
- RebuildTree(ctx);
- RebuildTree(sctx);
- }
- ReleaseMapping(sctx,sctxl);
- }
- ReleaseMapping(ctx,ctxl);
- }
-
-
- UnlockMMUContext(sctx);
- UnlockMMUContext(ctx);
- UnlockContextList(); /* We've to lock the list first, we want to lock more than one */
-
- if (err) {
- /* Uhoh, things didn't work here... */
- Printf("Can't remove the FastZero node, sorry.\n");
- }
-
- return err;
- }
- ///
- /// KillFastZero
- int KillFastZero(void)
- {
- struct FastZeroPort *port;
- struct MMUContext *ctx,*sctx; /* default context, supervisorcontext */
- struct MinList *ctxl,*sctxl; /* Copies of the mappings currently active */
- ULONG pagesize;
- ULONG lower,size,props;
- ULONG userpos,superpos,base;
- int err;
- BOOL retry;
-
-
- Forbid(); /* Shut up PatchWork */
-
- /* If MuFastZero is installed, remove it the easy way */
-
- port=(struct FastZeroPort *)FindPort("« MuFastZero »");
-
- if (port) {
- Permit();
- return RemoveFastZero();
- }
-
- Permit();
-
- ctx=DefaultContext(); /* get the default context */
- sctx=SuperContext(ctx); /* get the supervisor context for this one */
-
- /* Read the size */
- pagesize=GetPageSize(ctx);
-
- if (GetPageSize(sctx)!=pagesize) {
- Printf("Supervisor and user page size are different,\n"
- "MuFastZero failed.\n");
- return 10;
- }
-
- /* Lock the context, make sure nobody is messing with the memory */
- LockContextList(); /* We've to lock the list first, we want to lock more than one */
- LockMMUContext(ctx);
- LockMMUContext(sctx);
- err=0;
-
- /* Read the properties of the zeropage. If this is either invalid
- or not remapped, don't touch. */
-
- lower=0;
- size=0;
- base=0;
-
- do {
-
- retry=FALSE;
- userpos=superpos=0;
- props=GetPageProperties(ctx,lower+size,
- MAPTAG_DESTINATION,&userpos,
- TAG_DONE);
- props|=GetPageProperties(sctx,lower+size,
- MAPTAG_DESTINATION,&superpos,
- TAG_DONE);
-
- if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
- (props & MAPP_SUPERVISORONLY)) {
-
- lower += pagesize;
- retry = TRUE;
-
- } else if (props & MAPP_REMAPPED) {
- if (userpos == superpos) {
-
- if (base==0) {
- base = userpos;
- }
- /* Adjacent? */
- if (base+size == userpos) {
- size += pagesize;
- retry = TRUE;
- }
- }
- }
-
- } while(retry);
-
- if (size==0L) {
- Printf("The zero page is not remapped.\n");
- err = 5;
- }
-
- /* lower is now the lower end which is remapped.
- size is the length of the remapped memory
- base is the address it is remapped to */
-
- if (err==0L) {
-
- /* Make a copy of the software levels to be able to restore
- them later in case of an error. */
-
- if (ctxl=GetMapping(ctx)) {
- if (sctxl=GetMapping(sctx)) {
-
- /* Modify both contexts such that the zeropage is SINGLE.
- This operation is very costy, but it doesn't matter
- except for speed penalties if this is not un-done */
-
- err=ERROR_NO_FREE_STORE;
- props=MAPP_SINGLEPAGE;
-
- if (SetProperties(ctx,props,props,lower,size,TAG_DONE)) {
- if (RebuildTree(ctx)) {
- if (SetProperties(sctx,props,props,lower,size,TAG_DONE)) {
- if (RebuildTree(sctx)) {
-
- Disable();
-
- /* The new property flags */
- props=MAPP_SINGLEPAGE|MAPP_CACHEINHIBIT;
- CacheClearU();
- CopyMMULess((void *)lower,(void *)base,size);
-
- /* Map in the properties immediately. This should always work,
- except the parameters are invalid - which they aren't.
- This extra step is required because all other calls might
- break the Disable() above. */
-
- if (SetPages(ctx,props,lower,size,pagesize,0L)) {
- if (SetPages(sctx,props,lower,size,pagesize,0L)) {
-
- /* Tell the contexts not to relocate the zero page even in case MuForce
- is installed later, i.e. the software emulation should read
- the data from the relocated position, not from the original. */
-
- SetMMUContextData(ctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
- SetMMUContextData(sctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
-
- /* Now make the modifications in the abstraction level. */
- if (SetProperties(ctx,props,~0L,lower,size,TAG_DONE)) {
- if (SetProperties(sctx,props,~0L,lower,size,TAG_DONE)) {
-
- /* The modifications in the hardware level are actually already done.
- Calling RebuildTree isn't stricly required here, but we do it
- anyways to clear the dirty flags. This might or might not fail,
- but the resulting MMU trees are always what we want. In
- case it fails, the dirty flags are set. So what... */
-
- /* We're done here. Fine. */
- err=0;
- }
- }
- /* We can't set the software level. Urgh. At least, we can
- restore it how it looked like before. */
- }
- } /* of if SetPages */
-
- /* We try to restore the hardware tables now. */
- if (err) {
- props=MAPP_REMAPPED|MAPP_SINGLEPAGE|MAPP_COPYBACK;
- SetMMUContextData(ctx,MCXTAG_ZEROBASE,base,TAG_DONE);
- SetMMUContextData(sctx,MCXTAG_ZEROBASE,base,TAG_DONE);
-
- if ((!SetPages(ctx,props,lower,size,pagesize,base)) ||
- (!SetPages(sctx,props,lower,size,pagesize,base))) {
- /* We can't restore the hardware tables either! */
- Alert(0xbe000101);
- /* Sorry, go guru. We can't do much more here... */
- }
- }
-
- Enable();
- }
- }
- }
- } /* of if SetProperties() */
-
- /* We can't build the software level. In the one way or the other,
- just restore the previous software abstraction level. */
-
- if (err) {
- SetPropertyList(ctx,ctxl);
- SetPropertyList(sctx,sctxl);
- }
-
- /* The software level is now restored. The
- hardware level has been restored above.
- Now call RebuildTree() to clear the dirty
- flags.
- If this fails, tough luck. Both levels are
- actually fine, except for the busy flags. */
-
- RebuildTree(ctx);
- RebuildTree(sctx);
-
- ReleaseMapping(sctx,sctxl);
- } /* of if made copy */
- ReleaseMapping(ctx,ctxl);
- } /* of if made copy */
- } /* of if (err==0) */
-
- /* Release the locks */
- UnlockMMUContext(sctx);
- UnlockMMUContext(ctx);
- UnlockContextList();
-
- return err;
- }
- ///
- /// ChipLowEnd
- ULONG ChipLowEnd(void)
- {
- ULONG low;
- struct MemHeader *head;
-
- low=0x00200000; /* This is definitely the upper end of chip mem */
-
- Forbid();
- for(head=(struct MemHeader *)SysBase->MemList.lh_Head;
- head->mh_Node.ln_Succ;
- head=(struct MemHeader *)(head->mh_Node.ln_Succ)) {
- if (head->mh_Attributes & MEMF_CHIP) {
- if ((ULONG)(head->mh_Lower)<low) {
- low=(ULONG)(head->mh_Lower);
- }
- }
- }
- Permit();
-
- return low;
- }
- ///
- /// MoveSSP
- int MoveSSP(LONG stacksize)
- {
- ULONG minsize;
- struct Task *task;
- UBYTE *newstack;
-
- minsize=(UBYTE *)SysBase->SysStkUpper-(UBYTE *)SysBase->SysStkLower;
- if (stacksize<minsize) {
- task=FindTask(NULL);
- stacksize=(UBYTE *)(task->tc_SPUpper)-(UBYTE *)(task->tc_SPLower);
- }
- if (stacksize<minsize)
- stacksize=minsize;
-
- /* Round this to two cache lines */
-
- stacksize += 0x1f;
- stacksize &= ~0x1f;
-
- /* This must be fast, or this function is a joke... */
- newstack=AllocMem(stacksize,MEMF_CLEAR|MEMF_PUBLIC|MEMF_FAST);
-
- if (newstack==NULL) {
- return ERROR_NO_FREE_STORE;
- }
-
- SuperStackSwap(newstack,stacksize);
-
- return 0;
- }
- ///
- /// SuperStackSwap
- void SuperStackSwap(UBYTE *newstack,ULONG size)
- {
- UBYTE *oldsp,*newsp;
- size_t oldsize;
- UWORD sum;
- UWORD *p;
-
- /* Yup, this is possible in C */
- Disable();
- oldsp=SuperState();
-
- /* copy the stack over to the upper limit */
- oldsize=(UBYTE *)(SysBase->SysStkUpper)-oldsp;
- if (oldsize>0 && oldsize<size) {
- newsp=newstack+size-oldsize;
- memcpy(newsp,oldsp,oldsize);
- } else newsp=newstack+size;
- UserState(newsp);
-
- /* Now tell this exec! */
- SysBase->SysStkUpper=newstack+size;
- SysBase->SysStkLower=newstack;
-
- /* Recalculate the checksum */
- p=&SysBase->SoftVer;
- sum=0xffff;
- while(p<&SysBase->ChkSum)
- sum -= *p++;
-
- SysBase->ChkSum=sum;
- Enable();
-
- }
- ///
- /// CopyMMULess
- void CopyMMULess(void *to,void *from,ULONG size)
- {
- _cw_from=from;
- _cw_to=to;
- _cw_size=size;
- WithoutMMU(&__CopyWO);
- }
- ///
- /// CopyWO
- ULONG __CopyWO()
- {
- memcpy(_cw_to,_cw_from,(size_t)_cw_size);
- CacheClearU();
- return 0;
- }
- ///
-
-
-
-
-