; ; File: HwPriv.a ; ; Contains: This file holds the implementation of the HwPriv trap. ; ; Copyright: © 1987-1994 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 2/7/94 chp Extensive housecleaning in the HwPriv implementations, including ; the elimination of separate RISC and 68K dispatch tables. ; 12/23/93 PN Take out overpatches on LockMemoryproc, LockMemoryContigousProc ; and also take out IsUniversal conditionals. ; 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ ; machines. ; 11/9/93 KW added some eieioSTP macros. Only expands for CygnusX1 ROM ; 10/14/93 pdw . ; 10/11/93 CCH Separated Edisk protect routine into one for PowerPC and one for ; 68k. ; 10/10/93 CCH Turned on EDisk support for PowerPC machines. ; 9/13/93 SAM Replaced the alternate dispatch table that was inadvertently ; removed in the last rev. ; 9/1/93 chp DMADispatch is no more. This eliminates the _DMAIntInstall and ; frees up selector 11. All clients have been modified to use more ; efficient inline code instead. ; 8/19/93 chp Fix the dispatcher so it wonÕt barf on a selector of 13. (BHI -> ; BHS) ; 8/4/93 GMR Added code to SlotBlockXferCtl to support block transfers ; for BART machines (PDM,CF). ; 6/14/93 SAM Reenabled the "DMADispatch" selector for PDM. ; 6/14/93 kc Roll in Ludwig. ; 3/24/93 mal Added SlotBlockXferCtl to rom build. For system builds, updated ; LastVec, changed dispatch to BHS, and added cacheflushes to the ; self-modifying code. ; 4/22/93 CSS Changed emDMADispGlobs to emDMADispatchGlobals which matches ; Reality. ; 4/8/93 KW (LW7 KW) fixing Radar bug #1073805 and Radar bug #1075450. If ; RAM disk was on and using up lots of memory, Finder duplication ; would hang the System. MacWrite Pro would not install very well ; either. Routine chkContig was not initializing local var ; physAddr before use. Also calls to GetRealProc would trash A2 ; which was holding a pointer to Memory Dispatch Globals. ; 4/2/93 GMR Changed the parameters to _DMAIntInstall for PDM, to take a ; param block ptr in A0. This fixes the problem where a2 was used ; to pass in the refCon and was getting trashed. ; 3/11/93 SAM Added a refCon field to the PDM DMA irq handler installer. ; 2/20/93 SAM Changed every Page Table Entry/MMU whacking routine to work with ; EMMUs. Removed a few more slow things from GetPhysical - it ; shouldn't call any traps any more (rah!). Removed all the TST.W ; that followed every call to GetRealProc. Updated ; InitMemoryDispatch to know about EMMUs. Removed the separate ; code that Unimplements memorydispatch and put its functionality ; into InitMemDispatch. ; 2/11/93 PW Added passing of drivers' "don't munge heaps" bit into SCSILoad. ; 2/9/93 rab Sync up with Horror. Comments follow. ;

7/13/92 NJV Fixed bug in LockMemory and LockMemoryContiguous that ; crashed when the page containing the current stack was locked. ; Fixed it by turning off the data cache between modifying page ; descriptors and flushing the ATC. ; 2/6/93 RC Fixed last fix (sorry) ; 2/6/93 RC Fixed InitMemDispatchTrap for Quadra ; 2/5/93 SAM Added PDM build specific vectors for MemoryDispatch and have ; changed the code that unimplements MemDisp if you don't have a ; known MMU type. ; 12/11/92 SWC Moved the code to disable the MemoryDispatch trap here from ; StartInit. Put a hasMDU conditional around the EnableExtCache ; code. ; 11/3/92 SWC Changed SCSIEqu.a->SCSI.a. ; 10/30/92 chp I universalized DMADispatch by making it appear to be ; unimplemented (return paramErr) on machines with no PSC. ; DMADispatchNub should not be link patched for non-universal ROMs ; because it makes a TestFor. SwapSerialClock is broken on ; non-universal ROMs for exactly this reason. ; 6/19/92 RB Added the selector for the DMADispatch code. ; 5/17/92 kc Roll in Horror changes. Comments follow. ; 4/22/92 kc Changed MemoryDispatch to use word offsets instead of long ; offsets. Stubed out the routine LockMemoryContiguousProcÊin ; order to get the flasher to work. ; 7/11/91 CCH Fixed a bug in GetPhysical. ; 6/27/91 djw (pdw) Add new selector _WaitForSCSIDevs to wait for SCSI devices ; and load their drivers. Just added nub code here. ; 6/14/91 RP Changed length parameter for FlushCacheRange to be passed in A1 ; instead of D1. ; 5/10/91 RP Added selector to HwPriv for flush cache range. ; 5/10/91 CCH Added selector to HwPriv for Edisk protection. ;
2/18/91 JK Added WriteProtect selectors to MemoryDispatch ;
1/24/91 JK Added LockMemory calls that use a page-lock table. ;

1/24/91 CCH Moved LastEnt label to include new selectors. ;

1/24/91 CCH Significantly modified MemoryDispatch code. Removed translate ; routine in favor of _GetReal call, modified _GetPhysical to use ; GetRealProc instead. Added _GetReal and _GetPageDesc selectors. ; Removed _LockMemory code since it will change anyway. Also added ; padding at end of file. ;

10/2/90 CCH Patched out cache manipulation routines to HwPrivPatch.a. ; ¥ from HwPrivPatch.a ; <13> 7/11/91 HJR Change return result from SCSIDrvrs to success/failed. ; <12> 7/10/91 RP Changed FlushCacheRange to round count to be quad-word aligned. ; <11> 6/27/91 djw (pdw) Add WaitForSCSIDevs to wait for SCSI devices and load ; their drivers. ; <10> 6/25/91 CCH Fixed _SwapDataCache to flush the data cache before disabling it ; on 68040's. Also jump through jCacheFlush instead of using a ; CPUSH instruction in _FlushInstructionCache and ; _SwapInstructionCache. ; <9> 6/14/91 RP Changed length parameter for FlushCacheRange to be passed in A1 ; instead of D1. ; <8> 5/10/91 RP Added support to flush a range of cache lines from the 040 ; cache. ; <7> 5/10/91 CCH Made _ProtectMemory and _UnProtectMemory use the CacheFlush ; low-mem. ; <6> 4/22/91 BG Modified 040 cache flushing routines to add a NOP before the ; CPUSHA . This is required because of Motorola's xD43B ; errata item E19. This should be removed when the 040 processor ; base is D50D. Changed _FlushInstructionCache to jump to ; ([jCacheFlush]) so that if/when we have to fix/unfix flushing ; ALL caches, we only have to do it in one place. ; <5> 4/18/91 BG Changed the 040 part of _FlushInstructionCache to flush both ; caches. People are probably calling this becasuse they just ; read in some code/resource/driver/whatever that they want to ; execute and they want to make sure whatever it is in memory and ; the instruction cache is synchronized with memory. On the 040, ; the best way to do this is to flush both caches. ; <4> 2/18/91 JK Added WriteProtect and UnWriteProtect code ; <3> 1/24/91 JK MMUSetCacheMode whacks page descriptor in 32-bit mode. ; <2> 1/24/91 JK Added LockMemory calls that use a page-lock table. ; <1> 10/3/90 CCH first checked in ; ; <4> 3/31/92 FM Merged in changes from Reality. ; <3> 3/31/92 FM Rolled changes into reality. ; <2> 2/13/92 RB When I rolled in the new HWPriv selector for Flush cache range, ; I put the wrong label in the table. That label is used only by ; the 040 Blockmove, which passes parameters in the stack. ; Correcting the label will fix the stack. ; <29> 2/20/92 DTY #1021830: The Regatta version of _HWPriv totally breaks ; accelerators for 68000 CPUs because a selector number is not put ; in place for these machines. What winds up happening is on ; accelerated 68000s, every selector returns an error because ; _HWPriv thinks itÕs an invalid selector. Add a new InstallProc ; which initializes the valid selector range for the Plus, SE, and ; Portable ROMs if CPUFlag is a 68020 or 68030. ; <28> 1/24/92 KC Fix bug introduced in last revision (replace missing semicolon). ; <27> 1/23/92 KC Added InitMemoryDispatch from Zydeco:HWPrivPatch.a. ; <26> 1/3/92 RB Added the Flush cache range routine for 68040's from Terror to ; the ROM build. The system table is unchanged (uses Flush ; instruction cache instead). ; <25> 1/3/92 RB Added the EDiskProtection routine to the ROM hwPriv table. ; Terror changes in HWPrivPatch.a (Terror file) need to be looked ; at before modifying this file. ; <24> 11/16/91 DTY More BandAids¨ to get the ROM build working again. Re-export ; EnableExtCache (called by StartInit), put back MemoryDispatch ; code (referenced from DispTable), and add the HWPriv label back ; (also referenced from DispTable). ; <23> 10/29/91 SAM This file will now generate the correct code for the ROM build ; (it even works and doesnt change the System build code - rah). ; Everything changed in this rev is enclosed in forROM ; conditionals. ; <22> 10/29/91 SAM Removed the Ôstupid conditionalsÕ again. Sorry about that Jeff. ; <21> 10/28/91 SAM/KSM Rolled in Regatta file. Undid Changes <17>-<20>. ; ; 7.0.1 Change History: ; ; <6> 7/17/91 SAM Removed the commented out MemoryDispatch patch stuff. Added ; Paul Wolf's WaitForSCSI to hwPriv's list o' routines. ; <5> 6/14/91 SAM The hwPriv install procs that set up the ExpandMem set of ; vectors now only load on II ROMs or IIci ROMs. ; <3> 5/28/91 SAM Rewrote all of the HwPriv patcher/dispatcher. Now we have ; relocatable tables of vectors to the hwPriv routines that get ; installed by the LinkedPatch Loader. Non-TERROR ROM 020/030 ; Machines get their own table (that includes all of the routines ; in this file) and TERROR machines get a table of zeroes (which ; means call the ROM). This way all the code in this file is not ; loaded when not needed and also there is now an easy way to ; patch the vectors via expandMem. ; <2> 5/23/91 SAM Rewrote the hwPriv dispatcher. Now more LinkedPatch friendly ; than ever! Will now jump to ROM on a selector that is out of ; range. Made the table of hwPrivSelectors a separate resident ; proc. Added a new macro for the table of selectors called ; HwPrivSelectorInROM that acts as a placeholder for selectors ; that are implemented in ROM. ; <1> 5/22/91 SAM Split off from 7.0 GM sources. Changed hwPriv to call the ROM hwPriv ; for all selectors that this file doesnt know about. ; ; 7.0 Change History: ; ; <20> 10/18/91 JSM Get rid of all the stupid conditionals. ; <19> 9/30/91 JSM Cleanup header, donÕt use is32BitClean conditional - all future ; ROMs will be. ; <18> 8/30/91 DTY Define isUniversal here since itÕs no longer an available ; feature in BBSStartup. ; <17> 6/12/91 LN removed #include 'HardwareEqu.a' ; <16> 3/11/91 gbm stb, bbm: Take out the bogus GetPhysical patch, in preparation ; of loading the new one. ; <15> 2/6/91 eh (djw) Fix SwapSerialClock routine to wait for IOP request ; completion before returning. ; <14> 1/3/91 gbm (dnf) Fix last addition made by SAM. One of these days, he'll ; actually build the files he checks in. ; <13> 1/3/91 SAM Changed the LinkedPatch install conditional so that the patch to ; _MemoryDispatch for getPhysical is not installed if VM is ; running. ; <12> 12/14/90 dba get rid of include of VMCalls.a ; <11> 8/22/90 SAM Adding fixes to GetPhysical so it works correctly with the ; 8¥24¥GC. ; <10> 8/21/90 csd Changed the condition for the MemoryDispatch patch so that it ; doesnÕt install where MemoryDispatch is not implemented. (Elsie) ; <9> 7/30/90 BG Fixed 040 CACR-related problems. ; <8> 7/24/90 EMT NEEDED FOR SIXPACK: Fixed 68000 code and eliminated unecessary ; table. ; <7> 7/23/90 CCH NEEDED FOR SIXPACK: Patched the GetPhysical selector on ; _MemoryDispatch on $67c based ROMs to return physical addresses ; for non-RAM logical addrs. ; <6> 7/21/90 BG Removed unnecessary EclipseNOPs. Also changed s to <5>s ; (yer welcome, Carl). ; <5> 7/19/90 CCH NEEDED FOR SIXPACK: Rolled in SwapSerialClock selector from PTCH ; file and converted to linked patches. ; <4> 6/19/90 CCH Changed two occurences of CINVA IC to CPUSHA BC to hopefully ; prevent incompatibility problems with the 68040 copyback cache ; mode. Also added some NOPs for flaky 68040's. ; <3> 2/18/90 BG Added 040 versions of the machine-dependent routines for ; manipulating the I&D caches. ; <2> 1/11/90 CCH Added include of ÒHardwarePrivateEqu.aÓ. ; <2.1> 7/16/89 CSL cleaned up lockMemoryCont, GetPhysical, Translate. ; <2.0> 6/30/89 CSL disable data cache and increment LockMemCt when LockMemory and ; LockMemoryContiguous is performed successfully, increment ; lockMemCt when UnLockMemory is called, if LockMemCt becomes ; zero, enable data cache. Also removed selector for ; GetSystemMemoryInfo. ; <1.9> 6/15/89 CSL Added FlushExtCache selector. ; <1.8> 5/31/89 CSL Use register D2 for error code for chkcontiguous. ; <1.7> 5/30/89 GGD Added missing ".b" to DisableExtCache RBV access. Added code to ; return noErr for EnableExtCache and DisableExtCache. ; <1.6> 5/30/89 CSL For getPhysical and LockMemoryContiguous, always switched to 32 ; bit ; <1.5> 5/24/89 GGD Converted to feature based conditionals, No code changes. ; <1.4> 5/16/89 CSL changed using EQU Frmbufbase to lowMem Phys2log. ; <1.3> 4/28/89 CSL Changed Interface for GetPhysical. ; <1.2> 4/17/89 CSL update _MemoryDispatch with VM spec. ; <1.1> 2/28/89 CSL Added MemoryDispatch trap for address translation for hafmac. ; <1.0> 2/24/89 rwh rolled in today from Mac IIx ROM ; MACHINE MC68030 PRINT PUSH,OFF LOAD 'StandardEqu.d' INCLUDE 'hardwarePrivateEqu.a' INCLUDE 'GestaltEqu.a' INCLUDE 'InternalMacros.a' INCLUDE 'UniversalEqu.a' INCLUDE 'MMUEqu.a' INCLUDE 'IOPEqu.a' INCLUDE 'LinkedPatchMacros.a' INCLUDE 'SCSI.a' INCLUDE 'PowerPrivEqu.a' INCLUDE 'DockingEqu.a' PRINT POP ;---------- ; ; HwPrivSelector Macro ; ;---------- MACRO HwPrivSelector &addr IMPORT &addr dc.w &addr-Vects ; OFFSET of routine ENDM HwVecSize EQU 2 ;---------- ; ; HWPriv (_HWPriv trap) ; ; The _HWPriv trap was created to export some low level hardware control capabilites to ; the (user mode) world at large. A selector passed in D0 determines which specific ; transistor to twiddle. ; ; The selector mechanism makes the trap expandable - as we add more strange hardware, ; we can define new selectors (and write new routines) to control it. Each selector ; is almost like a new trap. If we want to be really gross, the parameter passing ; conventions can be different for each selector. At the expense of a non-uniform ; interface to the trap, this avoids having to invent some cumbersome huge extendable ; parameter block that covers all present and future possibilities. ; ; The selectors currently defined are: ; ; 0 - SwapInstructionCache (turn off/on the 020/030/... instruction cache) ; 1 - FlushInstructionCache ; 2 - SwapDataCache (turn off/on the 030/... data cache) ; 3 - FlushDataCache ; 4 - EnableExtCache ; 5 - DisableExtCache ; 6 - FlushExtCache ; 7 - SwapSerialClock ; 8 - EDiskProtect (in TERROR ROM) ; 9 - FlushRange (in TERROR ROM) ; 10 - WaitForSCSIDevs (in TERROR ROM) ; 11 - UnusedSelector (in SuperMario) ; 12 - SlotBlockXferCtl (in SuperMario) ; 13 - GetENetID (in SuperMario/KAOS ROM) ; ; Entry: ; D0 (low order word) holds routine selector ; A0 holds parameter (optional for some selectors) ; D1-D2/A1 saved by trap dispatcher ; ; Exit: ; D0 (long) zero if all went well, non-zero if selector out of range ; A0 (long) returned value (optional for some selectors) ; ; Destroys: D0, plus whatever registers the selector routines use ; ;---------- HWPriv PROC EXPORT ; KISS (Keep it simple and easy to patch) bra.b HWPrivSwitch ALIGN 8 Vects ;table of offsets to selector routines HwPrivSelector SwapICache ; 0 SwapICache HwPrivSelector FlushICache ; 1 FlushICache HwPrivSelector SwapDCache ; 2 SwapDCache HwPrivSelector FlushDCache ; 3 FlushDCache HwPrivSelector EnableExtCache ; 4 EnableExtCache HwPrivSelector DisableExtCache ; 5 DisableExtCache HwPrivSelector FlushExtCache ; 6 FlushExtCache HwPrivSelector SwapSerialClock ; 7 SwapSerialClock ; HwPrivSelector ProtectEDisk ; 8 Protect/Unprotect EDisk dc.w $d8b8 ; HARDCODED due to unhappy linker, must remove HwPrivSelector FlushCRange ; 9 FlushCRange HwPrivSelector ReturnErr ; 10 WaitForSCSIDevs HwPrivSelector ReturnErr ; 11 Unused HwPrivSelector SlotBlockXferCtl ; 12 - enable block xfers to a slot HwPrivSelector ReturnErr ; 13 - Get Ethernet ID from serial ROM HwPrivSelector ReturnErr ; 14 HwPrivSelector ReturnErr ; 15 HwPrivSelector MakeSomethingWriteThrough ; 16 LastVec ALIGN 8 HWPrivSwitch cmpi.w #(LastVec-Vects)/HwVecSize,d0 ; check if selector in range bcc.s ReturnErr ; abort if itÕs not a valid selector move.w Vects(d0*HwVecSize),d0 ; get offset to selectorÕs routine jmp Vects(d0) ; go to the routine ENDPROC ReturnErr PROC ENTRY move.l #hwParamErr,d0 ; abort: return error code rts ENDPROC ;---------- ; ; SwapICache (_HWPriv Selector 0) ; ; This routine turns the 020/030/040 instruction cache off or on. If the cache is being ; turned on, it is also flushed. ; ; Entry: ; ; A0 (long) - zero to turn instruction cache off, non-zero to turn it on ; ; Exit: ; ; A0 (long) - has previous state of instruction cache (zero = off, non-zero = on) ; ; Destroys: D1, D2 ; ;---------- SwapICache PROC EXPORT @EmuFake lea 1,a0 ; do nothing and report that caches were enabled moveq #noErr,d0 rts ENDPROC ;---------- ; ; FlushICache (_HWPriv Selector 1) ; ; This routine flushes the 020/030/040...'s instruction cache. ; ; On 040s, it also causes a flush of the data cache. This is because previous uses ; of _FlushInstructionCache were to make sure that memory and caches were in sync if ; either self-modifying or newly read-in code (from wherever). ; ; Destroys: none ; ;---------- FlushICache PROC EXPORT btst.b #2,$240a bnz.b @Coherent jsr ([jCacheFlush]) ; invalidate both caches @Coherent moveq #noErr,d0 ; signal all's well rts ENDPROC ;---------- ; ; SwapDCache (_HWPriv Selector 2) ; ; This routine turns the 020/030/040... data cache off or on. If the cache is being ; turned on, it is also flushed. ; ; Entry: ; ; A0 (long) - zero to turn data cache off, non-zero to turn it on ; ; Exit: ; ; A0 (long) - has previous state of data cache (zero = off, non-zero = on) ; ; Destroys: D1, D2 ; ;---------- SwapDCache PROC EXPORT @EmuFake lea 1,a0 ; do nothing and report that caches were enabled moveq #noErr,d0 rts ENDPROC ;---------- ; ; FlushDCache (_HWPriv Selector 3) ; ; This routine flushes the 030/040...'s data cache. It has no effect on an 020. ; ; Destroys: none ; ;---------- FlushDCache PROC EXPORT moveq #noErr,d0 ; signal all's well rts ENDPROC ;---------- ; ; EnableExtCache (_HWPriv Selector 4) ; ; This routine turns the external Cache on. ; Entry: none ; EXit: none ; ;---------- EnableExtCache PROC EXPORT moveq #noErr,d0 ; signal all's well rts ENDPROC ;---------- ; ; DisableExtCache (_HWPriv Selector 5) ; ; This routine turns the external Cache off. ; Entry: none ; EXit: none ; ;---------- DisableExtCache PROC EXPORT moveq #noErr,d0 ; signal all's well rts ENDPROC ;---------- ; ; FlushExtCache (_HWPriv Selector 6) ; ; This routine flushes the external Cache by disabling external Cache and ; enabling external cache. ; Entry: none ; EXit: none ; ;---------- FlushExtCache PROC EXPORT JSR DisableExtCache ; call routine directly JSR EnableExtCache ; call routine directly RTS ENDPROC ;---------- ; ; SwapSerialClock (_HWPriv Selector 7) ; ; This routine enables or disables external clocking to the SCC. The external clock ; comes to the SCC through the RTxC signal, which is connected to the GPi pin on the ; serial port connector. External clocking is currently switched by the vSync bit ; on VIA 1, or through a call to the SCC IOP. The interface is left open-ended to ; allow external clock control on any number of SCC's or serial ports. Current CPU's ; only support one SCC and port A external clocking. ; ; NOTE: this call is supported for the fx in BYPASS mode only. (although we still call ; the IOP to execute the call) ; ; Entry: ; D0.L = routine selector ; A0.L = .B .B .W ; bits 31-24: SCC number currently 0 for future expansion ; 23-16: port number 0=port A, 1=port B,... for future expansion ; 15-0 : 0=internal clocking, 1=external clocking ; Exit: ; D0.L = zero if good, -1 if error ; A0.L = .B .B .W ; ;---------- SwapSerialClock PROC EXPORT moveq #-1,d0 ; assume an error return move.l a0,d1 ; d1 will hold the return value move.l d1,d2 swap d2 ; d2 = .w .b .b tst.w d2 ; check SCC and port number bne ReturnErr ; only port A supported @BuiltinSCC TestFor VIA1Exists beq.s @Done ; no via - nothing to do now tst.w d1 ; get state to set from low word snz d2 ; set or clear D2.B accordingly movea.l VIA,a1 clr.w d1 btst #vSync,vBufA(a1) ; test current value snz d1 ; set or clear D1.B accordingly eor.b d1,d2 ; setting already the same as old ? beq.s @FixResult ; already set to correct state - done bchg #vSync,vBufA(a1) ; change the clock setting @FixResult neg.b d1 moveq #noErr,d0 ; set good error return ; Done - return the old external clock state. ; To do: This does not return valid information in the IOP case! ; To do: This does not return valid information when VIA1 is missing! @Done movea.l d1,a0 ; return previous state in A0 rts ENDPROC ;---------- ; ; FlushCRange (_HWPriv Selector 9) ; ; This routine flushes a range of addresses from the 040 caches ; (or the whole cache on non 040 machines). ; ; Entry: ; ; A0 (long) - Starting logical address. ; A1 (long) - Count. ; ; Exit: ; ; Destroys: D1, D2 ; ; FlushCRangeForBM is glue for BlockMove ; ;---------- FlushCRangeForBM PROC EXPORT EXPORT FlushCRange FlushCRange move.l a1,d0 dc.w $FC16 @EmuFake moveq #noErr,d0 rts ENDPROC ;---------- ; ; SlotBlockXferCtl (_HWPriv Selector 12) ; ; This routine enables/disables MUNI's, Cyclone/Tempest Nubus Controller, ability to ; block xfer TO a Nubus slot. Note: MUNI is always able to recv a block xfer FROM a ; Nubus slot. ; ; Entry: ; A0 (long) - (bits 31-9) reserved ; - (bit 8) zero to disable block xfer to a slot , one to turn it on ; - (bits 7-0) slot number, 1 - 14 ; ; Exit: ; D0 (long) - 0 if we're on a MUNI-based system & good slot value, paramErr if not ; A0 (long) - if noerr, previous state of block xfer for each slot (1=on, 0=off) ; (Bits 31-15 reserved, Bit 14 = slot 14, ... bit 1 = slot 1, bit 0 reserved) ; ; Destroys: D1, D2, A1 ; ;---------- SlotBlockXferCtl PROC EXPORT moveq #paramErr,D0 rts ENDPROC ;---------- ; ; MakeSomethingWriteThrough ; ;---------- MakeSomethingWriteThrough PROC EXPORT Move.L ([$1FF4],$8), D2 Move.L A0, D0 LsR.L D2, D0 MoveA.L D0, A0 Move.L A1, D0 SubQ.L #$1, D0 LsR.L D2, D0 Move.L D0, D2 @loop _nkMakePageWriteThrough Tst.L D0 BMI.B @exit AddQ #$1, A0 DBF D2, @loop MoveQ.L #$0, D0 @exit Rts ENDPROC ;==================================================================================================== ; ; Everything above was HwPriv. Everything below is MemoryDispatch. ; ; ItÕs not exactly clear why all this got thrown into one file. ; ;==================================================================================================== ;----- ; Adding new MemoryDispatch routines that work on a page basis. ; This to provide support for Sonic onboard Ethernet. ; ; To support write-protect, the lock counter behavior has been altered to include ; a write-protect bit. The high bit in each lock counter indicates that the page ; is write-protected. No count is kept of the number of lock/unlock calls that ; have been made. ;----- ;---------- ; ; MemDispSelector Macro - This macro allows us to build the selector jump table correctly, ; regardless of whether compiling for ROM or System. When compiling ; as a System patch, absolute addresses are generated, and offsets are ; used when compiling for ROM. ; ;----- IF ForROM THEN ; <5> MACRO MemDispSelector &addr import &addr dc.w &addr-Vects ; OFFSET of routine ENDM MdVecSize EQU 2 ELSE MACRO MemDispSelector &addr dcImportResident &addr ; ADDRESS of routine ENDM MdVecSize EQU 4 ENDIF ;--------------- ; ; MemoryDispatch a590 ; ; Provides services for Virtual Memory access to the hardware ; ;------------------- MemoryDispatch PROC Export bra.s MemoryDispatchCode Vects ;table of offset to selector routines MemDispSelector HoldMemoryProc ; 0 MemDispSelector UnHoldMemoryProc ; 1 MemDispSelector LockMemoryProc ; 2 MemDispSelector UnLockMemoryProc ; 3 MemDispSelector LockMemoryContiguousProc ; 4 MemDispSelector GetPhysicalProc ; 5 MemDispSelector WriteProtectProc ; 6 MemDispSelector UnWriteProtectProc ; 7 dc.w badSelect-Vects ; 8 dc.w badSelect-Vects ; 9 LastVec MemDispSelector LockMemoryProc ; 10 MemoryDispatchCode cmp.w #(LastVec-Vects)/MdVecSize,d0 ; check if selector in range bhi.s badSelect ; abort if its not a valid selector move.w Vects(d0.w*MdVecSize),d0 ; get offset to selector's routine jmp Vects(d0) ; go to the routine badSelect2 badSelect3 badSelect move.l #hwParamErr,d0 ; abort: return error code rts EndProc ;----- ; ; HoldMemoryProc a5c0 (_MemoryDispatch Selector 0) ; ; This routine makes the address space resident in real memory and ineligible for paging. ; ; Destroys: none ; ;----- HoldMemoryProc PROC Export Moveq #0,D0 ; no error Rts EndProc ;----- ; ; UnHoldMemoryProc a5d0 (_MemoryDispatch Selector 1) ; ; This routine makes the address space eligible for paging. ; ; Destroys: none ; ;----- UnHoldMemoryProc PROC Export Moveq #0,D0 ; no error Rts EndProc ;----- ; ; LockMemoryProc a5e0 (_MemoryDispatch Selector 2) ; ; This routine makes the address space immovable in real memory and ineligible for paging. ; It also marks the corresponding page frames as non-cacheable, and increments the ; lock count for the page. ; ; After calling GetPageRange, d1 contains the page number of the first logical page, ; and d2 contains the page count. ; ; Destroys: none ; ; Calls: GetPageRange, MMUMakePageNonCacheable, MMUFlushATC, MMUFlushDataCache ; ;----- LockMemoryProc PROC Export Import GetPageRange,MMUFlushATC,MMUSetCacheInhibit WITH MemDispGlobals @saveRegs REG d1-d4/a0-a2 movem.l @saveRegs,-(sp) ; save registers movea.l LockMemCt,a2 ; point to MemoryDispatch globals bsr GetPageRange ; check input arguments bne.s @error ; get out lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page moveq.l #1,d0 ; flag to MMUSetCacheInhibit to inhibit caching @loop addq.w #1,(a1)+ ; bump the lock count bsr MMUSetCacheInhibit ; mark page as noncacheable addq.l #1,d1 ; increment page number subq.l #1,d2 ; one less page to go bhi.s @loop ; keep looping @done moveq.l #noErr,d0 ; no error @error movem.l (sp)+,@saveRegs ; restore registers rts EndWith EndProc ;----- ; ; UnLockMemoryProc a610 (_MemoryDispatch Selector 3) ; ; This routine makes the address space movable in real memory and eligible for paging again. ; It also decrements the lock count for the corresponding page frames, and if the ; count is zero, markd the page as cacheable. ; ; Destroys: none ; ;----- UnLockMemoryProc PROC Export Import GetPageRange,MMUSetCacheInhibit,MMUFlushATC With MemDispGlobals @saveRegs REG d1-d4/a0-a2 movem.l @saveRegs,-(sp) ; save registers movea.l LockMemCt,a2 ; point to MemoryDispatch globals bsr GetPageRange ; check input arguments bne.s @error ; get out lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page move.l d2,d3 ; copy of the count move.w #notLockedErr,d0 ; assume a nonlocked page @lockCheckLoop tst.w (a1)+ ; check the page lock counter beq.s @error ; if zero, page was not locked previously subq.l #1,d3 ; one less page to go bhi.s @lockCheckLoop ; keep looping lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page move.l d2,d3 ; copy of the count moveq.l #0,d0 ; flag to MMUSetCacheInhibit to enable caching moveq.l #0,d4 ; assume ATC will not need to be cleared @unlockLoop subq.w #1,(a1)+ ; decrement the lock count for this page bne.s @stillLocked ; if count != 0, page will remain locked bsr MMUSetCacheInhibit ; mark page as cacheable moveq.l #1,d4 ; ATC will need to be cleared (a PTE changed) @stillLocked addq.l #1,d1 ; move on to next page subq.l #1,d3 ; one less page to go bhi.s @unlockLoop ; keep looping tst.l d4 ; do we need to flush the ATC beq.s @noFlush ; if not, don't do it bsr MMUFlushATC ; flush ATC's @noFlush moveq.l #noErr,d0 ; return noErr @error movem.l (sp)+,@saveRegs ; restore registers rts EndWith EndProc ;------------------------------------------------------------------- ; ; LockMemoryContiguousProc a660 (_MemoryDispatch Selector 4) ; ; This routine provides the service of making a virtual address range contiguous in ; physical address space. ; ; Destroys: none ; on Entry: ; A0.L = start of logical address ; D0.W = 4, selector ; A1.L = number of bytes in buffer ; ; on Exit: ; D0.W = error code ; ;------------------------------------------------------------------- LockMemoryContiguousProc PROC Export Import GetPageRange,GetRealProc,MMUSetCacheInhibit,MMUFlushATC With MemDispGlobals @saveRegs REG a0-a3/d1-d4 @moreRegs REG d1/a1-a2 movem.l @saveRegs,-(sp) ; save registers movea.l LockMemCt,a2 ; point to MemoryDispatch globals bsr GetPageRange ; check input arguments bne.s @error ; get out (returns paramErr) movea.l a0,a3 ; copy starting logical address movem.l @moreRegs,-(sp) ; save registers that GetReal destroys bsr GetRealProc ; get the starting physical address movem.l (sp)+,@moreRegs ; restore registers that GetReal destroys exg.l a0,a3 ; hold on to starting physical address adda.l a1,a0 ; add length of buffer - 1 subq.l #1,a0 movem.l @moreRegs,-(sp) ; save registers that GetReal destroys bsr GetRealProc ; get the ending physical address movem.l (sp)+,@moreRegs ; restore registers that GetReal destroys suba.l a3,a0 ; get the distance between the addresses addq.l #1,a0 ; adjust calculation cmpa.l a1,a0 ; compare the results bne.s @notContigError ; range crosses a non-contiguous bank boundary lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page moveq.l #1,d0 ; flag to MMUSetCacheInhibit to inhibit caching @loop addq.w #1,(a1)+ ; bump the lock count bsr MMUSetCacheInhibit ; mark page as noncacheable addq.l #1,d1 ; increment page number subq.l #1,d2 ; one less page to go bhi.s @loop ; keep looping @done moveq.l #noErr,d0 ; no error @error movem.l (sp)+,@saveRegs ; restore registers rts @notContigError move.w #cannotMakeContiguousErr,d0 ; addresses are not contiguous bra.s @error EndWith EndProc ;------------------------------------------------------------------- ; ; GetPhysicalProc a6c0 (_MemoryDispatch Selector 5) ; ; This routine translates virtual addressess to corresponding physical addresses. ; ; Destroys: none ; ; on Entry: ; A0.L = pointer to translation table ; D0.W = 5, selector ; A1.L = number of entries in table ; A1.L = 0, if caller want to get number of entries required ; ; on Exit: ; D0.W = error code ; A0.L = number of pairs returned/required ; A1.L = pointer to translation table ; ;------------------------------------------------------------------- VAddr EQU -8 ; offset to virtual address from A0 BuffSize EQU -4 ; offset to buffer size SavedPtr EQU 2 ; offset to saved ptr in stack GetPhysicalProc PROC Export Import GetRealProc,ChkContig GetPhysRegs REG d3/a3-a4 MOVEM.L GetPhysRegs,-(SP) ; save register move.l a0,-(sp) ; save pointer to table on stack move.l a0,a4 ; get table entry pointer in a4 Move.L A1,D3 ; get table entry number MOVE.L (A4)+,D2 ; get virtual address in d2 @NoSwap move.l d2,a0 ; put virtual address in a0 ADD.L (A4),D2 ; get end of buffer CMP.L realMemtop,D2 ; does it exceed available RAM BHI.S @BadAddress ; >>EXIT if it exceeds top of RAM BSR.L GetRealProc ; get physical address in a0 BMI.S @BadAddress ; branch if bad address MOVE.L A0,A3 ; save physical address in A3 MOVE.L D2,A0 ; get end of buffer SUBQ.L #1,A0 ; convert to end address BSR.L GetRealProc ; get physical address in a0 BMI.S @BadAddress ; branch if bad address SUB.L A3,A0 ; calculate distance between addresses ADDQ.L #1,A0 ; convert to byte count CMP.L (A4),A0 ; are they the same size BNE.S @NonContig ; branch, if memory is not contiguous TST.L d3 ; d3 = 0?? BEQ.S @return1 ; branch, if yes MOVE.L (A4)+,D0 ; save buffer size ADD.L D0,VAddr(A4) ; update virtual address MOVE.L #0,BuffSize(A4) ; update buffer size MOVE.L A3,(A4)+ ; save physcial address in table MOVE.L D0,(A4) ; save size in table @return1 MOVE.L #1,A0 ; return with 1 entry MOVE.W #0,D2 ; and with no error @GPEXit MOVE.L D2,D0 ; set final error code MOVE.L (SP)+,A1 ; restore pointer MOVEM.L (SP)+,GetPhysRegs ; restore registers RTS @BadAddress MOVEQ #0,A0 ; when error, return zero entry MOVE.W #paramErr,D2 ; return paramErr BRA.S @GPExit @NonContig MOVE.L (SP),A4 ; A0 gets pointer to table MOVE.L (A4),A0 ; get logical address in A0 ADD.L #8,A4 ; A4 = points to table entry MOVE.L D3,D1 ; D1 = number of table entry or 0 BSR ChkContig ; check contiguous physical TST.W D2 ; are there error BMI.S @BadAddress MOVE.L D1,A0 ; get number of entries in A0 BRA.S @GPEXit EndProc ;------------------------------------------------------------------- ; ; ChkContig:- ; Check for contiguous address space for buffer ; This code is written in a rush, and should be rewritten ; in the future. ; ; on entry: ; A0 = logical address ; A4 = pointer to table ; D1 = number of table entries or 0 ; on exit: ; D1 = number of table entries ; D2 = error code ; ; destroys: A3 ;------------------------------------------------------------------- StkFrame record {a6link},decr a6link DS.L 1 ; old link pointer PhysAddr DS.L 1 ; physical address PageAddr DS.L 1 ; physical page address ContigSize DS.L 1 ; contiguous memory size EntryNum DS.L 1 ; number of entry EntryReq DS.L 1 ; entry required EntryIndex DS.L 1 ; current entry Index OVAddr DS.L 1 ; original virtual address OSize DS.L 1 ; original size StkSize equ * ; size of locals endr ChkContig PROC Export Import GetRealProc With MemDispGlobals WITH StkFrame LINK A6,#StkSize ; define a stack frame for local variable Movem.L D3-D7,-(SP) ; save registers MOVE.L D1,EntryNum(A6) ; save number of entry MOVE.L #1,EntryReq(A6) ; initialize entry required to 1 MOVE.L #0,EntryIndex(A6) ; initialize current entry index to 0 MOVE.L VAddr(a4),OVaddr(A6) ; save original virtual address MOVE.L Buffsize(a4),OSize(A6) ; save original size BSR.L GetRealProc ; convert addr in a0 to physical addr BMI @BadAddress ; branch if bad address MOVE.L A0,PhysAddr(A6) ; save physical address MOVE.L LockMemCt,A2 ; point to MemoryDispatch globals move.l mdPageSize(A2),D2 ; point to MemoryDispatch globals ; Removed a ¥Gestalt¥ call to get the page size! Sheeze! ; to calculate amount of memory in the first page SUBQ #1,d2 ; create mask to get bytes in 1st page MOVE.L PhysAddr(A6),D3 ; get physical address NEG.L D3 ; negate the address AND.L D3,D2 ; get remaining bytes in first page MOVE.L D2,ContigSize(A6) ; save memory size MOVE.L OVaddr(A6),A3 ; get original logical address ADD.L D2,A3 ; get logical address on page boundary @loop MOVE.L A3,A0 ; get logical address into A0 BSR.L GetRealProc ; convert addr in A0 to physical addr BMI @BadAddress ; branch if bad address MOVE.L LockMemCt,A2 ; restore A2,points toMemoryDispatch globals MOVE.L PhysAddr(A6),D3 ; get saved start physical address Add.L ContigSize(A6),D3 ; added length of contiguous address CMP.L D3,a0 ; Does it match the new physical address BNE.S @NotContig ; branch if not contiguous MOVE.L ContigSize(A6),D3 ; get contiguous size @common ADD.L mdPageSize(a2),D3 ; update Contiguous memory size CMP.L BuffSize(a4),D3 ; is it end yet? BCC.S @Done ; yes, branch MOVE.L D3,ContigSize(A6) ; update contiguous size ADD.L mdPageSize(a2),A3 ; get new virtual address BRA.S @loop @NotContig TST.L EntryNum(A6) ; test number of entries BEQ.S @justCount ; just count MOVE.L EntryIndex(A6),D3 ; get entry index MOVE.L PhysAddr(A6),(0,a4,D3.L*8) ; store physical address MOVE.L ContigSize(A6),(4,a4,D3.L*8); store contiguous size Add.L #1,D3 ; advance current entry CMP.L EntryNum(A6),D3 ; end of table yet? BCC.S @ExitA ; if yes, done MOVE.L D3,EntryIndex(A6) ; update index @justCount ADDQ.L #1,EntryReq(A6) ; update entry required MOVE.L ContigSize(A6),D3 ; get ContigSize ADD.L D3,VAddr(a4) ; update virtual address SUB.L D3,BuffSize(a4) ; update buffer size Move.L A0,PhysAddr(A6) ; update new physical address MOVEQ #0,D3 ; initial to zero memory BRA.S @common ; branch back inside loop @Done TST.L EntryNum(A6) ; test number of entries BNE.S @GetResult ; branch, if not zero Move.L EntryReq(A6),D1 ; get entry required MOVE.L OVaddr(A6),VAddr(a4) ; restore original virtual address MOVE.L OSize(A6),BuffSize(a4) ; restore original size BRA.S @ExitB @GetResult MOVE.L EntryIndex(A6),D3 ; get entry index MOVE.L PhysAddr(A6),(0,a4,D3.L*8) ; store physical address MOVE.L BuffSize(a4),(4,a4,D3.L*8) ; store size MOVE.L BuffSize(a4),D2 ; save remaining buffsize Add.L D2,VAddr(a4) ; update virtual address MOVE.L #0,BuffSize(a4) ; indicate complete translation AddQ.L #1,D3 ; convert index to entry count @ExitA MOVE.L D3,D1 ; return entry count @ExitB MOVEQ #0,D2 ; no error @ExitC MOVEM.L (SP)+,D3-D7 ; restore registers UNLK A6 ENDWITH RTS @BadAddress MOVE.W #-1,D2 ; return paramErr BRA.S @ExitC EndWith EndProc ;----- ; ; WriteProtectProc a850 (_MemoryDispatch Selector 6) ; ; This routine protects the address space from write accesses. ; It also sets the high bit in the lock counter for each page in the range. ; ; The address range must start at a page boundary, and must be a multiple of ; page size in length. If either of these conditions are not true, then ; the call returns "paramErr". ; ; After calling GetPageRange, d1 contains the page number of the first logical page, ; and d2 contains the page count. ; ; Destroys: none ; ; Entry: A0.L = logical start address (must be at the start of a page) ; A1.L = number of bytes (must be a multiple of page size) ; D0.W = 6, selector ; ; Exit: D0.W = error code ; ; Calls: GetPageRange, MMUSetWriteProtect, MMUFlushATC, MMUFlushDataCache ; ;----- WriteProtectProc Proc Export Import GetRealProc,GetPageRange,MMUSetWriteProtect,MMUFlushATC With MemDispGlobals @saveRegs REG d1/d2/a0-a2 @setW EQU (1<<2) ; set Write protect mask (used as a flag) @setWMask EQU $8000 ; mask to set write-protect bit at top of lock count movem.l @saveRegs,-(sp) ; save registers movea.l LockMemCt,a2 ; point to MemoryDispatch globals moveq.l #paramErr,d0 ; assume it won't work move.l mdPageSize(a2),d2 ; get the page size subq.l #1,d2 ; mask for page boundary alignment check move.l a0,d1 ; get the start address and.l d2,d1 ; is the start address page-aligned ? bne.s @error ; start address must be page-aligned move.l a1,d1 ; is the range a multiple of page size ? and.l d2,d1 ; is the range a multiple of page size ? bne.s @error ; range must be a multiple of page size bsr GetPageRange ; check input arguments bne.s @error ; get out @NoFlush lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page moveq.l #@setW,d0 ; flag to MMUSetWriteProtect to write-protect @loop ori.w #@setWMask,(a1)+ ; set the write-protect flag bsr MMUSetWriteProtect ; mark page as write-protected addq.l #1,d1 ; increment page number subq.l #1,d2 ; one less page to go bhi.s @loop ; keep looping moveq.l #noErr,d0 ; no error @error movem.l (sp)+,@saveRegs ; restore registers rts ; EndWith EndProc ;----- ; ; UnWriteProtectProc a88c (_MemoryDispatch Selector 7) ; ; This routine allows write accesses to the address space. ; It also clears the high bit in the lock counter for each page in the range. ; ; The address range must start at a page boundary, and must be a multiple of ; page size in length. If either of these conditions are not true, then ; the call returns "paramErr". ; ; After calling GetPageRange, d1 contains the page number of the first logical page, ; and d2 contains the page count. ; ; Destroys: none ; ; Entry: A0.L = logical start address (must be at the start of a page) ; A1.L = number of bytes (must be a multiple of page size) ; D0.W = 7, selector ; ; Exit: D0.W = error code ; ; Calls: GetPageRange, MMUMakePageNonCacheable, MMUFlushATC, MMUFlushDataCache ; ;----- UnWriteProtectProc Proc Export Import GetPageRange,MMUSetWriteProtect,MMUFlushATC With MemDispGlobals @saveRegs REG d1/d2/a0-a2 @clearW EQU (0<<2) ; clear Write protect mask (used as a flag) @clearWMask EQU $7fff ; mask to clear write-protect bit at top of lock count movem.l @saveRegs,-(sp) ; save registers movea.l LockMemCt,a2 ; point to MemoryDispatch globals moveq.l #paramErr,d0 ; assume it won't work move.l mdPageSize(a2),d2 ; get the page size subq.l #1,d2 ; mask for page boundary alignment check move.l a0,d1 ; get the start address and.l d2,d1 ; is the start address page-aligned ? bne.s @error ; start address must be page-aligned move.l a1,d1 ; is the range a multiple of page size ? and.l d2,d1 ; is the range a multiple of page size ? bne.s @error ; range must be a multiple of page size bsr GetPageRange ; check input arguments bne.s @error ; get out lea.l mdLockTable(a2,d1.l*2),a1 ; point to lock counter for first page moveq.l #@clearW,d0 ; flag to MMUSetWriteProtect to clear write-protect @loop andi.w #@clearWMask,(a1)+ ; clear the write-protect flag bsr MMUSetWriteProtect ; mark page as writeable addq.l #1,d1 ; increment page number subq.l #1,d2 ; one less page to go bhi.s @loop ; keep looping bsr MMUFlushATC ; flush ATC's (to allow writes to previously protected pages) moveq.l #noErr,d0 ; no error @error movem.l (sp)+,@saveRegs ; restore registers rts ; EndWith EndProc ;------------------------------------------------------------------- ; ; InitMemoryDispatch a8e0 ; ; This routine allocates and initializes the MemoryDispatch globals. ; ;------------------------------------------------------------------- InitMemoryDispatch Proc Export With MemDispGlobals @UnimplementedTrap EQU $A89F @MemoryDispatchTrap EQU $A05C @saveRegs REG a0-a3/d0-d4 @localSize EQU -4 ; storage for the TC register @cm0bit EQU 5 ; CM[0] bit in 040 page descriptor link a6,#@localSize ; allocate space for the TC register movem.l @saveRegs,-(sp) ; save registers clr.l LockMemCt ; clear ptr to globals (assume failure) @hasMMU move.b CPUFlag,d1 ; get the CPU type moveq.l #0,d2 ; assume no page size move.l PhysMemTop,d3 ; get actual amount of physical RAM cmpi.b #cpu68040,d1 ; are we on an '040 ? bne.s @not040 ; if not, handle its MMU differently MACHINE MC68040 moveq.l #12,d1 ; assume 4K pages ( 12 = log2(4096) ) movec TC,d0 ; get the TC register btst.l #14,d0 ; are we in 8K page mode ? beq.s @gotPageSize ; if not, we have the page size addq.l #1,d1 ; page size is 8K ( 13 = log2(8192) ) bra.s @gotPageSize ; continue MACHINE MC68030 @not040 cmpi.b #cpu68020,d1 ; are we at least an '020 ? blo.w @noPages ; bail without allocating globals ??? (Use old code ?) cmpi.b #PMMU851,MMUType ; do we have a real MMU ? blo.w @noPages ; bail without allocating globals ??? (Use old code ?) moveq #0,D1 ; clear D1 move.l ([ProcessorInfoPtr],ProcessorInfo.PageSize),D0 ; Get the Page size from the nano-k beq.w @NoPages ; 0 Page size. Can't happen. @countBits asr.l #1,D0 ; Shift bit zero into the carry. bcs.s @gotPageSize ; -> Bail out at the first bit set w/bit # in d1 addq #1,d1 bra.s @countBits ; Keep shifting till we find one @gotPageSize bset.l d1,d2 ; get the page size lsr.l d1,d3 ; get number of page frames move.l d3,d4 ; remember number of page frames move.l d3,d0 ; set up to allocate page lock table asl.l #1,d0 ; each lock counter is a word addi.w #mdGlobalSize,d0 ; size of additional globals move.l d0,d3 ; remember size of globals _NewPtr ,Sys ,Clear ; allocate MemoryDispatch globals bne.w @noPages ; we're dead (bail, or use old code ???) move.l a0,LockMemCt ; save ptr to MemoryDispatch globals move.l d3,mdSize(a0) ; size of entire MemoryDispatch globals move.l d2,mdPageSize(a0) ; save page size move.l d1,mdLog2PageSize(a0) ; save log2 of page size move.l d4,mdPages32(a0) ; save number of logical pages in 32-bit mode move.l d4,mdPageFrames(a0) ; save number of page frames move.l #$800000,d3 ; max of 8MB addressable in 24-bit mode cmp.l PhysMemTop,d3 ; check amount of physical memory blo.s @use8meg ; if physical memory > 8MB, only 8MB available move.l PhysMemTop,d3 ; else use physical memory @use8meg lsr.l d1,d3 ; get number of logical pages in 24-bit mode move.l d3,mdPages24(a0) ; save number of pages in 24-bit mode @noPages movem.l (sp)+,@saveRegs ; restore registers unlk a6 rts EndWith EndProc ;------------------------------------------------------------------- ; GetPageRange a980 - Sanity check on the logical address and count ; ; Destroys: a0/d1/d2 ; ; On entry: ; a0.l = logical address ; a1.l = logical count ; a2.l = ptr to MemoryDispatch globals ; ; On exit: ; d0.w = error code ; d1.l = first page ; d2.l = number of pages in range ; a0.l = clean logical address ; a1.l = logical count (unchanged) ; a2.l = ptr to MemoryDispatch globals (unchanged) ; ;------------------------------------------------------------------- GetPageRange Proc Export With MemDispGlobals @saveRegs REG a1/a2 movem.l @saveRegs,-(sp) ; save registers move.l a0,d0 ; get logical address IF Supports24Bit THEN ; tst.b MMU32Bit ; check if in 32-bit mode bne.s @noStrip ; if 32-bit mode, assume clean address _StripAddress ; clean the address @noStrip ENDIF movea.l d0,a0 ; save clean logical address cmpa.w #0,a1 ; check the count beq.s @error ; if zero count, return paramErr move.l d0,d1 ; copy the start address move.l d0,d2 ; copy the start address add.l a1,d2 ; get end of buffer subq.l #1,d2 ; last = start + count - 1 cmp.l realMemtop,d2 ; check against available RAM bhs.s @error ; if last >= realMemTop, return paramErr move.l mdLog2PageSize(a2),d0 ; get log2 of page size lsr.l d0,d1 ; get page number of start address lsr.l d0,d2 ; get page number of last address sub.l d1,d2 ; page count = lastPage - firstPage + 1 addq.l #1,d2 moveq.l #noErr,d0 ; it worked @exit movem.l (sp)+,@saveRegs ; restore registers rts @error moveq.l #paramErr,d0 ; it failed bra.s @exit EndWith EndProc ;------------------------------------------------------------------- ; MMUSetWriteProtect a9c0 - Set W (Write Protect) bit for a page ; ; Destroys: none. ; ; On entry: d0.l = write protect mask: 0=clear write protect bit ; 4=set write protect bit (bit 2) ; d1.l = logical page number ; a2.l = ptr to MemoryDispatch globals ; ; Calls: GetPageDescProc ; ;------------------------------------------------------------------- MMUSetWriteProtect Proc Export Import GetPageDescProc With MemDispGlobals @saveRegs REG d0-d4/a0/a1 @moreRegs REG d1/a1/a2 @wBit EQU 2 ; write protect bit in all page descriptors movem.l @saveRegs,-(sp) ; save registers move.l d0,d4 ; remember write-protect mask MOVE.L D1,A0 ; Put the page number in A0 _nkGetPTEntryGivenPage ; Get the 030+ PTE from the nk BCLR #@wBit,D0 ; Clear the W bit OR.L D4,D0 ; Clear/set the write-protect flag MOVE.L D0,A0 ; Move the PTE to A0 MOVE.L D1,A1 ; Put the page number in A1 _nkSetPTEntryGivenPage ; Set the 030+ PTE @regDone movem.l (sp)+,@saveRegs ; restore registers @noPages rts EndWith EndProc ;------------------------------------------------------------------- ; MMUSetCacheInhibit a9e0 - Set CI (Cache Inhibit) bit for a page ; ; NOTE: On the 040, it is assumed that bit 5 of the page descriptor (CM[0]) is ; meaningful, since it is used to select write-through/copyback when ; caching is enabled. For this reason, only bit 6 (CM[1]) is set to ; disable caching. This will cause some pages to be marked noncachable ; serialized, and some to be non-serialized. Eventually, we need to ; maintain globally what the overall caching mode is so that the cache ; enabling code can set the CM[1:0] bits appropriately. ; ; Changed to get both page descriptors first, then whack them in 32-bit mode. ; ; Destroys: none. ; ; On entry: d0.l = cache inhibit flag: 0=clear cache inhibit bit(s) ; 1=set cache inhibit bit(s) ; d1.l = logical page number ; a2.l = ptr to MemoryDispatch globals ; ; Calls: GetPageDescProc ;------------------------------------------------------------------- MMUSetCacheInhibit Proc Export Import GetPageDescProc,MMUSetCacheMode With MemDispGlobals @saveRegs REG d0-d4/a0/a1 @moreRegs REG d1/a1/a2 movem.l @saveRegs,-(sp) ; save registers btst.b #7,$240A bne.s @RegDone MOVE.L D1,A0 ; Put the page number in A0 ADDI.W #mmuMakePageCacheable,D0 ; Turn the cache mode flag into a nKernel selector _KernelVMDispatch ; Set the cache status & flush the ATC @RegDone movem.l (sp)+,@saveRegs ; restore registers @noPages rts EndWith EndProc ;------------------------------------------------------------------- ; ; MMUFlushATC aa00 - Flush all entries in the MMU's Address Translation Cache ; ;------------------------------------------------------------------- MMUFlushATC Proc Export rts EndProc END