mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-22 08:30:05 +00:00
1539 lines
54 KiB
Plaintext
1539 lines
54 KiB
Plaintext
;
|
|
; 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):
|
|
;
|
|
; <SM32> 2/7/94 chp Extensive housecleaning in the HwPriv implementations, including
|
|
; the elimination of separate RISC and 68K dispatch tables.
|
|
; <SM31> 12/23/93 PN Take out overpatches on LockMemoryproc, LockMemoryContigousProc
|
|
; and also take out IsUniversal conditionals.
|
|
; <SM30> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
|
|
; machines.
|
|
; <SM29> 11/9/93 KW added some eieioSTP macros. Only expands for CygnusX1 ROM
|
|
; <SM28> 10/14/93 pdw <MC3><MC4>.
|
|
; <MC4> 10/11/93 CCH Separated Edisk protect routine into one for PowerPC and one for
|
|
; 68k.
|
|
; <MC3> 10/10/93 CCH Turned on EDisk support for PowerPC machines.
|
|
; <SM27> 9/13/93 SAM Replaced the alternate dispatch table that was inadvertently
|
|
; removed in the last rev.
|
|
; <SM26> 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.
|
|
; <SM25> 8/19/93 chp Fix the dispatcher so it wonÕt barf on a selector of 13. (BHI ->
|
|
; BHS)
|
|
; <SM24> 8/4/93 GMR <RC> Added code to SlotBlockXferCtl to support block transfers
|
|
; for BART machines (PDM,CF).
|
|
; <SM23> 6/14/93 SAM Reenabled the "DMADispatch" selector for PDM.
|
|
; <SM22> 6/14/93 kc Roll in Ludwig.
|
|
; <LW6> 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.
|
|
; <SM21> 4/22/93 CSS Changed emDMADispGlobs to emDMADispatchGlobals which matches
|
|
; Reality.
|
|
; <SM20> 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.
|
|
; <SM19> 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.
|
|
; <SM18> 3/11/93 SAM Added a refCon field to the PDM DMA irq handler installer.
|
|
; <SM17> 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.
|
|
; <LW3> 2/11/93 PW Added passing of drivers' "don't munge heaps" bit into SCSILoad.
|
|
; <SM15> 2/9/93 rab Sync up with Horror. Comments follow.
|
|
; <H2> 7/13/92 NJV <SES> 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.
|
|
; <SM14> 2/6/93 RC Fixed last fix (sorry)
|
|
; <SM13> 2/6/93 RC Fixed InitMemDispatchTrap for Quadra
|
|
; <SM12> 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.
|
|
; <SM11> 12/11/92 SWC Moved the code to disable the MemoryDispatch trap here from
|
|
; StartInit. Put a hasMDU conditional around the EnableExtCache
|
|
; code.
|
|
; <SM10> 11/3/92 SWC Changed SCSIEqu.a->SCSI.a.
|
|
; <SM9> 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.
|
|
; <SM8> 6/19/92 RB Added the selector for the DMADispatch code.
|
|
; <SM7> 5/17/92 kc Roll in Horror changes. Comments follow.
|
|
; <SM6> 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.
|
|
; <H11> 7/11/91 CCH Fixed a bug in GetPhysical.
|
|
; <H10> 6/27/91 djw (pdw) Add new selector _WaitForSCSIDevs to wait for SCSI devices
|
|
; and load their drivers. Just added nub code here.
|
|
; <H9> 6/14/91 RP Changed length parameter for FlushCacheRange to be passed in A1
|
|
; instead of D1.
|
|
; <H8> 5/10/91 RP Added selector to HwPriv for flush cache range.
|
|
; <H7> 5/10/91 CCH Added selector to HwPriv for Edisk protection.
|
|
; <H6> 2/18/91 JK Added WriteProtect selectors to MemoryDispatch
|
|
; <H5> 1/24/91 JK Added LockMemory calls that use a page-lock table.
|
|
; <H4> 1/24/91 CCH Moved LastEnt label to include new selectors.
|
|
; <H3> 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.
|
|
; <H2> 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 <cache(s)>. 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 <SMN29> 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 <JDR> 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 <xyz>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 = <SCC number>.B <port number>.B <enable/disable ext clock>.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 = <SCC number>.B <port number>.B <last state of external clock>.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 = <external clk value>.w <scc>.b <port>.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. <T2>
|
|
; This to provide support for Sonic onboard Ethernet. <start>
|
|
;
|
|
; To support write-protect, the lock counter behavior has been altered to include <T4>
|
|
; a write-protect bit. The high bit in each lock counter indicates that the page <T4>
|
|
; is write-protected. No count is kept of the number of lock/unlock calls that <T4>
|
|
; have been made. <T4>
|
|
;-----
|
|
|
|
;----------
|
|
;
|
|
; 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 <SM6>
|
|
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 <T6>
|
|
MemDispSelector UnWriteProtectProc ; 7 <T6>
|
|
dc.w badSelect-Vects ; 8 <T6>
|
|
dc.w badSelect-Vects ; 9 <T6>
|
|
LastVec MemDispSelector LockMemoryProc ; 10 <T6>
|
|
|
|
|
|
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 <T2>
|
|
; lock count for the page. <T2>
|
|
;
|
|
; 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 <T4>
|
|
bhi.s @loop ; keep looping <T4>
|
|
|
|
@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 <T2>
|
|
; count is zero, markd the page as cacheable. <T2>
|
|
;
|
|
; 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 <T4>
|
|
bhi.s @lockCheckLoop ; keep looping <T4>
|
|
|
|
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 <T4>
|
|
bhi.s @unlockLoop ; keep looping <T4>
|
|
|
|
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 <T4>
|
|
bhi.s @loop ; keep looping <T4>
|
|
|
|
@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 <v2.1>
|
|
move.l a0,-(sp) ; save pointer to table on stack
|
|
move.l a0,a4 ; get table entry pointer in a4 <T3>
|
|
Move.L A1,D3 ; get table entry number <T3>
|
|
MOVE.L (A4)+,D2 ; get virtual address in d2 <T3>
|
|
@NoSwap
|
|
move.l d2,a0 ; put virtual address in a0 <T3>
|
|
ADD.L (A4),D2 ; get end of buffer <T3>
|
|
CMP.L realMemtop,D2 ; does it exceed available RAM <v1.3>
|
|
BHI.S @BadAddress ; >>EXIT if it exceeds top of RAM <v2.1>
|
|
|
|
BSR.L GetRealProc ; get physical address in a0 <T3>
|
|
BMI.S @BadAddress ; branch if bad address
|
|
|
|
MOVE.L A0,A3 ; save physical address in A3
|
|
MOVE.L D2,A0 ; get end of buffer <T3>
|
|
SUBQ.L #1,A0 ; convert to end address <T3>
|
|
BSR.L GetRealProc ; get physical address in a0 <T3>
|
|
BMI.S @BadAddress ; branch if bad address
|
|
|
|
SUB.L A3,A0 ; calculate distance between addresses <T3>
|
|
ADDQ.L #1,A0 ; convert to byte count <T3>
|
|
CMP.L (A4),A0 ; are they the same size <T3>
|
|
BNE.S @NonContig ; branch, if memory is not contiguous
|
|
|
|
TST.L d3 ; d3 = 0?? <T3>
|
|
BEQ.S @return1 ; branch, if yes
|
|
MOVE.L (A4)+,D0 ; save buffer size <T3>
|
|
ADD.L D0,VAddr(A4) ; update virtual address <T3>
|
|
MOVE.L #0,BuffSize(A4) ; update buffer size <T3>
|
|
MOVE.L A3,(A4)+ ; save physcial address in table <T3>
|
|
MOVE.L D0,(A4) ; save size in table <T3>
|
|
@return1
|
|
MOVE.L #1,A0 ; return with 1 entry <v1.3>
|
|
MOVE.W #0,D2 ; and with no error
|
|
@GPEXit
|
|
MOVE.L D2,D0 ; set final error code <v1.6>
|
|
MOVE.L (SP)+,A1 ; restore pointer <v1.3>
|
|
MOVEM.L (SP)+,GetPhysRegs ; restore registers <v2.1>
|
|
RTS
|
|
@BadAddress
|
|
MOVEQ #0,A0 ; when error, return zero entry <v1.3>
|
|
MOVE.W #paramErr,D2 ; return paramErr
|
|
BRA.S @GPExit
|
|
|
|
@NonContig
|
|
MOVE.L (SP),A4 ; A0 gets pointer to table <T3>
|
|
MOVE.L (A4),A0 ; get logical address in A0 <v2.1>
|
|
|
|
ADD.L #8,A4 ; A4 = points to table entry
|
|
MOVE.L D3,D1 ; D1 = number of table entry or 0 <T11>
|
|
BSR ChkContig ; check contiguous physical
|
|
TST.W D2 ; are there error
|
|
BMI.S @BadAddress
|
|
MOVE.L D1,A0 ; get number of entries in A0 <v1.3>
|
|
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 <v2.1>
|
|
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 <T3>
|
|
MOVE.L Buffsize(a4),OSize(A6) ; save original size <T3>
|
|
|
|
BSR.L GetRealProc ; convert addr in a0 to physical addr <T3>
|
|
BMI @BadAddress ; branch if bad address
|
|
|
|
MOVE.L A0,PhysAddr(A6) ; save physical address <LW7>
|
|
|
|
MOVE.L LockMemCt,A2 ; point to MemoryDispatch globals <LW7>
|
|
move.l mdPageSize(A2),D2 ; point to MemoryDispatch globals
|
|
; Removed a ¥Gestalt¥ call to get the page size! Sheeze! <SM17>
|
|
|
|
; to calculate amount of memory in the first page
|
|
SUBQ #1,d2 ; create mask to get bytes in 1st page <T3>
|
|
MOVE.L PhysAddr(A6),D3 ; get physical address <T11>
|
|
NEG.L D3 ; negate the address <T11>
|
|
AND.L D3,D2 ; get remaining bytes in first page <T11>
|
|
|
|
MOVE.L D2,ContigSize(A6) ; save memory size
|
|
MOVE.L OVaddr(A6),A3 ; get original logical address <T11>
|
|
ADD.L D2,A3 ; get logical address on page boundary <T11>
|
|
@loop
|
|
MOVE.L A3,A0 ; get logical address into A0 <T11>
|
|
BSR.L GetRealProc ; convert addr in A0 to physical addr <T3>
|
|
BMI @BadAddress ; branch if bad address
|
|
|
|
MOVE.L LockMemCt,A2 ; restore A2,points toMemoryDispatch globals <LW7>
|
|
|
|
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<T3>
|
|
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 <SM17>
|
|
CMP.L BuffSize(a4),D3 ; is it end yet? <T3>
|
|
BCC.S @Done ; yes, branch
|
|
MOVE.L D3,ContigSize(A6) ; update contiguous size
|
|
ADD.L mdPageSize(a2),A3 ; get new virtual address <T11><SM17>
|
|
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 <T3>
|
|
MOVE.L ContigSize(A6),(4,a4,D3.L*8); store contiguous size <T3>
|
|
|
|
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 <T3>
|
|
SUB.L D3,BuffSize(a4) ; update buffer size <T3>
|
|
|
|
Move.L A0,PhysAddr(A6) ; update new physical address <T11>
|
|
|
|
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 <T3>
|
|
MOVE.L OSize(A6),BuffSize(a4) ; restore original size <T3>
|
|
BRA.S @ExitB
|
|
@GetResult
|
|
MOVE.L EntryIndex(A6),D3 ; get entry index
|
|
MOVE.L PhysAddr(A6),(0,a4,D3.L*8) ; store physical address <T3>
|
|
MOVE.L BuffSize(a4),(4,a4,D3.L*8) ; store size <T3>
|
|
MOVE.L BuffSize(a4),D2 ; save remaining buffsize <T3>
|
|
Add.L D2,VAddr(a4) ; update virtual address <T3>
|
|
MOVE.L #0,BuffSize(a4) ; indicate complete translation <T3>
|
|
AddQ.L #1,D3 ; convert index to entry count
|
|
@ExitA
|
|
MOVE.L D3,D1 ; return entry count
|
|
@ExitB
|
|
MOVEQ #0,D2 ; no error <v1.6>
|
|
@ExitC
|
|
MOVEM.L (SP)+,D3-D7 ; restore registers <v2.1>
|
|
UNLK A6
|
|
ENDWITH
|
|
RTS
|
|
@BadAddress
|
|
MOVE.W #-1,D2 ; return paramErr <v1.6>
|
|
BRA.S @ExitC
|
|
|
|
EndWith
|
|
EndProc
|
|
|
|
|
|
;-----
|
|
;
|
|
; WriteProtectProc a850 (_MemoryDispatch Selector 6) <T4>
|
|
; <start>
|
|
; 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 <end>
|
|
rts ; <T4>
|
|
EndWith
|
|
EndProc
|
|
|
|
;-----
|
|
;
|
|
; UnWriteProtectProc a88c (_MemoryDispatch Selector 7) <T4>
|
|
; <start>
|
|
; 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 <end>
|
|
rts ; <T4>
|
|
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. <SM17>
|
|
@countBits asr.l #1,D0 ; Shift bit zero into the carry. <SM17>
|
|
bcs.s @gotPageSize ; -> Bail out at the first bit set w/bit # in d1 <SM17>
|
|
addq #1,d1
|
|
bra.s @countBits ; Keep shifting till we find one <SM17>
|
|
|
|
@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 ; <SM17>
|
|
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 <T4>
|
|
; <start>
|
|
; 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 <T4>
|
|
@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. <T4>
|
|
;
|
|
; 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
|