mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
2737 lines
119 KiB
Plaintext
2737 lines
119 KiB
Plaintext
;
|
||
; File: SizeMem.a
|
||
;
|
||
; Written by: Gary Rensberger
|
||
;
|
||
; Copyright: © 1989-1993 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM49> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
|
||
; machines.
|
||
; <SM48> 11/19/93 KW copied HMCMerge EDisk calculations and put in OrwellMerge. Only
|
||
; effects the CygnusX1 ROM
|
||
; <SM47> 11/17/93 chp Put back TNT code inadvertantly removed by a previous checkin.
|
||
; <SM46> 11/17/93 KW added some forSTP601 conditionals. Only effects CygnusX1 ROM
|
||
; <SM45> 11/13/93 SAM Roll in <MC10> from mc900ftjesus.
|
||
; <MC10> 11/13/93 SAM In the EDisk calculation from the previous revision, I was not
|
||
; anticipating the result going negative. It does. I now check for
|
||
; it.; <SM44> 11/12/93 SAM Roll in <MC9> from mc900ftjesus.
|
||
; <MC9> 11/12/93 SAM When allocating an EDisk, make sure there is KminHeap (or
|
||
; somesuch) free or don't allocate. The ammount of RAM
|
||
; allocated for the edisk is stored beyond the diagnostic longs at
|
||
; the end of the chunk table. InitMMU uses this size for eMMU
|
||
; machines.
|
||
; <SMG2> 11/9/93 fau Added the TNT Decoder support (HammerHead)
|
||
; <SM42> 11/9/93 KW added some conditional forSTP601. Only used for CygnusX1 ROM
|
||
; <SM41> 11/7/93 SAM Roll in <MC8> from mc900ftjesus.
|
||
; <MC8> 11/7/93 SAM Keep a running total of RAM allocated by the nanokernel in the
|
||
; chunk table.
|
||
; <SM40> 11/6/93 SAM Roll in <MC7> from mc900ftjesus.
|
||
; <MC7> 11/6/93 SAM Disable Sonora video before mucking with the NanoKernel memory
|
||
; allocation.
|
||
; <SM39> 11/1/93 SAM Roll in <MC6> from mc900ftjesus.
|
||
; <MC6> 11/1/93 SAM (RC) HMCMerge now checks PRAM for the diag burn-in sig as well
|
||
; as reading the monitor sense lines for the RBV to determine if a
|
||
; DRAM based frame buffer should be allocated.
|
||
; <SM38> 10/16/93 SAM Roll in <MC5> from mc900ftjesus.
|
||
; <MC5> 10/16/93 SAM Add some slop to the RBV buffer for PDM to account for QD
|
||
; writing past the end of the buffer. (Doesn't this seem like a
|
||
; problem to you? Does to me...)
|
||
; <SM37> 10/15/93 SAM Roll in <MC4> from mc900ftjesus.
|
||
; <MC4> 10/15/93 SAM Ok, I fixed the boot beep code, so the RBV size is now set to a
|
||
; max of 600k (not 768). Removed the 3 extra longs allocated in
|
||
; the chunk table (for debugging).
|
||
; <SM36> 9/29/93 SAM For PDM: from mc900ftjesus.
|
||
; <MC3> 9/25/93 SAM For PDM: Loose Evt1 support.
|
||
; <SM35> 9/13/93 SAM For PDM (HMC): Removed the Edisk hack for the nanokernel.
|
||
; Marked all the DMA buffers noncacheable.
|
||
; <SM34> 9/9/93 pdw Added 'nk' onto front of MakePageWriteThrough.
|
||
; <SM33> 8/23/93 SAM Added a temp hack to increase the amount of RAM allocated for
|
||
; the RAM disk by 1 page (nk bug)
|
||
; <SM32> 8/23/93 SAM Changed the alignment restriction for the EDisk allocation to be
|
||
; 4k.
|
||
; <SM31> 8/23/93 SAM Added some space in the HMC chunk table for a couple of
|
||
; warmstart longs.
|
||
; <SM30> 8/12/93 KW adding two more smurf wombats
|
||
; <SM29> 8/11/93 KW added some branches based on new smurf boxes
|
||
; <SM28> 6/14/93 kc Roll in Ludwig.
|
||
; <LW4> 6/4/93 fau In sizing memory in Cyclone, there was a bug when a Wide Mode
|
||
; SIMM was in bank 5, no SIMM in bank 7, and a Standard Mode SIMM
|
||
; in Bank 0. Bug #1088829.
|
||
; <SM27> 6/3/93 SAM For HMC machines (PDM) if an evt2 or better is found, the floppy
|
||
; and serial DMA buffers are marked noncacheable in order fix a
|
||
; data path snooping during DMA bug.
|
||
; <SM26> 5/9/93 SAM Added a couple lines of crucial code to the PDM physical buffer
|
||
; allocation code. Grin.
|
||
; <SM25> 5/6/93 SAM For PDM. Changed the HMC entry in the sizemem "split" table to
|
||
; point directly at the HMCMerge routine (we don't have to size
|
||
; anything, really). Addded allocation of the DMA and video frame
|
||
; physical buffers to HMCMerge. Added code to make the frame
|
||
; buffer write-through cacheable.
|
||
; <SM24> 4/30/93 SAM Removed non-functional non-universal forRomulator code in
|
||
; SizeBanks (<LW2>). Added one more forSmurf condo.
|
||
; <SM23> 4/19/93 SAM Added forSmurf conditionals around RiscWombat boxflag check
|
||
; (ugh).
|
||
; <SM22> 3/31/93 chp Synchronize SuperMario with changes from <LW2>.
|
||
; <SM21> 3/11/93 SAM Added EDisk allocation to HMC merge code.
|
||
; <LW2> 2/26/93 fau Removed Cyclone EVT3 (MMC) support.
|
||
; <SM20> 2/25/93 RC Fixed Merge code for Smurf. Old code did not do what we thought
|
||
; it did, but now it correctly sizes memory by using the same code
|
||
; and PDM uses.
|
||
; <SM19> 2/20/93 SAM Added emuWarmStartConst to the chunk table build for HMC
|
||
; machines.
|
||
; <SM18> 2/5/93 SAM Added HMC "merge" code that conconcts a fake chunk table and
|
||
; generally does the right thing. (for PDM).
|
||
; <SM17> 12/23/92 RC Added Support for Smurf
|
||
; <SM16> 12/1/92 EH Changed PrattAddr reference to DecoderAddr reference for
|
||
; PrattMerge.
|
||
; <SM15> 12/1/92 EH Added code for Pratt memory controller.
|
||
; <SM14> 11/12/92 rab Added djMEMCSplit to the split table (had added the code but
|
||
; forgot the entry). Also exported SizeSoundBuffer for MMUTable.a.
|
||
; <SM13> 11/10/92 GD Fixed some "forRomulator" issues from latest Horror roll-in.
|
||
; <SM12> 11/3/92 rab Roll in Horror changes. <H16>10/13/92 BG Modified various
|
||
; comments in the djMEMCSplit code to indicate that both WLCD and
|
||
; Primus need to set the OneBufferedBus bit. <H15> 9/28/92 BG
|
||
; Changed the djMEMCMerge code so that if you are trying to create
|
||
; a ReAnimator type ROM, don't turn on memory interleaving. <H14>
|
||
; 8/4/92 SWC Fixed a bug in MSCMerge: we were only allocating
|
||
; enough space for 5 RAM banks (we support 8), so the end of the
|
||
; RAM chunk table was going into write-only RAM.
|
||
; <H13> 7/13/92 SWC Added some code to the end of MergeDone to move the RAM chunk
|
||
; table below a sound buffer in high RAM. This was moved here from
|
||
; MMUTables.a because (1) since the chunk table was moved down
|
||
; after running StartTest, we'd lose the warmstart flag (causes
|
||
; the RAM disk to get trashed on Restart, and (2) diagnostics seem
|
||
; to call SizeMem in several places, so I figured it was better to
|
||
; get everything set up once.
|
||
; <H10> 6/16/92 BG Added back in the interleave initialization for djMEMC.
|
||
; However, a precursor check has been added to only allow that
|
||
; code to be executed if the version number of djMEMC is greater
|
||
; than 0, since version 0 parts will cause Wombat/WLCD to die
|
||
; shortly after enabling interleaving.
|
||
; <H8> 6/12/92 BG Added support for sizing up to 16 banks of memory. This is
|
||
; needed because Wombat can support up to 10 banks. Also - removed
|
||
; the djMEMC configuration register initialization from here and
|
||
; moved it to UniversalPatch.a so that it is not executed multiple
|
||
; times (since SizeMemory gets called multiple times).
|
||
; <H7> 6/9/92 BG Added djMEMC memory controller to split and merge tables, as
|
||
; well as the split and merge code. However, changes to SizeBanks
|
||
; are also required that have not been fully tested on all
|
||
; machines yet, so that did _not_ get rolled in.
|
||
; <H6> 5/20/92 NJV Fixed register-trashing bug in SonoraMerge.
|
||
; <H5> 5/19/92 SWC Modified @MSCSplit and MSCMerge to temporarily support both MSC2
|
||
; and MSC3 while we make the transition.
|
||
; <H4> 5/12/92 HY Roll-in LC II changes. Change the sizing routine for VISA
|
||
; decoders to support 2 or 4MB on PCB.
|
||
; <H3> 5/4/92 JC Change Sonora split so that Bank 0 has 4 Megs of RAM installed.
|
||
; <H2> 4/13/92 JC Remove references to SonoraAddr (is going away) and replaced
|
||
; with references to RBVAddr for Sonora based machines.
|
||
; <SM11> 10/22/92 fau Added support for the YMCA Decoder in standard and wide mode.
|
||
; This involved adding a new YMCASize banks. Added a check to
|
||
; SizeBank to make sure we didn't spin forever if the ram bank end
|
||
; is not a multiple of 2^(n-1) * chunksize. (This will occur when
|
||
; sizing wide memory as standard memory). Also, changed the use
|
||
; of MMC/YMCAExists and MMC/YMCAAddr to use the decoder info.
|
||
; <SM10> 10/18/92 CCH Added support for HMC decoder.
|
||
; <SM9> 9/30/92 fau Incorporated support for the YMCA decoder that is found in
|
||
; Cyclone EVT4. This included the YMCA split routine and the
|
||
; YMCAMerge routine. Left the support for the MMC in there.
|
||
; Eventually, the MMC (used in previous Cyclone EVT's, should go
|
||
; away.)
|
||
; <SM8> 8/19/92 CSS Update from Reality:
|
||
; <23> 8/18/92 DTY Change the name of BootGlobs to StartGlobals to avoid confusion
|
||
; with BootGlobals, which is used by the boot code in Boot[1-3].a.
|
||
; <SM7> 8/17/92 CCH Changed orwell stitch code to use DecoderAddr field instead of
|
||
; OrwellAddr.
|
||
; <SM6> 8/11/92 kc Don't split memory while running the ROM image in RAM on
|
||
; Cyclone. Use A3 instead of A7 in SizeMem to make ReAnimator
|
||
; happy.
|
||
; <SM5> 8/9/92 CCH Don't attempt to stitch memory when running on a RISC processor
|
||
; in a Quadra.
|
||
; <SM4> 7/13/92 CCH Added conditionalized support for Cub Card on Quadras.
|
||
; <SM3> 5/25/92 RB Making Cyclone changes...Pandora/Horror comments follow: <P4>
|
||
; 5/13/92 KW (HV,H4) Roll-in LC II changes. Change the sizing
|
||
; routine for VISA decoders to support 2 or 4MB on PCB. (JC,H3)
|
||
; Change Sonora split so that Bank 0 has 4 Megs of RAM installed.
|
||
; <P2> 3/4/92 RMP Changed MMCMerge to configure Bank B correctly.
|
||
; <H5> 5/19/92 SWC Modified @MSCSplit and MSCMerge to temporarily
|
||
; support both MSC2 and MSC3 while we make the transition.
|
||
; <SM2> 5/16/92 kc Roll in Horror and Terror Changes. Comments follow:
|
||
; <H13> 01/27/92 jmp The original contents of this file have been moved to the
|
||
; SizeMemPatch.a file.
|
||
; <H9> 12/9/91 SAM Added a read to ROM in SizeBank between the RAM write and compare
|
||
; to prevent a floating bus from fooling us into thinking that
|
||
; there are 4 gigabytes of RAM built-in.
|
||
; <H7> 12/5/91 SAM Removing all special cases for built-in RAM for Vail machines
|
||
; cuz the hardware folks decided that their klude was a kludge.
|
||
; <H5> 12/3/91 SAM Changed Sonora split/merge code to use the new SonoraVIA2
|
||
; base address equate.
|
||
; <H4> 11/25/91 SAM First attempt at the Sonora sitch routine for Vail and
|
||
; Carnation.
|
||
; <H3> 10/22/91 SWC Changed MSCAddr references to RBVAddr since MSC is just a
|
||
; variant of the RBV.
|
||
; <H2> 8/5/91 SWC Added a fix to MSCMerge so that it works correctly if all RAM
|
||
; banks are not filled.
|
||
; <T9> 6/21/91 BG Swapped the order of the case table in SizeMemory to match the
|
||
; (new) order of the DecoderKinds table in UniversalEqu.a.
|
||
; <T7> 5/1/91 HJR SWC - Added support for the MSC for DB-Lite.
|
||
; <T4> 11/7/90 BG Made changes for new rev. of Orwell (2) permanent.
|
||
; <22> 12/29/91 RB Added Terror changes.
|
||
; <21> 9/16/91 JSM Cleanup header.
|
||
; <20> 6/12/91 LN removed #include 'HardwareEqu.a'
|
||
; <19> 3/5/91 dba put in an align directive so that we donÕt get a warning
|
||
; <18> 3/5/91 PN Fix the warning by putting the END statement at the end
|
||
; <17> 9/24/90 GMR Added special case to JAWS merge code to deal with 2 meg bank A,
|
||
; 0 meg bank B and vice versa when the 2 meg is in a single chunk
|
||
; (as in TIM).
|
||
; <16> 9/19/90 BG Removed 040-related kludges (EclipseNOPs).
|
||
; <15> 8/2/90 CCH Clear D6 error flag after chunk table is written.
|
||
; <14> 7/10/90 CCH Fixed bug in orwell merge, and modified it to create a separate
|
||
; chunk table entry for each chunk listed in universal.a.
|
||
; <13> 5/10/90 GMR Preserved reg d2 inside FMCMerge.
|
||
; <12> 5/3/90 GMR Fixed file contents- ROMLister corrupted the file before
|
||
; check-in.
|
||
; <11> 5/3/90 GMR The chunk table now contains separate, contiguous chunks for
|
||
; each bank of RAM.
|
||
; <10> 4/25/90 GMR Made previous change save register A4, as before.
|
||
; <9> 4/21/90 GMR Moved ConfigureRAM functionality from StartInit.a to this file,
|
||
; to fix problems associated with writing the chunk table before
|
||
; the memory is stitched together. The sizing code now can size up
|
||
; to 8 banks before storing the info in the chunk table. Added
|
||
; Waimea splitting/stitching code to deal with it's 8 banks of
|
||
; RAM.
|
||
; <8> 4/2/90 JJ Correct memory address used to distinguish between Elsies with 1
|
||
; MB vs 2 MB on main logic board.
|
||
; <7> 3/23/90 JJ Added code to handle Elsie VISA 2 setting of size bits.
|
||
; <6> 2/28/90 JJ Added code to initialize memory size bits for machines with VISA
|
||
; decoders.
|
||
; <5> 2/21/90 BG The Orwell configuration code needed a small bit of tweaking.
|
||
; <4> 2/16/90 BG Added code to initialize Orwell bank addresses to the known
|
||
; default power-on state.
|
||
; <3> 1/11/90 CCH Added include of ÒHardwarePrivateEqu.aÓ.
|
||
; <2.9> 10/9/89 GMR NEEDED FOR ZONE5: Return bit mask for bad byte lanes, supporting
|
||
; up to 8 banks of 4 byte lanes each. Initialize FMC to put bank B
|
||
; on 64 Meg boundary.
|
||
; <2.8> 6/30/89 GMR Put FF's on bus between byte compare write/read cycles, to
|
||
; eliminate stray capacitance problems when no RAM present on
|
||
; access.
|
||
; <2.7> 6/26/89 GMR Changed to exit with a real stack pointer near low memory, top
|
||
; element on stack contains pointer to memory chunk table at top
|
||
; of last bank.
|
||
; <2.6> 6/11/89 GGD Converted to use RamInfo in rom tables.
|
||
; <2.5> 6/11/89 GMR Changed call to GetHardwareInfo to be a BigBSR6 so it'll reach.
|
||
; <2.4> 5/30/89 GMR Added comment describing error code returned in D6
|
||
; <2.3> 5/26/89 GMR Return error, instead of ignoring bank, if only some SIMMs in a
|
||
; bank are present. This should make Service happy.
|
||
; <2.2> 5/26/89 rwh changed to new improved BootGlobs field names.
|
||
; <2.1> 5/22/89 GMR Corrected prep of d2 before GetHardwareInfo call, optimized a
|
||
; few things, terminated tables with 1 long instead of 2 longs.
|
||
; <2.0> 5/16/89 GMR Rewrote entire file, returning a7 pointing to table of bank
|
||
; entries (start,length,...,$FFFF) on all machines. It's now
|
||
; non-destructive.
|
||
; ---------------Below doesn't apply now---------------
|
||
;==============================================================================================
|
||
; <1.9> 4/28/89 rle check startup code (now in d5) upon entry to determine if stack
|
||
; is valid or memory needs to be tested
|
||
; <1.8> 3/28/89 SES Cleaned up code to run a bit more efficiently. Added an initial
|
||
; browse through memory so that we can run out of Bank B only for
|
||
; HafMac.
|
||
; <1.7> 3/7/89 SES Added code to check for warm start and PwrMgr reset before
|
||
; running Ram test.
|
||
; <1.6> 2/24/89 SES Added code to ensure screen is clean for RBV-based machines.
|
||
; <1.5> 2/23/89 SES Mixed conditional for EXPORT BankASize to reflect what's in the
|
||
; body of routine.
|
||
; <1.4> 2/22/89 SES Added non-destructive code back in. Added check for startup or
|
||
; entry from booted system. Changed stack and table setup to be a
|
||
; bit more flexible. Still need to add a search for where first
|
||
; RAM is.
|
||
; <1.3> 2/16/89 rwh Added support for Fitch Memory Controller rev 1. When FMC2
|
||
; arrives, may need to change these for a contiguous physical
|
||
; memory model. Removed MvMac hack in SizeMem.
|
||
; <1.2> 2/16/89 SES Removed non-destructive code because restored values end up
|
||
; writing via wrap into locations that haven't been checked yet.
|
||
; <1.1> 2/15/89 SES Fixed routine so that it is non-destructive. On exit, stack will
|
||
; be set to the top of tested memory.
|
||
; <1.0> 2/13/89 SES Adding to EASE for the first time.
|
||
;
|
||
;_____________________________________________________________________________________________
|
||
|
||
PRINT OFF
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
INCLUDE 'STEqu.a'
|
||
INCLUDE 'MmuEqu.a'
|
||
INCLUDE 'BootEqu.a'
|
||
INCLUDE 'EDiskEqu.a'
|
||
INCLUDE 'DepVideoEqu.a'
|
||
PRINT ON
|
||
STRING ASIS
|
||
|
||
PROC
|
||
|
||
IMPORT GetHardwareInfo, RdXByte,RamInfoPrattFlash
|
||
EXPORT SizeMemory
|
||
EXPORT SizeSoundBuffer ; <SM14>
|
||
MACHINE MC68020
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: SizeMemory
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: a7 - initialized stack pointer (if RAM found), top element points to
|
||
; memory table of size blocks found.
|
||
; d6 - result code, 1 nibble/bank, 1 bit set for each SIMM bad in bank:
|
||
; = 00000000 if RAM sized ok
|
||
; = 00000001 if SIMM 0 in bank A is bad
|
||
; = 0000000F if SIMMs 0,1,2,3 in bank A are bad
|
||
; = 00000020 if SIMM 1 in bank B is bad
|
||
;
|
||
; NOTE!! D6 only holds error information for the first 8 banks! <H8>
|
||
;
|
||
; Uses: a0 - Ptr to table of base addresses
|
||
; a1 - Ptr to product info record
|
||
; d0
|
||
;
|
||
; Destroys: d0-d5,a0-a3,a5
|
||
;
|
||
; This file contains the universal size memory routine, which sizes memory banks
|
||
; for all machines and returns a table of start/size records for each bank found.
|
||
; It assumes data cache is off, and no MMU translation.
|
||
; The table is located at the top of the last bank of RAM found, and the entries
|
||
; have the following format:
|
||
;
|
||
; A7 --> (pointer to chunk table) -----
|
||
; |
|
||
; |
|
||
; ChunkTable: start.L,length.L { bank A } <----
|
||
; start.L,length.L { bank B }
|
||
; ... { bank n }
|
||
; $FFFFFFFF
|
||
;_____________________________________________________________________________________________
|
||
WITH DecoderInfo,DecoderKinds,StartGlobals, RAMBankInfo ; <SM3> rb <SM8> CSS
|
||
|
||
SizeMemory
|
||
move.l a6,d3 ; save return address
|
||
|
||
moveq #0,d2 ; don't know anything about machine
|
||
BigBSR6 GetHardwareInfo,a0
|
||
move.l d3,a2 ; now keep return address in a2
|
||
|
||
moveq #0,d3 ; clear a reg
|
||
move.b d2,d3 ; get memory controller type
|
||
add.w d3,d3 ; adjust for word table index
|
||
move.w @splitTbl(d3.w),d3 ; get offset to splitter routine
|
||
jmp @splitTbl(d3.w) ; SWITCH(controller type)
|
||
|
||
@splitTbl
|
||
|
||
; This table should match the DecoderKinds record in UniversalEqu.a
|
||
|
||
dc.w SizeBanks -@splitTbl ; unknown
|
||
dc.w SizeBanks -@splitTbl ; Mac Pal (no splitting required)
|
||
dc.w SizeBanks -@splitTbl ; BBU (no splitting required)
|
||
dc.w SizeBanks -@splitTbl ; Normandy (no splitting required)
|
||
dc.w @GlueSplit -@splitTbl ; Mac2Glue
|
||
dc.w SizeBanks -@splitTbl ; MDU (no splitting required)
|
||
dc.w @FMCSplit -@splitTbl ; OSS FMC
|
||
dc.w @VisaSplit -@splitTbl ; VISA <T9>
|
||
dc.w @OrwellSplit -@splitTbl ; Orwell <T9>
|
||
dc.w @JAWSSplit -@splitTbl ; JAWS
|
||
dc.w @MSCSplit -@splitTbl ; MSC <7> HJR
|
||
dc.w @SonoraSplit -@splitTbl ; Sonora <H4> SAM
|
||
dc.w @NiagraSplit -@splitTbl ; Niagra <xxx>
|
||
dc.w @YMCASplit -@splitTbl ; Cyclone EVT4 <SM9> fau
|
||
dc.w @djMEMCSplit -@splitTbl ; djMEMc <SM10><SM14>
|
||
dc.w HMCMerge -@splitTbl ; HMC (Go directly to the merge routine) <SM25> <SM10>
|
||
dc.w @PrattSplit -@splitTbl ; Pratt <SM15>
|
||
dc.w HHeadMerge -@splitTbl ; HHead (Go directly to the merge routine) <SM10>
|
||
|
||
Align 4
|
||
;_____________________________________________________________________________________________
|
||
@GlueSplit
|
||
move.l VIA2Addr(a0),a5 ; Yes, get VIA2 base
|
||
ori.b #$C0,VBufA(a5) ; put bank B on 64 meg boundary
|
||
bra SizeBanks ; continue with sizing
|
||
|
||
;_____________________________________________________________________________________________
|
||
@FMCSplit
|
||
movea.l FMCAddr(a0),a5 ; get the FMC base address
|
||
move.w #FMCInit,d2 ; config reg value to put bank B on 64 meg boundary
|
||
moveq.l #16-1,d3 ; loop counter to load 16 bits
|
||
@FMCload move.b d2,FMCConfig(a5) ; load in a bit
|
||
lsr.w #1,d2 ; put next bit into position
|
||
dbra d3,@FMCload ; repeat till all bits loaded
|
||
move.b d2,FMCLatch(a5) ; latch the config data
|
||
bra SizeBanks ; continue with sizing
|
||
|
||
;_____________________________________________________________________________________________
|
||
;
|
||
; Make sure that the 4 banks are split apart onto their default 64MB boundaries.
|
||
; No other changes to the Orwell configuration register are needed because they
|
||
; have been set up in Universal.a and shouldn't require any changes or reconfiguration.
|
||
; See {IntAIncludes}HardwarePrivateEqu.a for a full description of this register.
|
||
;_____________________________________________________________________________________________
|
||
WITH ProductInfo
|
||
|
||
@OrwellSplit
|
||
IF forSTP601 THEN
|
||
bra OrwellMerge ; sized memory in HardwareInit.s <SM46>
|
||
ENDIF
|
||
|
||
IF forSmurf THEN ; <SM24> SAM
|
||
cmp.b #boxRiscQuadra700,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM42>
|
||
cmp.b #boxRiscQuadra900,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM42>
|
||
cmp.b #boxRiscQuadra950,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM29>
|
||
ENDIF
|
||
; Eclipse/040 Memory Controller INIT <4>
|
||
movea.l DecoderAddr(a0),a5 ; get base address of Orwell regs <SM7>
|
||
lea OrBankBCfgAddr(a5),a0 ; get address of config regs.
|
||
move.l #((ORINITBankB)|\ ; get default bank-split values <T6>
|
||
(ORINITBankC<<OrBankFieldSize)|\; <T6>
|
||
(ORINITBankD<<2*OrBankFieldSize)),d3; <T6>
|
||
moveq.l #(3*OrBankFieldSize)-1,d2 ; (18-1) -1 for DBRA, <T3><T4><T6>
|
||
|
||
@OrwellLoad move.l d3,(a0)+ ; send that bit out there
|
||
lsr.l #1,d3 ; get the next bit in position
|
||
dbra d2,@OrwellLoad ; repeat til all bits loaded <T2>
|
||
|
||
move.l d2,OrLoadBanks(a5) ; initialize DRAM bank starting addrs <T2>
|
||
;
|
||
bra SizeBanks ; continue with sizing
|
||
|
||
;_____________________________________________________________________________________________
|
||
@VisaSplit
|
||
move.l RBVAddr(a0),a5 ; Yes, get VISA base <6><SM4> rb, start
|
||
andi.b #%00011111,VsExp(a5) ; clear size bits. Bits now set to 4MB on PCB <H5><Begin>
|
||
; and no memory in SIMMs
|
||
movea.l #$001FFFFE,a0 ; Figure out whether we have 2/4mb on PCB by
|
||
; writing to 2/3 MB boundary.
|
||
move.l #$50616E44,(a0) ; Write a long word. Low then high byte is written out to bus
|
||
cmp.l #$50616E44,(a0) ; If what we wrote is what we get back then we have 4MB on PCB.
|
||
bne.s @got2MB
|
||
ori.b #%11000000,VsExp(a5) ; push RAM on PCB up to 8MB boundary so we can check how much RAM in SIMMs
|
||
|
||
;¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
|
||
; At this point we've determined that there is 4MB on PCB. We must now figure out how much
|
||
; RAM is in the SIMM sockets before going on any further. If we have 8Mb in SIMMs then the
|
||
; size bits are set correctly (we then lose 2Mb of on board memory), but if we have less than
|
||
; 8Mb the size bits are incorrect and if left this way the on board memory will not be sized
|
||
; correctly by the routines that follow and the chunk table will be wrong.
|
||
|
||
move.l a5,a7 ; save ptr to VISA base address in a7
|
||
move.l a1,a5 ; get product info ptr
|
||
adda.l ProductInfo.RamInfoPtr(a5),a5
|
||
adda.l #RAMInfoSize+4,a5 ; '+4' taking into account the end of table mark
|
||
move.l #0,a0 ; start of bank A
|
||
move.l #$00800000,a1 ; end of bank A
|
||
move.l #0,d0 ; no previous banks sized
|
||
move.l #$54696e61,d1 ; setup signature
|
||
move.l #0,d5 ; clear bank size nibbles
|
||
BSR6 SizeBank ; how much memory do we have in Bank A?
|
||
cmp.l #$00800000,a0 ; SizeBank returns amount of RAM found in A0
|
||
|
||
blt.s @notMaxMem ; if less than 8mb found then reset size bits and RAM ranges
|
||
|
||
sub.l #RAMInfoSize+4,a5
|
||
bra continue
|
||
@notMaxMem
|
||
ori.b #%10000000,VsExp(a7)
|
||
andi.b #%10011111,VsExp(a7) ; set Bank A to 4mb, since this is the next size if not 8mb
|
||
bra continue
|
||
@got2MB
|
||
ori.b #%11100000,VsExp(a5) ; set size bits to 10mb (i.e. 2mb on PCB and 8mb in SIMMs)
|
||
; we set Bank A to 8Mb so PCB RAM is pushed out of the way
|
||
; so we can then get an accurate reading of Bank A RAM. <SM4> rb, end <H5><End>
|
||
bra SizeBanks ; and continue with sizing
|
||
|
||
ENDWITH
|
||
;_____________________________________________________________________________________________
|
||
@NiagraSplit
|
||
@JAWSSplit
|
||
moveq #0,d0
|
||
movea.l JAWSAddr(a0),a5 ; get ptr to JAWS base
|
||
adda.l #JAWSMemConfigA,a5
|
||
move.b d0,(a5) ; set size reg A
|
||
adda.w #JAWSMemConfigB-JAWSMemConfigA,a5
|
||
move.b d0,(a5) ; set size reg B
|
||
adda.w #JAWSMemConfigC-JAWSMemConfigB,a5
|
||
move.b d0,(a5) ; set size reg C
|
||
bra SizeBanks ; and continue with sizing <22> rb
|
||
|
||
;_____________________________________________________________________________________________
|
||
@MSCSplit
|
||
move.l RBVAddr(a0),a5 ; get MSC base (same as RBV's) <H3> <SM12> begin
|
||
ori.b #(1<<MSCBank8M)|\
|
||
(%111<<MSCSize0),MSCConfig(a5) ; make all banks accessable <H5>
|
||
MOVEA.L A1,A5 ; point to ProductInfo table <H5>
|
||
ADDA.L ProductInfo.RamInfoPtr(A5),A5 ; point to the RAM bank map info <H5>
|
||
BRA.S @MSCRefresh ; <H5>
|
||
@MSCNextBank ; <H5>
|
||
MOVEA.L D2,A0 ; point to the start of this bank <H5>
|
||
MOVEQ #8-1,D0 ; make enough long word accesses to <H17>
|
||
@RASLoop TST.L (A0)+ ; provide 8 RAS cycles of <H17>
|
||
DBRA D0,@RASLoop ; memory initialization <H17>
|
||
@MSCRefresh ADDQ.L #4,A5 ; skip over the bank end <H5>
|
||
MOVE.L (A5)+,D2 ; last RAM bank? <H5>
|
||
BPL.S @MSCNextBank ; -> nope <H5>
|
||
bra SizeBanks ; and continue with sizing <7> HJR <SM12> end
|
||
|
||
;_____________________________________________________________________________________________
|
||
@PrattSplit
|
||
IF forRomulator THEN
|
||
TestInRAM a3 ; are we in RAM?
|
||
bne SizeBanks ; yes, then don't split
|
||
ENDIF
|
||
MOVEA.L A1,A5 ; point to ProductInfo table
|
||
ADDA.L ProductInfo.RamInfoPtr(A5),A5 ; point to the RAM bank map info
|
||
|
||
IF BlackBirdDebug THEN
|
||
PrattFlashSystem ; IF FlashSystem THEN
|
||
bne.s @Continue1 ;
|
||
BigLea RamInfoPrattFlash,a5 ; use phony Flash system RamInfoTables
|
||
@Continue1 ;
|
||
ENDIF ;
|
||
movea.l PrattAddr(a0),a0 ; get ptr to Pratt
|
||
move.b #PrattDefDensity,\ ;
|
||
PrattRAMDensity(a0) ; set default RAM Density
|
||
|
||
move.b #PrattDefConfig,\ ; (don't worry, Pratt will do the right thing if there is Flash)
|
||
PrattRAMConfig(a0) ; set default RAM Configuration
|
||
|
||
;** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING **
|
||
;The following line was added to test Pratt timing for OTPs currently in use for EVT's.
|
||
;For the final product, we need to decide what this value should really be.
|
||
;NOTE: This value does not affect execution speed from Flash.
|
||
move.b #Pratt150nsROM,\
|
||
PrattROMSpeed(a0)
|
||
;** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING **
|
||
|
||
; wait for at least 2mS so that Pratt has time to initialize the RAM banks to meet all
|
||
; vendor specs (the HW spec is really ~500 uS, so we have some margin here)
|
||
move.w #$3000,d2
|
||
@stall dbra d2,@stall
|
||
|
||
BRA.S @PrattRefresh ;
|
||
|
||
@PrattNextBank ;
|
||
MOVEA.L D2,A0 ; point to the start of this bank
|
||
TST.L (A0)+ ; make 8 accesses to each physical RAM bank (for added confidence)
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
TST.L (A0)+
|
||
@PrattRefresh
|
||
ADDQ.L #4,A5 ; skip over the bank end
|
||
MOVE.L (A5)+,D2 ; last RAM bank?
|
||
BPL.S @PrattNextBank ; -> nope
|
||
bra SizeBanks ; and continue with sizing
|
||
|
||
;_____________________________________________________________________________________________
|
||
@SonoraSplit ; <H4>
|
||
MOVE.L RBVAddr(A0),A5 ; Get RBV (Sonora VIA2) <H4> <H2>
|
||
ORI.B #%01111111,SonoraRAMSize(A5) ; Make each bank start at 16mg boundary <H4><H3>
|
||
; and make bank 0 assume 4 megs of RAM <H3>
|
||
BRA SizeBanks ; and continue with sizing <H4>
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
@YMCASplit ;
|
||
IF forRomulator THEN
|
||
TestInRAM a3 ; are we in RAM?
|
||
bne SizeBanks ; yes, then don't split <SM13>
|
||
ENDIF
|
||
|
||
; Set the width options for all 4-pairs of banks to 0 (Standard Mode) This is necessary because <SM11> fau start
|
||
; SizeMem is called multiple times by diagnostics, so the power-up values for the YMCA might be changed
|
||
; by the time the 2nd call is made.
|
||
|
||
Move.l DecoderAddr(A0),A5 ; Get YMCA's Base address
|
||
Lea YMCA_DRAMwidth0(a5),a5 ; Get the base address for the first bank's width register
|
||
Clr.l (A5)+ ; Bank's 0,2
|
||
Clr.l (A5)+ ; Bank's 1,3
|
||
Clr.l (A5)+ ; Bank's 4,6
|
||
Clr.l (A5)+ ; Bank's 5,7 <SM11> fau end
|
||
|
||
; Write to all 8 bank addresses to set their starting addresses 16 MB apart and to set their size to
|
||
; 16 MBytes.
|
||
Move.l DecoderAddr(A0),A5 ; Get YMCA's Base address
|
||
Lea YMCA_DRAMBank0_A20(a5),a5 ; Get the base address for the first bank's A20 register
|
||
|
||
Moveq #0,D0 ; D0 Contains the starting address
|
||
Move.w #8-1,D5 ; No of banks
|
||
|
||
@NextBank
|
||
Move.w #BankBdryRegSize-1,d2 ; Size of boundary address register (bits A26..A20 starting at 0)
|
||
|
||
@loadBdry Ror.l #1,d0 ; Move bit 0 to bit 31
|
||
move.l d0,(a5)+ ; and write it out
|
||
dbra d2,@loadBdry ; continue for all bits
|
||
|
||
Rol.l #BankBdryRegSize,D0 ; Return the address to it's starting position
|
||
Add.l #$10,D0 ; Add (16M >> 20) to the address
|
||
|
||
Move.l #%101,D1 ; D1 contains the size bits = 16MB banks
|
||
Move.w #BankSizeRegSize-1,d2 ; size of memory bank size bits
|
||
|
||
@loadSize Ror.l #1,d1 ; d1 = nibble size = bank size
|
||
move.l d1,(a5)+ ; and write it out
|
||
dbra d2,@loadSize ; continue for all bits
|
||
dbra d5,@NextBank ; go look at the next bank
|
||
|
||
|
||
BRA YMCASizeBanks ; and continue with sizing <SM11>
|
||
; <SM9> fau, end
|
||
|
||
;_____________________________________________________________________________________________ <H7> thru next <H7>
|
||
WITH ProductInfo
|
||
|
||
@djMEMCSplit ; <SM12>begin
|
||
IF forSTP601 THEN
|
||
bra OrwellMerge ; sized memory in HardwareInit.s, so act exactly like STP Orwell machines <SM48>
|
||
ENDIF
|
||
IF forSmurf THEN ; <SM23>
|
||
cmp.b #boxRiscCentris610,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM29>
|
||
cmp.b #boxRiscCentris650,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM29>
|
||
cmp.b #boxRiscQuadra800,ProductKind(a1) ; if we're on a Risc card <SM29>
|
||
beq SizeBanks ; >>SKIP this <SM29>
|
||
cmp.b #boxRiscQuadra610,ProductKind(a1) ; if we're on a Risc card <SM30>
|
||
beq SizeBanks ; >>SKIP this <SM30>
|
||
cmp.b #boxRiscQuadra650,ProductKind(a1) ; if we're on a Risc card <SM30>
|
||
beq SizeBanks ; >>SKIP this <SM30>
|
||
ENDIF ; <SM23> SAM
|
||
; We need to determine whether this machine is a WLCD or not. Get VIA1 information.
|
||
;
|
||
; Useful VIA1 PortA bits to read: PA6, PA4, PA2, PA1 ($56)
|
||
;
|
||
; PA6 = Lego (1), or Frigidaire (0) plastics for Wombat
|
||
; PA4, PA2 = CPU Speed. 0=20MHz, 1=25MHz, 2=33MHz, 3=40MHz
|
||
; PA1 = WLCD or Primus (0), or NOT! [reserved] (1)
|
||
;
|
||
|
||
move.l VIA1Addr(a0),a5 ; get VIA1 address to get machine/cpu_speed info
|
||
moveq #%00101000,d1 ; force VIA1 VDirA to have the correct directions
|
||
move.b d1,VDirA(a5) ; ... so we can read the CPU ID extension info
|
||
|
||
; Preset/Reset the Interleaving Enable register:
|
||
; ----------------------------------------------
|
||
;
|
||
; To be able to call SizeBanks repeatedly, we need to turn OFF any interleaving we may have
|
||
; turned on during previous SizeMemory calls. However, if you are a WLCD, you want to have
|
||
; enabled the OneBufferedBus flag in the InterleaveEnable register. _I_ would have put this
|
||
; bit in a different register (Configuration Register?) but since it's not, we have to make
|
||
; sure it is correctly set.
|
||
;
|
||
; For WLCD and Primus, the OneBufferedBus bit MUST be set.
|
||
; For Wombat(s), the OneBufferedBus bit MUST be CLEARED.
|
||
|
||
moveq #0,d0 ; preset InterleaveEnable to NO interleaving <H8>
|
||
btst.b #1,VBufA(a5) ; PA1: 0 = WLCD, 0 = NOT WLCD <H8>
|
||
bne.s @writeIntReg ; IF ( machine_type == WLCD ) || ( machine_type == Primus ) <H16>
|
||
bset #dj_OneBufferedBusBit,d0 ; set OneBufferedBus bit
|
||
@writeIntReg ; ENDIF
|
||
LEA MEMCAddr,A5 ; Get djMEMC base
|
||
move.l d0,MEMCIntleaveEnable(a5) ; disable interleaving, set/clear OneBufferedBus bit
|
||
|
||
; Reset the chip's MemTop
|
||
|
||
MOVEQ #-1,D0
|
||
MOVE.L D0,MEMCmemTop(A5) ; Set MemTop reg to $FF
|
||
|
||
; Reset all bank Cfg Regs so each bank starts on a 64 mb boundary in preparation
|
||
; for sizeBanks. (ie put $110 in Cfg1, $120 in Cfg2, etc.)
|
||
|
||
;_____________________________________________________________________________ <H8> thru next <H8>
|
||
; MEMC DRAM Bank configuration registers look like this: | 11-9 | 8 | 7-0 |
|
||
; Bits 11-9 are unused.
|
||
; Bit 8 is DRAM addressing mode (0 = 64mb bank, 1 = 4mb or 16mb bank)
|
||
; Bits 7-0 are bits 29-22 of the bank's starting physical address.
|
||
; (i.e. smallest bank size = 4mb)
|
||
;
|
||
; Hysterical Note: (BG - 92 June 10)
|
||
; The High-End HW team says that it is entirely unlikely that we'll
|
||
; see 64MBit parts any time in the near future, and it's unlikely that
|
||
; from power/voltage requirements that our boards would be able to
|
||
; support them. So instead of writing the Sizing code to make two passes,
|
||
; one with bit 8 ZERO to check for 64MB banks, then a second pass for
|
||
; non-64MB parts to see whether or not they are there, we simply assume
|
||
; they are NOT there and set bit 8 front and make a single pass.
|
||
;_____________________________________________________________________________
|
||
|
||
MOVE.L #$100,D1 ; Default bank start address (bits 29-22 of addr)
|
||
MOVEQ #dj_MaxBanks-1,D0 ; Loop counter (10 banks) <H8>
|
||
LEA MEMCdRAMCfg0(A5),A5 ; Get starting bank Cfg reg base
|
||
|
||
@Loop MOVE.L D1,(A5)+
|
||
ADD.W #$10,D1 ; Bump the start addr by 64 meg (bits 29-22 of addr)
|
||
DBRA D0,@Loop
|
||
|
||
* BRA.S SizeBanks ; and continue with sizing <H7>
|
||
|
||
; <SM12>end
|
||
|
||
ENDWITH
|
||
;=============================================================================================
|
||
SizeBanks
|
||
movea.l a1,a5 ; pointer to product info table <2.6>
|
||
adda.l ProductInfo.RamInfoPtr(a5),a5 ; point to the ram bank map info <2.6>
|
||
|
||
IF BlackBirdDebug THEN
|
||
btst #(PrattExists//8),(ProductInfo.BasesValid1+3-(PrattExists/8))(a1)
|
||
beq.s @noPratt
|
||
PrattFlashSystem ; IF FlashSystem THEN
|
||
bne.s continue ;
|
||
BigLea RamInfoPrattFlash,a5 ; use phony Flash system RamInfoTables
|
||
@noPratt
|
||
ENDIF ;
|
||
|
||
Continue ; label needed for VISA memory sizing <H5><SM4> rb
|
||
moveq #0,d0 ; clear total RAM size <H8><SM12>
|
||
sub.l a3,a3 ; initialize the "bank 8-15" information <H7><SM12>
|
||
subq.l #1,a3 ; ... to an improbable bank config value <H8><SM12>
|
||
@SizeBanks2 ; label needed for djMEMC sizing 2nd half of table <H8><SM12><SM13>
|
||
movea.l a5,a7 ; keep running copy in a7 <SM12>
|
||
addq.l #4,a7 ; skip over chunk size <SM12>
|
||
moveq #0,d5 ; clear bank size nibbles
|
||
moveq #0,d6 ; clear error bits
|
||
move.l #$54696e61,d1 ; setup signature
|
||
@nextBank
|
||
ror.l #4,d5 ; make room for next bank size nibble
|
||
ror.l #4,d6 ; make room for next bank error nibble
|
||
movea.l (a7)+,a0 ; get start of bank (or terminator) <SM12>
|
||
move.l a0,d2 ; end of table?
|
||
cmpi.l #'SamB',d2 ; at end of 1st table? <H8>
|
||
beq.s @checkErr ; -> yes, check for errs then continue <H8>
|
||
addq.l #1,d2
|
||
beq.s @checkErr ; yes, check for any errors and quit <SM12>
|
||
movea.l (a7)+,a1 ; get end+1 of bank <SM12>
|
||
|
||
BSR6 CheckByteLanes ; any byte lanes valid at start? <2.3>
|
||
moveq #$0F,d3 ; byte lane mask
|
||
and.b d6,d3 ; all byte lanes good here?
|
||
beq.s @size ; yes, try next bank <2.3>
|
||
cmp.b #$0F,d3 ; were all byte lanes bad?
|
||
bne.s @nextBank ; no, leave mask with bad bits
|
||
eor.b d3,d6 ; yes, clear out bit mask
|
||
bra.s @nextBank
|
||
|
||
@size BSR6 SizeBank ; find size of this bank
|
||
bra.s @nextBank ; now size next bank...
|
||
|
||
@checkErr move.l a7,d2 ; Save A7 <H8><SM12>
|
||
sub.l a5,d2 ; (table end + 8) - table start <H8><SM12>
|
||
subq.l #8,d2 ; #entries * 8 <H8><SM12>
|
||
lsr.w #1,d2 ; / 8 * 4 = # of nibbles to roll
|
||
rol.l d2,d5 ; d5 = ....dcba
|
||
rol.l d2,d6 ; d6 = ....dcba
|
||
|
||
tst.l d6 ; any errors?
|
||
bne.s @badBanks ; -> Yes, return now <H8> thru next <H8><SM12>
|
||
|
||
move.l a0,d2 ; get the terminator or extend flag in D2 <SM12>
|
||
cmpi.l #'SamB',d2 ; Extended flag? <SM12>
|
||
bne.s @stitchEm ; -> Nope, we're done <SM12>
|
||
move.l d5,a3 ; We have more to do, save D5 in A3 <SM12>
|
||
|
||
move.l a7,a5 ; Point A5 at the 2nd half of RAMInfo <SM12>
|
||
bra.s @SizeBanks2 ; -> make the second pass <SM12><SM13>
|
||
|
||
@stitchEm move.l a3,d2 ; have we put anything in A3 yet? <SM12>
|
||
addq.l #1,d2 ; if not, it was $FFFFFFFF <SM12>
|
||
beq.w Concat ; IF SomethingInA3 THEN <SM12>
|
||
move.l a3,d6 ; Put the extended nibbles in D6 <SM12>
|
||
exg d6,d5 ; Put low order banks in d5, extended in d6 <SM12>
|
||
bra.w Concat ; Sew baby sew! <SM12>
|
||
|
||
@badBanks jmp (a2) ; yes, return immediately <H8><SM12>
|
||
|
||
|
||
|
||
|
||
;=============================================================================================
|
||
; <SM11> fau start
|
||
YMCASizeBanks
|
||
;
|
||
; The YMCA has a separate SizeBanks routine because it supports standard and wide mode DRAM SIMMs. (See
|
||
; the YMCA ERS). Wide Mode DRAMs have more rows than columns and use less power -- Wombat uses these too.
|
||
; But, we're different and we support the standard mode, where the # of rows and columns are the same. What
|
||
; this means is that in order to size the banks we have to go through the sizing routine twice: once with
|
||
; the memory controller addressing the SIMMS in standard mode, and once in wide mode. (Note: The YMCA ERS
|
||
; has this complicated roadmap to follow in order to size the memory. After reviewing and looking at the
|
||
; DRAMs we support I determined that we can size the memory by making the two passes (standard and wide) and
|
||
; then comparing the nibble sizes for each bank and taking the largest one). One has to be careful because
|
||
; the standard/wide mode is programmed by bank pair: 0/2, 1/3, 4/6, and 5/7. Any bank can be populated, thus
|
||
; have to watch out for nibble sizes of 0. Well, enough of this. FAU 10/21/92
|
||
|
||
movea.l a1,a5 ; pointer to product info table
|
||
movea.l a1,a7 ; save a copy in a7 for the second sizing.
|
||
adda.l ProductInfo.RamInfoPtr(a5),a5 ; point to the ram bank map info
|
||
|
||
IF forRomulator THEN
|
||
|
||
TestInRAM a3 ; Are we in RAM?
|
||
beq.s @YMCAnotInRAM ; No? Then carry on.
|
||
; Yes? Assume Bank A is 4 MB
|
||
movea.l a5,A3 ; keep running copy in A3
|
||
add.l #$0C,A3 ; skip over chunk size and bank A
|
||
move.l #$00400000,d0 ; set RAM size for bank A
|
||
moveq #$01,d5 ; set bank A size nibbles
|
||
moveq #0,d6 ; clear error bits
|
||
move.l #$54696e61,d1 ; setup signature
|
||
|
||
bra.s @YMCAnextBank ; start checking at bank B
|
||
@YMCAnotInRAM
|
||
ENDIF
|
||
|
||
movea.l a5,A3 ; keep running copy in A3
|
||
addq.l #4,A3 ; skip over chunk size
|
||
moveq #0,d0 ; clear total RAM size
|
||
moveq #0,d5 ; clear bank size nibbles
|
||
moveq #0,d6 ; clear error bits
|
||
move.l #$54696e61,d1 ; setup signature
|
||
@YMCAnextBank
|
||
ror.l #4,d5 ; make room for next bank size nibble
|
||
ror.l #4,d6 ; make room for next bank error nibble
|
||
movea.l (A3)+,a0 ; get start of bank (or terminator)
|
||
move.l a0,d2 ; end of table?
|
||
addq.l #1,d2
|
||
beq.s @YMCAcheckErr ; yes, check for any errors
|
||
movea.l (A3)+,a1 ; get end+1 of bank
|
||
|
||
BSR6 CheckByteLanes ; any byte lanes valid at start?
|
||
moveq #$0F,d3 ; byte lane mask
|
||
and.b d6,d3 ; all byte lanes good here?
|
||
beq.s @YMCAsize ; yes, try next bank
|
||
cmp.b #$0F,d3 ; were all byte lanes bad?
|
||
bne.s @YMCAnextBank ; no, leave mask with bad bits
|
||
eor.b d3,d6 ; yes, clear out bit mask
|
||
bra.s @YMCAnextBank
|
||
|
||
@YMCAsize BSR6 SizeBank ; find size of this bank
|
||
bra.s @YMCAnextBank ; now size next bank...
|
||
|
||
@YMCAcheckErr
|
||
suba.l a5,A3 ; (table end + 8) - table start
|
||
subq.l #8,A3 ; #entries * 8
|
||
move.l A3,d2
|
||
lsr.w #1,d2 ; / 8 * 4 = # of nibbles to roll
|
||
rol.l d2,d5 ; d5 = ....dcba
|
||
rol.l d2,d6 ; d6 = ....dcba
|
||
|
||
tst.l d6 ; any errors?
|
||
bne @ExitSizeMem ; if so, don't do the wide banks stuff
|
||
|
||
; Now, resize the memory in wide mode.
|
||
; Save d5 in a7 and do the sizing with the wide mode. Note, d0 has the total size of DRAM, but
|
||
; we're going to recalculate this later, once we figure out which bank needs to be in standard mode and
|
||
; which one is in wide mode
|
||
|
||
; Get back the RamInfoPtr and the Address of our Decoder
|
||
|
||
movea.l a7,a5 ; restore the pointer to the product info table
|
||
adda.l ProductInfo.RamInfoPtr(a5),a5 ; point to the ram bank map info <2.6>
|
||
|
||
movea.l a7,a1 ; restore the pointer to the product info
|
||
adda.l ProductInfo.DecoderInfoPtr(a1),a1 ; point to the decoder info stuff
|
||
movea.l DecoderAddr(a1),a1 ; And get the decoder address
|
||
|
||
; Program the width registers to wide mode now
|
||
|
||
Lea YMCA_DRAMwidth0(a1),a1 ; and get the offset to the width options register
|
||
Move.l #-1,(a1)+ ; Bank's 0,2
|
||
Move.l #-1,(a1)+ ; Bank's 1,3
|
||
Move.l #-1,(a1)+ ; Bank's 4,6
|
||
Move.l #-1,(a1)+ ; Bank's 5,7
|
||
|
||
; Save our nibble sizes for standard mode
|
||
|
||
move.l d5,a7 ; save our standard mode bank sizes
|
||
|
||
IF forRomulator THEN
|
||
|
||
TestInRAM a3 ; Are we in RAM?
|
||
beq.s @2YMCAnotInRAM ; No? Then carry on.
|
||
; Yes? Assume Bank A is 4 MB
|
||
movea.l a5,A3 ; keep running copy in A3
|
||
add.l #$0C,A3 ; skip over chunk size and bank A
|
||
move.l #$00400000,d0 ; set RAM size for bank A
|
||
moveq #$01,d5 ; set bank A size nibbles
|
||
moveq #0,d6 ; clear error bits
|
||
move.l #$54696e61,d1 ; setup signature
|
||
|
||
bra.s @2YMCAnextBank ; start checking at bank B
|
||
@2YMCAnotInRAM
|
||
ENDIF
|
||
movea.l a5,A3 ; keep running copy in A3
|
||
addq.l #4,A3 ; skip over chunk size
|
||
moveq #0,d0 ; clear total RAM size
|
||
moveq #0,d5 ; clear bank size nibbles
|
||
moveq #0,d6 ; clear error bits
|
||
move.l #$54696e61,d1 ; setup signature
|
||
@2YMCAnextBank
|
||
ror.l #4,d5 ; make room for next bank size nibble
|
||
ror.l #4,d6 ; make room for next bank error nibble
|
||
movea.l (A3)+,a0 ; get start of bank (or terminator)
|
||
move.l a0,d2 ; end of table?
|
||
addq.l #1,d2
|
||
beq.s @2YMCAcheckErr ; yes, check for any errors
|
||
movea.l (A3)+,a1 ; get end+1 of bank
|
||
|
||
BSR6 CheckByteLanes ; any byte lanes valid at start?
|
||
moveq #$0F,d3 ; byte lane mask
|
||
and.b d6,d3 ; all byte lanes good here?
|
||
beq.s @2YMCAsize ; yes, try next bank
|
||
cmp.b #$0F,d3 ; were all byte lanes bad?
|
||
bne.s @2YMCAnextBank ; no, leave mask with bad bits
|
||
eor.b d3,d6 ; yes, clear out bit mask
|
||
bra.s @2YMCAnextBank
|
||
|
||
@2YMCAsize BSR6 SizeBank ; find size of this bank
|
||
bra.s @2YMCAnextBank ; now size next bank...
|
||
|
||
@2YMCAcheckErr
|
||
suba.l a5,A3 ; (table end + 8) - table start
|
||
subq.l #8,A3 ; #entries * 8
|
||
move.l A3,d2
|
||
lsr.w #1,d2 ; / 8 * 4 = # of nibbles to roll
|
||
rol.l d2,d5 ; d5 = ....dcba
|
||
rol.l d2,d6 ; d6 = ....dcba
|
||
|
||
tst.l d6 ; any errors?
|
||
bne @ExitSizeMem ; if so, don't do the wide banks stuff
|
||
|
||
; We have finished sizing the memory in wide mode. a7 has the nibble sizes with standard mode,
|
||
; and d5 has the nibble sizes in wide mode.
|
||
|
||
Move.l a7,d4
|
||
|
||
; OK, at this point d4 contains the nibble sizes when sized in standard mode and d5 contains the
|
||
; nibble sizes when sized in wide mode. We now need to determine, for each bank, which nibble contains
|
||
; the largest amount of ram and program the YMCA to the corresponding Std/Wide option. We'll put the
|
||
; combined nibble sizes into d0 and then move it to d5, as that's what the Concat routine expects.
|
||
|
||
Move.l #$50f30420,a3 ; YMCA Width Register
|
||
Lea YMCAWidthOffsets,a0 ; Offset lookup table
|
||
clr.w d1 ; Use d1 as our loop/bank counter
|
||
clr.l d0 ; d0 will contain the combined nibbles
|
||
|
||
@LoopBanks
|
||
move.b d4,d2 ; we need to compare lower nibbles only (d2: std)
|
||
andi.b #$0f,d2 ; so mask out higher nibble
|
||
move.b d5,d3 ; we need to compare nibbles only (d3: wide)
|
||
andi.b #$0f,d3 ; so mask out higher nibble
|
||
cmp.b d3,d2 ; d3<-wide, d2<-standard
|
||
bhs.s @StdMode ; if d2 is ³ then program in standard mode <LW4>
|
||
or.b d3,d0 ; else, d3 is > so or move nibble into our keeper
|
||
Tst.b d3 ; Was our bank size 0 <LW4>
|
||
beq.s @NextNibble ; Don't set the width register if the size is 0
|
||
Move.w (a0,d1.w*2),a1 ; get offset for this bank
|
||
adda.l a3,a1 ; and add the base of the width registers
|
||
Move.l #-1,(a1) ; and write it out
|
||
bra.s @NextNibble ; go look at next nibble
|
||
@StdMode
|
||
or.b d2,d0 ; Standard width size into the keeper
|
||
; program bank d1 to std mode
|
||
Tst.b d2 ; Was our bank size 0 <LW4>
|
||
beq.s @NextNibble ; Don't set the width register if the size is 0
|
||
Move.w (a0,d1.w*2),a1 ; get offset for this bank
|
||
adda.l a3,a1 ; and add the base
|
||
Clr.l (a1) ; and write it out
|
||
@NextNibble
|
||
lsr.l #4,d4 ; look at next nibble of standard mode
|
||
lsr.l #4,d5 ; look at next nibble of wide mode
|
||
ror.l #4,d0 ; make room for next nibble in our keeper
|
||
addi.w #1,d1 ; increment our loop counter
|
||
cmpi.w #8,d1 ; have we done all 8 banks?
|
||
bne.s @LoopBanks ; go loop through the banks
|
||
|
||
move.l d0,d5 ; put the nibble sizes into d5
|
||
|
||
bra Concat ; no, then stitch banks together (if possible)
|
||
|
||
@ExitSizeMem
|
||
jmp (a2) ; yes, return immediately
|
||
; <SM11> fau end
|
||
;_____________________________________________________________________________________________
|
||
; Routine: SizeBank
|
||
;
|
||
; Inputs: a0 - points to start of physical bank to size
|
||
; a1 - points to end of physical bank to size
|
||
; a2 - SizeMem return address
|
||
; (a5) - page size to check for aliasing (e.g. 1 meg)
|
||
; d0 - total RAM from previous banks sized
|
||
; d1 - signature
|
||
; d5 - x......., where x = nibble sizes of previous bank(s) sized.
|
||
;
|
||
; Outputs: d0 - total RAM including this banks size.
|
||
; d5 - x......n, where n = nibble size of this bank (0..15)
|
||
; a0 - actual size of bank
|
||
;
|
||
; Destroys: a1,d2-d4
|
||
;
|
||
; Given the start and end of a bank of memory, this routine finds the last location
|
||
; within the bank which can be written to (including wrap). Then it trims this back,
|
||
; checking for wrap. On exit, it sets a0 = actual size of unique RAM found in the bank,
|
||
; (0 if no RAM found), and the low nibble of d5 contains n where bank size = 2^(n-1)*chunk size
|
||
; for n > 0, and bank size = 0 for n=0.
|
||
;
|
||
; This routine assumes that the data cache is OFF. The addresses passed in
|
||
; must be on page boundaries, where the page size is in D0.
|
||
;_____________________________________________________________________________________________
|
||
SizeBank
|
||
move.l a0,d4 ; save start of bank
|
||
|
||
subq.l #4,a1 ; point to end-4 of bank
|
||
@check move.l (a1),d2 ; save original
|
||
move.l d1,(a1) ; write signature at top
|
||
|
||
@here tst.l (@here) ; Bus capacitance is a no, no. <H9> SAM
|
||
|
||
cmp.l (a1),d1 ; any RAM there?
|
||
beq.s @foundRAM ; yes, check for wrap
|
||
|
||
suba.l (a5),a1 ; step back to lower block
|
||
cmpa.l a0,a1 ; stepped below start?
|
||
bgt.s @check ; no, continue looking for RAM
|
||
bra.s @exit ; yes, exit
|
||
|
||
@foundRAM
|
||
subq.l #4,a0 ; go 4 bytes back from start
|
||
@loop adda.l (a5),a0 ; add in chunk size
|
||
cmp.l (a0),d1 ; found lowest occurance of signature?
|
||
bne.s @loop ; no, check a little higher up
|
||
|
||
move.l d2,(a0)+ ; restore last four bytes we wiped out
|
||
@length suba.l d4,a0 ; leave a0 with size of bank
|
||
|
||
moveq #0,d3 ; n=0
|
||
move.l a0,d2 ; any ram?
|
||
beq.s @stuff ; no, stuff n=0 into size register
|
||
|
||
move.l (a5),d2 ; start with smallest chunk size (e.g. 1M)
|
||
@next addq #1,d3 ; n=n+1
|
||
cmpa.l d2,a0 ; (2^(n-1))*chunk size = bank size?
|
||
beq.s @stuff ; yes, stuff 'n' into d5
|
||
|
||
; If a0 < d2 then something is wrong! Stuff 0 into d3 and exit. <SM10> fau
|
||
|
||
blt.s @NotAPowerofTwo ; Our loop has gone over a possible match, so better bailout <SM10> fau
|
||
add.l d2,d2 ; calculate next power of two
|
||
bra.s @next
|
||
@NotAPowerofTwo ;<SM10> fau
|
||
moveq #0,d3 ; say no memory.
|
||
@stuff or.b d3,d5 ; 'OR' in 'n' (size of this bank)
|
||
add.l a0,d0 ; add this banks RAM to total size
|
||
@exit RTS6
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: CheckByteLanes
|
||
;
|
||
; Inputs: a0 - location to check
|
||
; d1 - signature
|
||
; d6 - x......0 where x = running bit mask of previous bank(s) SIMM errors
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: d6 - x......e where e = bit mask for this banks errors:
|
||
; e = 0000 if byte lanes 0-3 seem ok
|
||
; e = 0001 if byte lane 0 seems bad
|
||
; e = 1111 if byte lanes 0-3 seem bad
|
||
;
|
||
; Destroys: d2-d4
|
||
;
|
||
; This routine checks which byte lanes are valid at location pointed to by
|
||
; a0. This helps service identify missing SIMMs, etc. It can be called up
|
||
; to 8 times (for 8, 4-byte-wide banks) before overflowing the result register.
|
||
;_____________________________________________________________________________________________
|
||
CheckByteLanes ; <2.3>
|
||
move.l (a0),d3 ; preserve original value
|
||
move.l 4(a0),d4 ; preserve next value <2.8>
|
||
move.l d1,(a0) ; write signature
|
||
|
||
moveq #4-1,d2
|
||
@next move.l #$FFFFFFFF,4(a0) ; take care of stray capacitance on bus <2.8>
|
||
cmp.b (a0,d2.w),d1 ; did this byte match?
|
||
bne.s @bad ; no, shift in error bit
|
||
|
||
not.b d1 ; yes, try compliment to make sure
|
||
not.b (a0,d2.w) ; compliment RAM value
|
||
cmp.b (a0,d2.w),d1 ; did compliment match?
|
||
beq.s @shift ; yes, next byte...
|
||
|
||
@bad bset d2,d6 ; set bad bit mask <2.9>
|
||
|
||
@shift ror.l #8,d1 ; next signature byte
|
||
dbra d2,@next ; do next byte
|
||
move.l d3,(a0) ; restore original at start
|
||
move.l d4,4(a0) ; restore next value <2.8>
|
||
RTS6
|
||
|
||
|
||
|
||
|
||
|
||
;=============================================================================================
|
||
; Routine: Concat
|
||
;
|
||
; Inputs: d0 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; d6 - nibble sizes for up to an additional 8 banks <H7><H8><SM12>
|
||
; a2 - SizeMem return address
|
||
;
|
||
; This routine vectors to the appropriate 'stitch' routine, after getting the decoder type.
|
||
;_____________________________________________________________________________________________
|
||
Concat move.l d0,d3 ; save last size <9>
|
||
moveq #0,d2 ; don't know anything about machine
|
||
movea.l #aStack,sp ; set stack pointer value
|
||
move.l a2,d4 ; save return address
|
||
BigBSR6 GetHardwareInfo,a0 ; get universal info again
|
||
movea.l d4,a2 ; restore return address
|
||
|
||
IF BlackBirdDebug THEN
|
||
btst #(PrattExists//8),(ProductInfo.BasesValid1+3-(PrattExists/8))(a1)
|
||
adda.l ProductInfo.RamInfoPtr(a1),a1 ; point to the ram bank map info
|
||
beq.s @Continue1
|
||
PrattFlashSystem ; IF FlashSystem THEN
|
||
bne.s @Continue1 ;
|
||
BigLea RamInfoPrattFlash,a1 ; use phony Flash system RamInfoTables
|
||
@Continue1 ;
|
||
ELSE ;
|
||
adda.l ProductInfo.RamInfoPtr(a1),a1 ; point to the ram bank map info
|
||
ENDIF
|
||
add.b d2,d2 ; decoder type adjusted for word table access
|
||
ext.w d2
|
||
move.w @mergTbl(d2.w),d1 ; get offset to merger routine
|
||
move.l (a1)+,d2 ; get chunk size in d2 now
|
||
jmp @mergTbl(d1.w) ; call routine (d2=chunk size, a1=1st table entry)
|
||
|
||
@mergTbl
|
||
|
||
; This table should match the DecoderKinds record in UniversalEqu.a <SM9> fau
|
||
|
||
dc.w noMerge -@mergTbl ; unknown
|
||
dc.w noMerge -@mergTbl ; Mac Pal (no merging required)
|
||
dc.w noMerge -@mergTbl ; BBU (no merging required)
|
||
dc.w noMerge -@mergTbl ; Normandy (no merging required)
|
||
dc.w GlueMerge -@mergTbl ; Mac2Glue
|
||
dc.w MDUMerge -@mergTbl ; MDU (no merging possible)
|
||
dc.w FMCMerge -@mergTbl ; OSS FMC
|
||
dc.w VISAMerge -@mergTbl ; VISA <T9>
|
||
dc.w OrwellMerge -@mergTbl ; Orwell <T9>
|
||
dc.w JAWSMerge -@mergTbl ; JAWS
|
||
dc.w MSCMerge -@mergTbl ; MSC <7> HJR
|
||
dc.w SonoraMerge -@mergTbl ; Sonora <H4> SAM
|
||
dc.w NiagraMerge -@mergTbl ; Niagra <xxx>
|
||
dc.w YMCAMerge -@mergTbl ; YMCA <SM9> fau
|
||
dc.w djMEMCMerge -@mergTbl ; djMEMC (djMEMC has a max of 10 banks) <H7><SM12>
|
||
dc.w HMCMerge -@mergTbl ; HMC <SM18> SAM
|
||
dc.w PrattMerge -@mergTbl ; Pratt <SM15>
|
||
dc.w HHeadMerge -@mergTbl ; HHead
|
||
|
||
|
||
Align 4
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: noMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to universal base addresses table
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d1,a1
|
||
;
|
||
; This routine simply writes the chunk table at the top of the bank (pointed to by a1), given
|
||
; the banks size in d0. Used ONLY for single bank systems (like MacPlus, SE, Portable).
|
||
;_____________________________________________________________________________________________
|
||
noMerge ; <9>
|
||
moveq #(3*4)+(1*8),d1 ; size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
|
||
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: HMCMerge (emulated system fake stitch and fake chunk table creation) <SM18> Sam
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
; a1 - Ptr to product info record
|
||
;
|
||
; Destroys: D0-D3/D6,A0-A2
|
||
;
|
||
; This routine creates a fixed size chunk table at the end of logical RAM. The emulator provides
|
||
; us with the size of logical and physical RAM. The logical size accounts for the RAM stolen by
|
||
; the emu for DMA buffers, video, EDisk, etc. The Physical size is useful only for display at the
|
||
; Finder, etc. Oh, yes, by the time we get run (68k code, that is) the native hardware init has
|
||
; already sized and stitched memory together.
|
||
;
|
||
; The fake table looks like this:
|
||
;
|
||
; 1st bank start addr: $00000000
|
||
; Length (log ram size returned from the emu) 0 < X <= 256mb
|
||
; Chunk table terminator $FFFFFFFF
|
||
; Std diagnostic long #1 $00000000
|
||
; Std diagnostic long #2 $00000000
|
||
; Std diagnostic long #3 $00000000
|
||
; Total bytes allocated for an EDisk $xxxxxxxx
|
||
; Total RAM allocated by the nanokernel $xxxxxxxx ; The end of "Physical RAM"
|
||
;
|
||
; Table size: $20 bytes fixed.
|
||
;
|
||
; D7 is used as a flag register for the size of the RAM Disk and whether or not to allocate Video RAM
|
||
; bit 31: high = allocate Video RAM (bit is cleared when testing to turn on video or not)
|
||
;_____________________________________________________________________________________________
|
||
export HMCMerge
|
||
|
||
HMCMerge ; <SM18> Sam
|
||
With NKSystemInfo, ProductInfo, VideoInfo
|
||
|
||
MOVE.L A2,D6 ; Save SizeMem's return address
|
||
|
||
LongBSR6 GetHardwareInfo ; Get universal info again
|
||
MOVE.L DecoderInfo.VIA1Addr(A0),A2 ; Get VIA1's base address for RdXByte
|
||
|
||
; Read PRAM locations (FC through FF) and test for one of several factory settings that
|
||
; tell us to allocate a frame buffer (even if no monitor is connected)
|
||
|
||
MOVEQ.L #0,D7 ; Clear the fb allocation flag
|
||
MOVE.W #burnInLoc,D1 ; 1st burn in byte
|
||
BSR6 RdXByte ; Read the Factory data
|
||
MOVE.B D1,D3 ; Save hi byte
|
||
SWAP D3
|
||
LSL.L #8,D3 ; Shift to high byte
|
||
MOVEQ #0,D1 ; Prep D1 for PRAM data
|
||
MOVE.W #burnInLoc+1,D1 ; 2nd burn in byte
|
||
BSR6 RdXByte ; Read the Factory data
|
||
SWAP D1 ; Save second hi byte
|
||
OR.L D1,D3 ;
|
||
MOVEQ #0,D1 ; Prep D1 for PRAM data
|
||
MOVE.W #burnInLoc+2,D1 ; 3rd burn in byte
|
||
BSR6 RdXByte ; Read the Factory data
|
||
LSL.W #8,D1 ; Shift byte to second low byte
|
||
OR.L D1,D3 ;
|
||
MOVEQ #0,D1 ; Prep D1 for PRAM data
|
||
MOVE.W #burnInLoc+3,D1 ; 4th burn in byte
|
||
BSR6 RdXByte ; Read the Factory data
|
||
OR.L D3,D1 ; OR in the result
|
||
|
||
CMP.L #burninSig,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
CMP.L #burnInSigAlt,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
CMP.L #burnInSig12,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
CMP.L #burnInSig13,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
CMP.L #burnInSig15,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
CMP.L #burnInSig16,D1 ; Is this one of the factory settings?
|
||
BEQ @GetFB ; -> Yes, allocate the frame buffer
|
||
|
||
; No factory enable. Check to see what's connected. If nothing is connected, do not
|
||
; allocate the frame buffer.
|
||
|
||
MOVE.L #SonoraVdCtlBase,A0 ; Offset from VIA1 base to Sonora Control Regs
|
||
ADD.L A2,A0 ; Add in VIA1 base. A0 points to SonoraCtrlRegs
|
||
|
||
MOVE.B #$9F,SonoraVdModeReg(A0) ; Disable video (if it was on) <MC7>
|
||
MOVE.B #tristateSonoraSense,SonoraVdSenseRg(A0) ; Tristate the sense lines.
|
||
BSR6 CheckVidSense
|
||
CMP.B #indexedNoConnect,D3 ; If Sense == No Connect, check Extended Sense
|
||
BNE @GetFB ; Otherwise turn of Video RAM
|
||
|
||
MOVEQ #0,D1 ; prep D1 for Extended sense data
|
||
MOVEQ #0,D3 ; prep D2 for Extended sense data
|
||
|
||
; Sense lines indicate something might be connected. Check the extended sense.
|
||
|
||
; Drive a, Read bc
|
||
|
||
@DriveA MOVE.B #sonoraEnableAMask,SonoraVdSenseRg(A0) ; abc <- 011
|
||
BSR6 CheckVidSense
|
||
ANDI.B #sonoraAMask,D3 ; 0BC
|
||
MOVE.B D3,D1 ; 00 00 BC
|
||
LSL.B #2,D1 ; 00 BC 00
|
||
|
||
; Drive b, Read ac
|
||
|
||
@DriveB MOVE.B #sonoraEnableBMask,SonoraVdSenseRg(A0) ; abc <- 101
|
||
BSR6 CheckVidSense
|
||
ANDI.B #sonoraBMask,D3 ; A0C
|
||
BCLR #sonoraSenseLineA,D3 ; A0C becomes
|
||
BEQ.S @OrIn ; A0C or
|
||
BSET #sonoraSenseLineB,D3 ; A1C
|
||
|
||
@OrIn OR.B D3,D1 ; 00 BC AC
|
||
LSL.B #2,D1 ; BC AC 00
|
||
|
||
; Drive c, Read ab
|
||
|
||
@DriveC MOVE.B #sonoraEnableCMask,SonoraVdSenseRg(A0) ; abc -> 110
|
||
BSR6 CheckVidSense
|
||
ANDI.B #sonoraCMask,D3 ; AB0
|
||
LSR.B #1,D3 ; 0AB
|
||
OR.B D3,D1 ; BC AC AB
|
||
|
||
CMP.B #extendedNoConnect,D1 ; Is anything connected?
|
||
BEQ.S @NoFB ; -> Nope, leave D7 alone. Don't allocate the frame buffer
|
||
|
||
@GetFB BSET.L #31,D7 ; Set the "Allocate a DRAM frame buffer" flag
|
||
@NoFB
|
||
|
||
; Read PRAM to see if the user wants an EDisk. If the size is > MinRamDiskSize then ask the <SM21> SAM
|
||
; nanokernel for some RAM.
|
||
|
||
LongBSR6 GetHardwareInfo ; Get universal info again
|
||
MOVE.L DecoderInfo.VIA1Addr(A0),A2 ; Get VIA1's base address for RdXByte
|
||
|
||
MOVE.W #ramDiskPramAddr,D1 ; Get the EDisk PRAM byte constant
|
||
BSR6 RdXByte ; Read the EDisk size (in % of total RAM) in D1
|
||
MOVE.L D6,A2 ; Restore the return address
|
||
|
||
ADD.L VideoInfoPtr(A1),A1 ; Point A1 to the VideoInfo record for this machine
|
||
MOVE.L VRAMLogAddr32(A1),D6 ; Get the Logical Frame Buffer base address
|
||
|
||
; Get the MMU page size from the nanokernel. Count bits in the result to get a shift factor
|
||
|
||
MOVEQ #0,D3 ; Clear D3
|
||
MOVE.L ([ProcessorInfoPtr],ProcessorInfo.PageSize),D0 ; Get the Page size from the nano-k
|
||
BFFFO D0{15:15},D3 ; Get the shift factor (Find First One)
|
||
NOT.B D3 ; Flip the order (BF instr start at bit 32 -> )
|
||
ADD.B #32,D3 ; Get the bit number (lsb based)
|
||
|
||
MOVEQ #0,D5 ; Clear the EDisk allocation size <MC9>
|
||
MOVE.L (NKSystemInfoPtr),A5 ; Point to the nanokernel SystemInfo record
|
||
ANDI.L #$FF,D1 ; Clear upper bytes of pram byte
|
||
BEQ.S @DMABuffer ; -> No EDisk, check DMA Buffer
|
||
|
||
MOVE.L PhysicalMemorySize(A5),D2 ; Get physical RAM size
|
||
LSR.L #8,D2 ; Scale the size by 256k chunks
|
||
MULU.L D1,D2 ; Mult Chunks by ChunkCount from PRAM = EDisk size
|
||
ADD.L #$7FFF,D2 ; Add an extra 32k to the size
|
||
AND.W #$8000,D2 ; Round down to 32k boundary
|
||
CMPI.L #MinRamDiskSize,D2 ; Is this size too small? (user pulled some SIMMs)
|
||
BLO.S @DMABuffer ; -> Yes, too small. No EDisk
|
||
CMPI.L #MaxRamDiskSize,D2 ; Is it too big? <MC8>
|
||
BHI.S @DMABuffer ; -> Yes, too big. No EDisk
|
||
|
||
MOVE.L LogicalMemorySize(A5),D0 ; Get the logical size (Phys - nk private stuff) <MC8> till next <MC8>
|
||
SUB.L #PDMDMAbufSize,D0 ; Subtract the DAM buffer size from Log RAM size
|
||
TST.L D7 ; Are we going to allocate 614k for a frame buffer?
|
||
BPL.S @CheckMinHeap ; -> Nope,
|
||
SUB.L #604*1024,D0 ; Subtract the frame buffer size if enabled
|
||
@CheckMinHeap
|
||
SUB.L D2,D0 ; Subtract the EDisk size
|
||
CMP.L #MinHeapSize,D0 ; Will we have at least MinHeapSize free after the EDisk?
|
||
BLT.S @DMABuffer ; -> No, do not allocate the EDisk (signed) <MC9>
|
||
|
||
MOVE.L D2,D5 ; Save the number of bytes used by the EDisk in the chunk table. <MC8>
|
||
ADD.L D2,D7 ; Add the size to our running allocation counter
|
||
MOVE.L #bRamDisk,D0 ; Get the EDisk logical base address
|
||
LSR.L D3,D0 ; Turn the address into a page number
|
||
MOVE.L D0,A0 ; Put the logical page number in A0
|
||
|
||
LSR.L D3,D2 ; Turn the size into a page count
|
||
MOVE.L D2,A1 ; Put page count in A1
|
||
|
||
MOVEQ #0,D1 ; Indicate no special alignment necessary
|
||
_nkAllocateMemory ; Get the RAM and map it where we asked
|
||
|
||
; Allocate space for the DMA buffer
|
||
|
||
@DMABuffer MOVE.L #PDMDMAbufSize,D0 ; Get the hard coded DMA buffer size (160k)
|
||
ADD.L D0,D7 ; Add the DMA buffer size to our counter
|
||
LSR.L D3,D0 ; Turn the byte count into a page count
|
||
MOVE.L D0,A1 ; Put page count in A1
|
||
|
||
MOVE.L #PDMDMAlogAddr,D0 ; Get the desired logical address
|
||
LSR.L D3,D0 ; Turn it into a page number
|
||
MOVE.L D0,A0 ; Put the logical page number in A0
|
||
|
||
MOVE.L #(256*1024)-1,D1 ; Align physical address to 256k boundary (AMIC Requirement)
|
||
LSR.L D3,D1 ; Make that a page alignment
|
||
_nkAllocateMemory ; Get the DMA buffer RAM.
|
||
|
||
; Due to a DataPath bug, all byte-assembled buffers need to be marked noncacheable (floppy & serial).
|
||
; Due to an IBM bug, all the rest of the DMA buffers need to be marked noncacheable (marginal parts
|
||
; don't like Global/ARty being asserted).
|
||
|
||
MOVE.L #PDMDMAbufSize,D2 ; Get the number of bytes to mark noncacheable (all of them)
|
||
LSR.L D3,D2 ; Convert that to a page count
|
||
SUBQ #1,D2 ; Make it zero based for DBRA
|
||
|
||
MOVE.L #PDMDMAlogAddr,D0 ; Start of non cacheable range
|
||
LSR.L D3,D0 ; Turn it into a logical page number
|
||
MOVE.L D0,A0 ; Put the page number in A0
|
||
|
||
@NoCacheLup _nkMMUMakePageNonCacheable ; Disable the cache for this page <SM27>
|
||
LEA 1(A0),A0 ; PageNumber++
|
||
DBRA D2,@NoCacheLup ; -> Do this for each page
|
||
|
||
; Allocate RAM for the RAM Based Video (NQD writes *past* the end of the buffer. Get some slop for sloppy...)
|
||
|
||
BCLR.L #31,D7 ; If zero don't allocate the frame buffer
|
||
BEQ.S @Chunky ; -> Do not allocate the frame buffer
|
||
|
||
MOVE.L #604*1024,D2 ; Get 618496 (604k) bytes (max RBV can support w/slop)
|
||
ADD.L D2,D7 ; Add the frame buffer size to our counter
|
||
LSR.L D3,D2 ; Turn the byte count into a page count
|
||
MOVE.L D2,A1 ; Page Count -> A1
|
||
|
||
LSR.L D3,D6 ; Turn the logical video base into page number
|
||
MOVE.L D6,A0 ; Logical Page # -> A0
|
||
MOVEQ #-1,D1 ; Force the allocation to start at phys 0 (HMC Requirement)
|
||
LSR.L D3,D1 ; Make that a page alignment
|
||
_nkAllocateMemory ; Get the RAM and map it where we asked
|
||
|
||
; Make the frame buffer RAM cache mode WriteThrough
|
||
|
||
SUBQ #1,D2 ; Make the RBV page count zero based
|
||
@CacheLupe _nkMakePageWriteThrough
|
||
LEA 1(A0),A0 ; PageNumber++
|
||
DBRA D2,@CacheLupe ; -> Do this for ¥every¥ page
|
||
|
||
; Now that RAM has been adjusted by the possible allocation of an EDisk, Video frame buffer
|
||
; and/or DMA buffer, we can construct the RAM chunk table that sits at the top of logical RAM.
|
||
; At this point A5 should be pointing to the nanokernel SystemInfo record.
|
||
|
||
@Chunky MOVE.L UsableMemorySize(A5),D1 ; Get the Useable RAM size from NK
|
||
MOVE.L D1,A5 ; Put the size (our Memtop) in A5
|
||
|
||
; Start from the Top down
|
||
MOVE.L D7,-(A5) ; Put our total allocation at the top of L RAM (Inc edisk). <MC8>
|
||
MOVE.L D5,-(A5) ; Num bytes used by the EDisk <MC8>
|
||
MOVE.L #$68657265,-(A5) ; Old Unused Diag long #3
|
||
MOVE.L #$77617320,-(A5) ; Old Unused Diag long #2
|
||
MOVE.L #$53616D20,-(A5) ; Old Unused Diag long #1
|
||
MOVE.L #-1,-(A5) ; Chunk table terminator
|
||
MOVE.L D1,-(A5) ; Top of usable RAM
|
||
CLR.L -(A5) ; Logical start of RAM
|
||
|
||
MOVE.L A5,A1 ; Put Ptr to chunk table in A1 for MergeDone
|
||
MOVEQ #0,D6 ; Signal no RAM test errors.
|
||
BRA MergeDone ; Set the stack and leave
|
||
|
||
EndWith
|
||
|
||
CheckVidSense
|
||
|
||
MOVE.W #550,D0 ; 550 iterations
|
||
@WaitLupe TST.B vIER(A2) ; Wait ~1.2µs
|
||
DBRA D0,@WaitLupe ; -> Keep looping for ~550µs
|
||
|
||
MOVEQ #0,D3 ; D2 used as senseline scratch.
|
||
MOVE.B SonoraVdSenseRg(A0),D3 ; Read the lines into scratch.
|
||
LSR.B #4,D3 ; Get inputs out of upper nybble.
|
||
|
||
MOVE.W #550,D0 ; 550 iterations
|
||
@WaitLupe2 TST.B vIER(A2) ; Wait ~1.2µs
|
||
DBRA D0,@WaitLupe2 ; -> Keep looping for ~550µs
|
||
RTS6
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: HHEadMerge (emulated system fake stitch and fake chunk table creation) <SM18> Sam
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
; a1 - points to the chunk table
|
||
;
|
||
; Destroys: D0-D3,A0-A2
|
||
;
|
||
; This routine creates a fixed size chunk table at the end of logical RAM. The emulator provides
|
||
; us with the size of logical and physical RAM. The logical size accounts for the RAM stolen by
|
||
; the emu for DMA buffers, video, EDisk, etc. The Physical size is useful only for display at the
|
||
; Finder, etc. Oh, yes, by the time we get run (68k code, that is) the native hardware init has
|
||
; already sized and stitched memory together.
|
||
;
|
||
; The fake table looks like this:
|
||
;
|
||
; 1st bank start addr: $00000000
|
||
; Length (log ram size returned from the emu) 0 < X <= 256mb
|
||
; Chunk table terminator $FFFFFFFF
|
||
; Std diagnostic long #1 $00000000
|
||
; Std diagnostic long #2 $00000000
|
||
; Std diagnostic long #3 $00000000 ; The end of "Physical RAM"
|
||
;
|
||
; Table size: $24 bytes fixed.
|
||
;
|
||
;_____________________________________________________________________________________________
|
||
export HHEADMerge
|
||
|
||
HHEadMerge ; <SM18> Sam
|
||
With NKSystemInfo, ProductInfo, VideoInfo
|
||
|
||
; Read PRAM to see if the user wants an EDisk. If the size is > MinRamDiskSize then ask the <SM21> SAM
|
||
; nanokernel for some RAM.
|
||
|
||
MOVE.L A2,D3 ; Save SizeMem's return address
|
||
|
||
LongBSR6 GetHardwareInfo ; Get universal info again
|
||
MOVE.L DecoderInfo.VIA1Addr(A0),A2 ; Get VIA1's base address for RdXByte
|
||
|
||
LSR.W #8,D2 ; Get the boxflag in the low byte <SM27>
|
||
MOVE.B D2,D7 ; Save it in D7 <SM27>
|
||
|
||
MOVE.W #ramDiskPramAddr,D1 ; Get the EDisk PRAM byte constant
|
||
BSR6 RdXByte ; Read the EDisk size (in % of total RAM) in D1
|
||
MOVE.L D3,A2 ; Restore the return address
|
||
|
||
; Get the MMU page size from the nanokernel. Count bits in the result to get a shift factor
|
||
|
||
MOVEQ #0,D3 ; Clear D3
|
||
MOVE.L ([ProcessorInfoPtr],ProcessorInfo.PageSize),D0 ; Get the Page size from the nano-k
|
||
BFFFO D0{15:15},D3 ; Get the shift factor (Find First One)
|
||
NOT.B D3 ; Flip the order (BF instr start at bit 32 -> )
|
||
ADD.B #32,D3 ; Get the bit number (lsb based)
|
||
|
||
MOVE.L (NKSystemInfoPtr),A5 ; Point to the nanokernel SystemInfo record
|
||
ANDI.L #$FF,D1 ; Clear upper bytes of pram byte
|
||
BEQ.S @Chunky ; -> No EDisk
|
||
|
||
MOVE.L PhysicalMemorySize(A5),D2 ; Get physical RAM size
|
||
LSR.L #8,D2 ; Scale the size by 256k chunks
|
||
MULU.L D1,D2 ; Mult Chunks by ChunkCount from PRAM = EDisk size
|
||
ADD.L #$7FFF,D2 ; Add an extra 32k to the size
|
||
AND.W #$8000,D2 ; Round down to 32k boundary
|
||
CMPI.L #MinRamDiskSize,D2 ; Is this size too small? (user pulled some SIMMs)
|
||
BLO.S @Chunky ; -> Yes, too small. No EDisk
|
||
|
||
MOVE.L #bRamDisk,D0 ; Get the EDisk logical base address
|
||
LSR.L D3,D0 ; Turn the address into a page number
|
||
MOVE.L D0,A0 ; Put the logical page number in A0
|
||
|
||
LSR.L D3,D2 ; Turn the size into a page count
|
||
MOVE.L D2,A1 ; Put page count in A1
|
||
|
||
ADD.W #1,A1 ; (Temp Hack bump up by one to work around nk bug) <SM33>
|
||
;MOVEQ #0,D1 ; Indicate no special alignment necessary
|
||
MOVE.L #16,D1 ; (Temp Hack to get around a nk bug) <SM32>
|
||
_nkAllocateMemory ; Get the RAM and map it where we asked
|
||
|
||
; Now that RAM has been adjusted by the possible allocation of an EDisk, Video frame buffer
|
||
; and/or DMA buffer, we can construct the RAM chunk table that sits at the top of logical RAM.
|
||
; At this point A5 should be pointing to the nanokernel SystemInfo record.
|
||
|
||
@Chunky MOVE.L UsableMemorySize(A5),D1 ; Get the Useable RAM size from NK
|
||
MOVE.L D1,A5 ; Put the size (our Memtop) in A5
|
||
|
||
; Start from the Top down
|
||
LEA -8(A5),A5 ; Leave room for two temp warm start flags <SM31>
|
||
|
||
CLR.L -(A5) ; Old Diag long #3
|
||
CLR.L -(A5) ; Old Diag long #2
|
||
CLR.L -(A5) ; Old Diag long #1
|
||
MOVE.L #-1,-(A5) ; Chunk table terminator
|
||
MOVE.L D1,-(A5) ; Top of usable RAM
|
||
CLR.L -(A5) ; Logical start of RAM
|
||
|
||
MOVE.L A5,A1 ; Put Ptr to chunk table in A1 for MergeDone
|
||
MOVEQ #0,D6 ; Signal no RAM test errors.
|
||
BRA MergeDone ; Set the stack and leave
|
||
|
||
EndWith
|
||
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: GlueMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,d3,a1,a5
|
||
;
|
||
; This routine stitches banks A,B together for the MacII's glue chip decoder. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;_____________________________________________________________________________________________
|
||
GlueMerge ; <9>
|
||
moveq #$0F,d1 ; prepare to mask for size A nibble
|
||
and.b d5,d1 ; get bank A size nibble
|
||
bne.s @sizeBits ; RAM in bank A, leave a1 pointing to bank A start
|
||
addq #8,a1 ; else, advance to bank B's start
|
||
lsr.l #4,d5 ; and move bank B's nibble into lsn
|
||
@sizeBits move.b @VIASizeTable(d1),d0 ; get VIA value
|
||
movea.l VIA2Addr(a0),a5 ; get VIA 2 base
|
||
and.b d0,VBufA(a5) ; stuff in new size bits
|
||
|
||
moveq #(3*4)+(2*8),d1 ; size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
@VIASizeTable
|
||
dc.b $FF ; [0] A size = 0Mb: Start bank B on 64Mb boundary
|
||
dc.b $3F ; [1] A size = 1Mb: Start bank B on 1Mb boundary
|
||
dc.b $FF ; [2] A size = 2Mb: ----
|
||
dc.b $7F ; [3] A size = 4Mb: Start bank B on 4Mb boundary
|
||
dc.b $FF ; [4] A size = 8Mb: ----
|
||
dc.b $BF ; [5] A size =16Mb: Start bank B on 16Mb boundary
|
||
dc.b $FF ; [6] A size =32Mb: ----
|
||
dc.b $FF ; [7] A size =64Mb: Start bank B on 64Mb boundary
|
||
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: MDUMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d3,a1,a5
|
||
;
|
||
; This routine writes the chunk table (containing 1 or 2 entries) at the top of the highest bank,
|
||
; for the Mac IIci's MDU decoder (no stitching possible with this one).
|
||
;_____________________________________________________________________________________________
|
||
MDUMerge ; <9>
|
||
moveq #0,a5 ; no chunk table started yet
|
||
adda.w #16,a1 ; point to end of bank info table
|
||
|
||
@bankLoop tst.b d5 ; any banks left?
|
||
beq MergeDone ; no, exit
|
||
|
||
subq #8,a1 ; point to previous bank
|
||
lsl.l #4,d5 ; yes, shift over next bank
|
||
move.w d5,d1
|
||
lsr.w #8,d1 ; get bank nibble
|
||
andi.b #$0F,d1 ; mask it
|
||
beq.s @bankLoop ; no bank, try next
|
||
|
||
BSR6 expandSize ; convert nibble size (in d1) --> real size (in d0)
|
||
move.l a5,d1 ; already started table?
|
||
bne.s @writeChunk ; yes, then don't write tail
|
||
move.l (a1),a5 ; get base of bank
|
||
adda.l d0,a5 ; point to end of bank
|
||
clr.l -(a5) ; clear test space
|
||
clr.l -(a5) ; clear test space
|
||
move.l #-1,-(a5) ; write FFFFFFFF
|
||
@writeChunk move.l d0,-(a5) ; write size (0nn00000)
|
||
move.l (a1),-(a5) ; write start (0x000000)
|
||
bra.s @bankLoop
|
||
|
||
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: FMCMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d2,a1,a5
|
||
;
|
||
; This routine stitches banks A,B together for the Mac IIfx's FMC decoder. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;_____________________________________________________________________________________________
|
||
FMCMerge ; <9>
|
||
move.w #FMCInit,d1 ; get initial FMC value (assuming no Parity)
|
||
btst.l #RPUExists,d0 ; do we have parity?
|
||
beq.s @cont ; no, we're ok
|
||
move.w #FMCRPUInit,d1
|
||
@cont move.w d1,d0
|
||
|
||
moveq #$0F,d1 ; prepare to mask for size A nibble
|
||
and.b d5,d1 ; get A size nibble
|
||
bne.s @sizeBits ; yes, leave a1 pointing to bank A start
|
||
addq #8,a1 ; else, advance to bank B's start
|
||
lsr.l #4,d5 ; and move bank B's nibble into lsn
|
||
@sizeBits and.b @FMCSizeTable(d1),d0 ; 'or' in FMC size bits
|
||
|
||
movea.l FMCAddr(a0),a5 ; get the FMC base address
|
||
moveq.l #16-1,d1 ; loop counter to load 16 bits <13>
|
||
@FMCload move.b d0,FMCConfig(a5) ; load in a bit
|
||
lsr.w #1,d0 ; put next bit into position
|
||
dbra d1,@FMCload ; repeat till all bits loaded <13>
|
||
st.b FMCLatch(a5) ; latch the config data
|
||
|
||
@writeTable
|
||
moveq #(3*4)+(2*8),d1 ; max size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
@FMCSizeTable
|
||
dc.b $FF ; [0] A size = 0Mb: Start bank B on 64Mb boundary
|
||
dc.b $FF ; [1] A size = 1Mb: ----
|
||
dc.b $FF ; [2] A size = 2Mb: ----
|
||
dc.b $3F ; [3] A size = 4Mb: Start bank B on 4Mb boundary
|
||
dc.b $7F ; [4] A size = 8Mb: Start bank B on 8Mb boundary
|
||
dc.b $BF ; [5] A size =16Mb: Start bank B on 16Mb boundary
|
||
dc.b $FF ; [6] A size =32Mb: ----
|
||
dc.b $FF ; [7] A size =64Mb: Start bank B on 64Mb boundary
|
||
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: OrwellMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks (we only use the lower 4)
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d4,d6,a3,a5
|
||
;
|
||
; This routine stitches banks A,B,C,D together for Eclipse's Orwell decoder. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;_____________________________________________________________________________________________
|
||
WITH ProductInfo
|
||
|
||
OrwellMerge ; <CCH>
|
||
IF forSTP601 THEN ; <SM46>
|
||
WITH NKSystemInfo ; <SM46>
|
||
|
||
; Start <SM48>
|
||
; Read PRAM to see if the user wants an EDisk. If the size is > MinRamDiskSize
|
||
; then ask thenanokernel for some RAM.
|
||
MOVE.L A2,D6 ; Save SizeMem's return address
|
||
|
||
MOVEQ.L #0,D7 ; Memory that might get used for RAM disk
|
||
|
||
LongBSR6 GetHardwareInfo ; Get universal info again
|
||
MOVE.L DecoderInfo.VIA1Addr(A0),A2 ; Get VIA1's base address for RdXByte
|
||
|
||
MOVE.W #ramDiskPramAddr,D1 ; Get the EDisk PRAM byte constant
|
||
BSR6 RdXByte ; Read the EDisk size (in % of total RAM) in D1
|
||
MOVE.L D6,A2 ; Restore the return address>
|
||
|
||
; Get the MMU page size from the nanokernel.Count bits in the result to get a shift factor
|
||
|
||
MOVEQ #0,D3 ; Clear D3
|
||
MOVE.L ([ProcessorInfoPtr],ProcessorInfo.PageSize),D0 ; Get the Page size from the nano-k
|
||
BFFFO D0{15:15},D3 ; Get the shift factor (Find First One)
|
||
NOT.B D3 ; Flip the order (BF instr start at bit 32 -> )
|
||
ADD.B #32,D3 ; Get the bit number (lsb based)
|
||
|
||
MOVEQ #0,D5 ; Clear the EDisk allocation size
|
||
MOVE.L (NKSystemInfoPtr),A5 ; Point to the nanokernel SystemInfo record
|
||
ANDI.L #$FF,D1 ; Clear upper bytes of pram byte
|
||
BEQ.S @AfterRAMDiskCheck ; -> No EDisk
|
||
|
||
MOVE.L PhysicalMemorySize(A5),D2 ; Get physical RAM size
|
||
LSR.L #8,D2 ; Scale the size by 256k chunks
|
||
MULU.L D1,D2 ; Mult Chunks by ChunkCount from PRAM = EDisk size
|
||
ADD.L #$7FFF,D2 ; Add an extra 32k to the size
|
||
AND.W #$8000,D2 ; Round down to 32k boundary
|
||
CMPI.L #MinRamDiskSize,D2 ; Is this size too small? (user pulled some SIMMs)
|
||
BLO.S @AfterRAMDiskCheck ; -> Yes, too small. No EDisk
|
||
CMPI.L #MaxRamDiskSize,D2 ; Is it too big?>
|
||
BHI.S @AfterRAMDiskCheck ; -> Yes, too big. No EDisk
|
||
|
||
MOVE.L LogicalMemorySize(A5),D0 ; Get the logical size (Phys - nk private stuff)
|
||
|
||
@CheckMinHeap
|
||
SUB.L D2,D0 ; Subtract the EDisk size
|
||
CMP.L #MinHeapSize,D0 ; Will we have at least MinHeapSize free after the EDisk?
|
||
BLT.S @AfterRAMDiskCheck ; -> No, do not allocate the EDisk (signed)
|
||
|
||
MOVE.L D2,D5 ; Save the number of bytes used by the EDisk in the chunk table.
|
||
ADD.L D2,D7 ; Add the size to our running allocation counter
|
||
MOVE.L #bRamDisk,D0 ; Get the EDisk logical base address
|
||
LSR.L D3,D0 ; Turn the address into a page number
|
||
MOVE.L D0,A0 ; Put the logical page number in A0
|
||
|
||
LSR.L D3,D2 ; Turn the size into a page count
|
||
MOVE.L D2,A1 ; Put page count in A1
|
||
|
||
MOVEQ #0,D1 ; Indicate no special alignment necessary
|
||
_nkAllocateMemory ; Get the RAM and map it where we asked
|
||
|
||
@AfterRAMDiskCheck
|
||
; End <SM48>
|
||
|
||
MOVE.L (NKSystemInfoPtr),A5 ; Point to the nanokernel SystemInfo record <SM46>
|
||
MOVE.L UsableMemorySize(A5),D1 ; Get the Useable RAM size from NK <SM46>
|
||
MOVE.L D1,A5 ; Put the size (our Memtop) in A5 <SM46>
|
||
|
||
; Start from the Top down <SM46>
|
||
MOVE.L D7,-(A5) ; Put total allocation at the top of L RAM. <SM46>
|
||
MOVE.L #$52555348,-(A5) ; Old Unused Diag long #3 <SM46>
|
||
MOVE.L #$6E757320,-(A5) ; Old Unused Diag long #2 <SM46>
|
||
MOVE.L #$4379676E,-(A5) ; Old Unused Diag long #1 <SM46>
|
||
MOVE.L #-1,-(A5) ; Chunk table terminator <SM46>
|
||
MOVE.L D1,-(A5) ; Top of usable RAM <SM46>
|
||
CLR.L -(A5) ; Logical start of RAM <SM46>
|
||
|
||
MOVE.L A5,A1 ; Put Ptr to chunk table in A1 for MergeDone<SM46>
|
||
MOVEQ #0,D6 ; Signal no RAM test errors. <SM46>
|
||
BRA MergeDone ; Set the stack and leave <SM46>
|
||
ENDWITH ; <SM46>
|
||
ENDIF ; <SM46>
|
||
|
||
IF forSmurf THEN
|
||
bra HMCMerge ; >>SKIP this <SM5> <SM20>
|
||
ENDIF
|
||
|
||
move.w d5,d1 ; get a copy of the size for 4 banks
|
||
swap d5 ; put a copy in msw of d5
|
||
move.w d1,d5 ; and put a copy in the lsw of d5 too
|
||
move.l a1,d6 ; save productinfo ptr for later
|
||
movea.l #0,a3 ; clear memory counter
|
||
move.l #0,d3 ; start with bank 0 (bank A)
|
||
bra.s @bankMapped ; no need to map bank A
|
||
;
|
||
; This code maps the current bank to begin immediately after the previous bank.
|
||
; It loads Orwell's bank configuration registers, but does not latch them in.
|
||
;
|
||
; a3.l - offset to map current bank at
|
||
; d3.l - bank which we are currently mapping
|
||
;
|
||
@mergeLoop ; LOOP
|
||
move.l d3,d1 ; get current bank number
|
||
subq.l #1,d1 ; adjust so Bank 1 has zero offset
|
||
mulu.l #OrBankFieldSize,d1 ; get bit position in register for this bank
|
||
move.l DecoderAddr(a0),a5 ; get base addr of Orwell <SM7>
|
||
lea (OrBankBCfgAddr,a5,d1.w*4),a5 ; get base address of bank field for this bank
|
||
move.l a3,d1 ; get addr to map this bank to
|
||
move.l #22,d4 ; bits to shift to get Orwell config value
|
||
lsr.l d4,d1 ; d1 contains config value for this bank
|
||
move.w #OrBankFieldSize-1,d4 ; size of field to load
|
||
@loadCfgReg move.l d1,(a5)+ ; load a bit
|
||
lsr.l #1,d1 ; get next bit into position
|
||
dbra d4,@loadCfgReg ; continue until entire field is loaded
|
||
;
|
||
; Latch the value we just put into Orwell in.
|
||
;
|
||
movea.l DecoderAddr(a0),a5 ; get base address of Orwell <SM7>
|
||
lea OrLoadBanks(a5),a5 ; get address of latch location
|
||
move.b #$ff,(a5) ; latch bank config values in <14>
|
||
;
|
||
; Increment offset to map next bank to and point to next chunk. Continue loop if not finished.
|
||
;
|
||
@bankMapped
|
||
move.l #$0F,d1 ; mask for size nibble of current bank
|
||
and.b d5,d1 ; get size nibble for current bank
|
||
lsr.l #4,d5 ; shift size of next bank into low nibble <14>
|
||
BSR6 expandSize ; nibble size (in d1) --> real size (in d0)
|
||
adda.l d0,a3 ; calc total amount of memory so far
|
||
@contLoop
|
||
tst.l 8(a1) ; are we at the last bank?
|
||
bmi.s @mergeDone ; >>EXITLOOP if so
|
||
adda.l #8,a1 ; bump chunk pointer to next entry
|
||
addq.l #1,d3 ; bump bank number
|
||
bra.s @mergeLoop ; ENDLOOP
|
||
;
|
||
; Write chunk table at the end of RAM. After merging, RAM looks like one big chunk starting at zero.
|
||
;
|
||
@mergeDone
|
||
move.l a3,d3 ; get a copy of total amount of memory <14>
|
||
move.l d6,a1 ; restore productinfo ptr <14>
|
||
@endMerge moveq #(3*4)+(4*8),d1 ; size of chunk table for this decoder <14>
|
||
|
||
bra writeChunkTable ; and exit <14>
|
||
|
||
ENDWITH
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: SonoraMerge <SAM>
|
||
;
|
||
; Inputs: D0 - bases valid bits
|
||
; D2 - chunk size for this decoder
|
||
; D3 - total size of RAM in system
|
||
; D5 - nibble sizes for up to 8 banks
|
||
; A0 - ptr to table of base addresses
|
||
; A1 - ptr to universal RAMInfo table (first entry)
|
||
; A2 - SizeMem return address
|
||
;
|
||
; Outputs: A5 - points to the chunk table
|
||
;
|
||
; Destroys: D0-D4,D6,A3,A5
|
||
;
|
||
; This routine stitches banks A,B,C,D and E together and sets the SIMM size
|
||
; bits for the two SIMM sockets for the Sonora decoder.
|
||
; It then writes the chunk table at the top of RAM.
|
||
;__________________
|
||
;
|
||
; Weirdness Notes:
|
||
;
|
||
; Supports two SIMMs. Each with at most two banks of RAM.
|
||
;
|
||
; Carnation/Vail machines that have any RAM in bank 0/A (built-in) must have the "Bank0Size" bit
|
||
; in the RAM Config register set to 1.
|
||
;
|
||
; Assumptions:
|
||
; If there is no RAM in the first bank of each SIMM, then the other bank is assumed empty as well.
|
||
; If RAM is found in the second bank of a SIMM it is assumed to be the same size as
|
||
; the first bank.
|
||
;
|
||
;_____________________________________________________________________________________________
|
||
|
||
RAMCfgBank0Size EQU 6 ; Sonora RAMConfig Bank0Size Bit. 1=Onboard RAM for Carnation
|
||
|
||
SonoraMerge MOVE.L D2,A5 ; Save D2 for later <H6><SM12>
|
||
MOVEQ #1,D4 ; SIMM loop counter <H4><SM12>
|
||
MOVEQ #(1<<RAMCfgBank0Size),D6 ; Assume RAM in bank 0.
|
||
|
||
MOVE.L D5,D1 ; Get a copy of the Nibble/Bank count
|
||
AND.B #$0F,D0 ; Get Bank A's nibble count
|
||
BNE.S @noBank0 ; -> No RAM in bank 0/A
|
||
|
||
BCLR.L #RAMCfgBank0Size,D6 ; If no RAM in bank 0 clear the Bank0Size Bit
|
||
@noBank0
|
||
LSR.L #4,D1 ; Look at next bank
|
||
|
||
@SIMMLupe MOVE.B D1,D0 ; Copy two nibbles
|
||
AND.B #$0F,D0 ; Strip the upper nibble
|
||
BEQ.S @noRAMBank1 ; -> branch if no RAM in the first bank of this SIMM
|
||
|
||
MOVE.B D1,D2 ; Copy two nibbles
|
||
AND.B #$F0,D2 ; Strip the lower nibble
|
||
BEQ.S @NoRAMbank2 ; -> No RAM in the second bank of this SIMM
|
||
|
||
ADDQ #1,D0 ; Both banks filled. Assume both same size. Bump the SIMM size
|
||
@noRAMbank2 OR.B D0,D6 ; Put this SIMM size in the Cfg reg
|
||
|
||
@noRAMbank1 ROR.B #3,D6 ; Rotate the Cfg reg to prep for setting SIMM1 size
|
||
LSR.L #4*2,D1 ; Shift the Bank sizes reg two banks right
|
||
DBRA D4,@SIMMLupe ; Do this twice (once for each SIMM)
|
||
ROR.B #2,D6 ; Put the config reg back where it belongs
|
||
|
||
@Done MOVE.L A5,D2 ; restore D2 <H6><SM12>
|
||
MOVE.L RBVAddr(A0),A5 ; Get RBV (Sonora's VIA2) Base Addr <H2><SM12>
|
||
MOVE.B SonoraRAMSize(A5),D0 ; Get the Cfg Reg
|
||
AND.B #$80,D0 ; Mask out all but the HiBit (Slot16MHz)
|
||
OR.B D0,D6 ; Put the Slot16MHz into our SIMM size and Bank0Size byte
|
||
MOVE.B D6,SonoraRAMSize(A5) ; Set the SIMM size & Stich the banks together (magic)
|
||
|
||
MOVEQ #(3*4)+(5*8),D1 ; size of chunk table for this decoder (3 longs + 5 banks)
|
||
BRA writeChunkTable ; write chunk table and exit...
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: YMCAMerge <SM9> fau, start
|
||
;
|
||
; Inputs: D0 - bases valid bits
|
||
; D2 - chunk size for this decoder
|
||
; D3 - total size of RAM in system
|
||
; D5 - nibble sizes for up to 8 banks
|
||
; A0 - ptr to table of base addresses
|
||
; A1 - ptr to universal RAMInfo table (first entry)
|
||
; A2 - SizeMem return address
|
||
;
|
||
; Outputs: A5 - points to the chunk table
|
||
;
|
||
; Destroys: D0-D4,D6,A3,A5
|
||
;
|
||
; This routine stitches banks 0 through 7 and sets the SIMM size
|
||
; bits for the eight banks for the YMCA decoder.
|
||
; It then writes the chunk table at the top of RAM.
|
||
;
|
||
;__________________
|
||
;
|
||
; Weirdness Notes:
|
||
; TBD
|
||
;_____________________________________________________________________________________________
|
||
|
||
YMCAMerge
|
||
Move.w #YMCAMaxSize,d6 ; Max bank size supported by the YMCA in 2^(n-1)* chunksize
|
||
movea.l #0,a3 ; clear memory counter
|
||
Move.l DecoderAddr(A0),A5 ; Get YMCA's Base address <SM11>
|
||
Move.l d5,YMCA_DRAMBank0_A20(a5) ; get the base address for the first bank's A20 register
|
||
|
||
|
||
; d6.w will loop through the supported sizes,from largest to smallest
|
||
; d4.w will have the bank the size is in
|
||
|
||
@NextSize ; LOOP (thru memory sizes)
|
||
Move.l d5,d3 ; Get a running copy of the nibble sizes
|
||
rol.l #4,d3 ; adjust it for the 1st time thru nibble loop
|
||
Moveq #0,d4 ; Counter to loop through 8 nibbles
|
||
Move.l DecoderAddr(A0),A5 ; Get YMCA's Base address <SM11>
|
||
Lea YMCA_DRAMBank0_A20(a5),a5 ; get the base address for the first bank's A20 register
|
||
|
||
@NextNibble ; LOOP (thru banks)
|
||
ror.l #4,d3 ; Get the nibble
|
||
move.w d3,d1 ; we will trash d1
|
||
Andi.w #$000f,d1 ; We only want the lowest nibble
|
||
Cmp.w d6,d1 ; Is this the size we're looking for
|
||
Bne.s @NoSzMatch ; nope
|
||
Swap d4 ; save our counter and use the other word for the shift count & size counter
|
||
Move.w #20,d4 ; # of bits to shift the address to get at the bit we need to program
|
||
Move.l A3,D0 ; get the current amount of memory
|
||
lsr.l d4,D0 ; the boundary reg's consist of A20 thru A26
|
||
Move.w #BankBdryRegSize-1,d4 ; size of boundary address register
|
||
|
||
@loadBdry Ror.l #1,d0 ; Move bit 0 to bit 31
|
||
move.l d0,(a5)+ ; and write it out
|
||
dbra d4,@loadBdry ; continue for all bits
|
||
Move.w #BankSizeRegSize-1,d4 ; size of memory bank
|
||
Move.w d1,d0 ; Get a copy of nibble size in the msw of d1
|
||
Swap d1 ; expand size will trash d1
|
||
Move.w d0,d1 ; both words of d1 contain the nibble size
|
||
BSR6 expandSize ; nibble size (in d1) --> real size (in d0)
|
||
adda.l d0,a3 ; calc total amount of memory so far
|
||
swap d1 ; get d1.w with the nibble size
|
||
|
||
@loadSize Ror.l #1,d1 ; d1 = nibble size = bank size
|
||
move.l d1,(a5)+ ; and write it out
|
||
dbra d4,@loadSize ; continue for all bits
|
||
Swap D4 ; return our bank counter
|
||
bra.s @NextBank ; go look at the next bank
|
||
@NoSzMatch
|
||
Adda.l #40,a5 ; if we didn't match get the base address of the next bank
|
||
@NextBank
|
||
Addq.w #1,d4 ; increment our counter
|
||
Cmpi.w #8,d4 ; Did we loop through the 8 nibbles yet
|
||
bne.s @NextNibble ; ENDLOOP (through banks)
|
||
Dbra d6,@NextSize ; ENDLOOP (through memory sizes)
|
||
|
||
move.l a3,d3 ; get a copy of total amount of memory <14>
|
||
|
||
@Done MOVEQ #(3*4)+(8*8),D1 ; size of chunk table for this decoder (3 longs + 8 banks)
|
||
BRA writeChunkTable ; write chunk table and exit...
|
||
|
||
; <SM9> fau, end
|
||
ALIGN 4
|
||
|
||
; <SM11> fau, start
|
||
YMCAWidthOffsets
|
||
; This table lists the offsets to the YMCA Width base address from the Base Address of the Width Register.
|
||
; It is indexed by bank and provides the offset from YMCA_DRAMwidth0
|
||
|
||
dc.w $0 ; Bank 0's offset
|
||
dc.w $4 ; Bank 1's offset
|
||
dc.w $0 ; Bank 2's offset
|
||
dc.w $4 ; Bank 3's offset
|
||
dc.w $8 ; Bank 4's offset
|
||
dc.w $c ; Bank 5's offset
|
||
dc.w $8 ; Bank 6's offset
|
||
dc.w $c ; Bank 7's offset
|
||
|
||
; <SM11> fau, end
|
||
;_____________________________________________________________________________________________
|
||
; Routine: VISAMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,a5
|
||
;
|
||
; This routine stitches banks A,B together for Elsie's VISA decoder. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;
|
||
; Rewritten 5/12/92 (<H4>) to work with LC and LCII. This routine now assumes that the <SM4> rb, start
|
||
; @VISASplit code has set the size bits correctly for bank B. All we have to do here
|
||
; is set the size bits for bank A only. Couldn't use old routine because on LC II its
|
||
; possible to have the same total RAM configuration but different size bit settings
|
||
; (i.e. 6MB total = 2 MB on PCB + 2-2 MB SIMMs in bank A OR 4 MB on PCB and 2-1 MB SIMMs).
|
||
;_____________________________________________________________________________________________
|
||
VISAMerge ; <9>
|
||
move.b d5,d1 ; <H5><Begin>
|
||
and.w #$000F,d1 ; get Bank A size nibble
|
||
move.b (@VISASizeTable,d1.w),d1 ; use size as index into table for "real" size
|
||
movea.l RBVAddr(a0),a5 ; get size bits
|
||
and.b #%00111111,VsExp(a5) ; zero out bank A size
|
||
or.b d1,VsExp(a5) ; OR in bank A size we just got from table
|
||
|
||
btst #5,VsExp(a5) ; test size bits to see if 2/4mb in bank B
|
||
bne.s @done ; if 4mb then we need to change RAM info tables
|
||
adda.l #RAMInfoSize+4,a1 ; set a1 to 4mb RAM info table
|
||
|
||
@done
|
||
moveq #(3*4)+(2*8),d1 ; size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
@VISASizeTable
|
||
dc.b $00 ; [0] A size = 0MB
|
||
dc.b -1 ; [1] A size = 1MB illegal
|
||
dc.b $40 ; [2] A size = 2MB
|
||
dc.b $80 ; [3] A size = 4MB
|
||
dc.b $C0 ; [4] A size = 8MB <H5><End><SM4> rb, end
|
||
|
||
ALIGN
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: JAWSMerge/NiagraMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,d4,a5
|
||
;
|
||
; This routine stitches banks A-B-C-D,E-F-G-H together for Waimea's JAWS decoder. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;_____________________________________________________________________________________________
|
||
NiagraMerge
|
||
JAWSMerge ; <9>
|
||
moveq #0,d4 ; init card size reg
|
||
|
||
moveq #3,d1 ; get our special-case value (2 Meg, 1 chunk) <4>
|
||
cmp.l d1,d5 ; does bank A have it (with bank B=0)? <4>
|
||
bne.s @checkSpec2 ; no, see if bank B is special (with bank A=0) <4>
|
||
moveq #0,d4 ; B-A = 0-2 meg, use the 0 table entry <4>
|
||
bra.s @getTable ; <4>
|
||
|
||
@checkSpec2 swap d1 ; now check bank B for 2 Meg in lowest chunk <4>
|
||
cmp.l d1,d5 ; with bank A=0 <4>
|
||
bne.s @notSpec ; no, use standard lookup <4>
|
||
moveq #$20,d4 ; yes, use B-A = 4-0 meg table entry <4>
|
||
bra.s @getTable ; <4>
|
||
|
||
@notSpec BSR6 @calcSize ; calc bank B size
|
||
BSR6 @calcSize ; calc bank A size
|
||
|
||
moveq #16-3,d0 ; prepare to shift bank A size code into high 3 bits
|
||
lsl.w d0,d4 ; 00000000 00000bbb aaa00000 00000000
|
||
lsr.l d0,d4 ; 00000000 00000000 00000000 00bbbaaa
|
||
@getTable move.b @JAWSSizeTable(d4.w),d0 ; get JAWS size config value
|
||
|
||
movea.l JAWSAddr(a0),a5 ; get ptr to JAWS base
|
||
adda.l #JAWSMemConfigA,a5
|
||
move.b d0,(a5) ; set size reg A
|
||
|
||
lsr.b #2,d0 ; move in next 2 bits
|
||
adda.w #JAWSMemConfigB-JAWSMemConfigA,a5
|
||
move.b d0,(a5) ; set size reg B
|
||
|
||
lsr.b #2,d0 ; move in last 2 bits
|
||
adda.w #JAWSMemConfigC-JAWSMemConfigB,a5
|
||
move.b d0,(a5) ; set size reg C
|
||
|
||
moveq #(3*4)+(8*8),d1 ; size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
;............................................................................................
|
||
|
||
@calcSize movea.l a6,a5 ; keep return address in a5
|
||
moveq #4-1,d1 ; count 4 banks
|
||
@nextNib swap d1 ; keep count in d1.hw
|
||
move.w #$0F,d1
|
||
rol.l #4,d5 ;
|
||
and.b d5,d1 ; get next size nibble
|
||
BSR6 expandSize ; nibble size (in d1) --> real size (in d0)
|
||
add.l d0,d4 ; add to total for this bank
|
||
swap d1 ; get count back
|
||
dbra d1,@nextNib
|
||
|
||
swap d4 ; 000x00n0
|
||
lsr.w #4,d4 ; 000x000n
|
||
|
||
cmpi.b #8,d4 ; was it 8?
|
||
bne.s @done ; no, then we're done
|
||
subq.b #1,d4 ; yes, make it a 7.
|
||
@done jmp (a5) ; and exit
|
||
|
||
|
||
@JAWSSizeTable
|
||
dc.b %00000 ;[000 000] B:0, A:0
|
||
dc.b %00001 ;[000 001] B:0, A:1
|
||
dc.b %00001 ;[000 010] B:0, A:2
|
||
dc.b %00010 ;[000 011] B:0, A:3
|
||
dc.b %00000 ;[000 100] B:0, A:4
|
||
dc.b %00000 ;[000 101] --------
|
||
dc.b %00000 ;[000 110] B:0, A:6
|
||
dc.b %00000 ;[000 111] B:0, A:8
|
||
|
||
dc.b %11111 ;[001 000] B:1, A:0
|
||
dc.b %10011 ;[001 001] B:1, A:1
|
||
dc.b %00011 ;[001 010] B:1, A:2
|
||
dc.b %01010 ;[001 011] B:1, A:3
|
||
dc.b %01001 ;[001 100] B:1, A:4
|
||
dc.b %00000 ;[001 101] --------
|
||
dc.b %00110 ;[001 110] B:1, A:6
|
||
dc.b %01000 ;[001 111] B:1, A:8
|
||
|
||
dc.b %11111 ;[010 000] B:2, A:0
|
||
dc.b %00111 ;[010 001] B:2, A:1
|
||
dc.b %00011 ;[010 010] B:2, A:2
|
||
dc.b %10010 ;[010 011] B:2, A:3
|
||
dc.b %01001 ;[010 100] B:2, A:4
|
||
dc.b %00000 ;[010 101] --------
|
||
dc.b %00110 ;[010 110] B:2, A:6
|
||
dc.b %01000 ;[010 111] B:2, A:8
|
||
|
||
dc.b %11101 ;[011 000] B:3, A:0
|
||
dc.b %00100 ;[011 001] B:3, A:1
|
||
dc.b %00100 ;[011 010] B:3, A:2
|
||
dc.b %11001 ;[011 011] B:3, A:3
|
||
dc.b %10001 ;[011 100] B:3, A:4
|
||
dc.b %00000 ;[011 101] --------
|
||
dc.b %01110 ;[011 110] B:3, A:6
|
||
dc.b %11000 ;[011 111] B:3, A:8
|
||
|
||
dc.b %10111 ;[100 000] B:4, A:0
|
||
dc.b %01001 ;[100 001] B:4, A:1
|
||
dc.b %00101 ;[100 010] B:4, A:2
|
||
dc.b %01111 ;[100 011] B:4, A:3
|
||
dc.b %11011 ;[100 100] B:4, A:4
|
||
dc.b %00000 ;[100 101] --------
|
||
dc.b %10110 ;[100 110] B:4, A:6
|
||
dc.b %00000 ;[100 111] B:4, A:8
|
||
|
||
dc.b %00000 ;[101 000] --------
|
||
dc.b %00000 ;[101 001] --------
|
||
dc.b %00000 ;[101 010] --------
|
||
dc.b %00000 ;[101 011] --------
|
||
dc.b %00000 ;[101 100] --------
|
||
dc.b %00000 ;[101 101] --------
|
||
dc.b %00000 ;[101 110] --------
|
||
dc.b %00000 ;[101 111] --------
|
||
|
||
dc.b %10111 ;[110 000] B:6, A:0
|
||
dc.b %01011 ;[110 001] B:6, A:1
|
||
dc.b %01011 ;[110 010] B:6, A:2
|
||
dc.b %01100 ;[110 011] B:6, A:3
|
||
dc.b %10100 ;[110 100] B:6, A:4
|
||
dc.b %00000 ;[110 101] --------
|
||
dc.b %11010 ;[110 110] B:6, A:6
|
||
dc.b %00000 ;[110 111] B:6, A:8
|
||
|
||
dc.b %10111 ;[111 000] B:8, A:0
|
||
dc.b %01101 ;[111 001] B:8, A:1
|
||
dc.b %01101 ;[111 010] B:8, A:2
|
||
dc.b %10101 ;[111 011] B:8, A:3
|
||
dc.b %10111 ;[111 100] B:8, A:4
|
||
dc.b %00000 ;[111 101] --------
|
||
dc.b %10111 ;[111 110] B:8, A:6
|
||
dc.b %00000 ;[111 111] B:8, A:8
|
||
|
||
|
||
|
||
; <22> rb, from Terror for DBLite
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: MSCMerge
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,a5
|
||
;
|
||
; This routine stitches banks A-H together for DB-Lite's MSC controller. It then writes
|
||
; the chunk table at the top of RAM. RAM banks 4-7 can either contain 2MB or 8MB of RAM.
|
||
; If bank 4 doesn't have 8MB of RAM, we'll assume the rest don't and clear the MSCBank8M
|
||
; bit in the MSC configuration register.
|
||
;
|
||
; Bank A is always 2MB
|
||
; Bank B is always 2MB
|
||
; Bank C can be 0 or 2
|
||
; Bank D can be 0 or 2
|
||
; Bank E can be 0 or 2 or 8
|
||
; Bank F can be 0 or 2 or 8
|
||
; Bank G can be 0 or 2 or 8
|
||
; Bank H can be 0 or 2 or 8
|
||
;_____________________________________________________________________________________________
|
||
|
||
MSCMerge ; <T7>
|
||
bfffo d5{0:31},d1 ; find the highest bit (bank) set <H5><SM12>
|
||
neg.b d1 ; <H5><SM12>
|
||
add.b #32,d1 ; <H5><SM12>
|
||
asl.b #MSCSize0-2,d1 ; / bank size = highest bank # (upper 3 bits) <H5><SM12>
|
||
ori.b #(1<<MSC25MHz)|(1<<MSCEconoBit)|(1<<MSCFastROM)|(1<<3)|(1<<MSCBank8M),d1 ; <H5><SM12>
|
||
|
||
moveq #$0F,d0 ; find out how much in bank 4 <H5><SM12>
|
||
swap d0 ; <H5><SM12>
|
||
and.l d5,d0 ; <H5><SM12>
|
||
swap d0 ; nibble size in low byte <H5><SM12>
|
||
subq.b #$03,d0 ; check for 8 MB <H5><SM12>
|
||
beq.s @TwoMegBanks ; <H5><SM12>
|
||
bclr #MSCBank8M,d1 ; not 8 MB, clear our Bank8M enable <H5><SM12>
|
||
@TwoMegBanks
|
||
movea.l RBVAddr(a0),a5 ; get ptr to MSC (same as RBV's) <H3>
|
||
and.b d1,MSCConfig(a5) ; set MSC size bits <H2><H5><SM12>
|
||
|
||
@done moveq #(3*4)+(8*8),d1 ; size of chunk table for this decoder <H14><SM12>
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: PrattMerge <SM15>
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,d4,a5
|
||
;
|
||
; This routine stitches banks A-F together for the Pratt controller. It then writes
|
||
; the chunk table at the top of RAM.
|
||
;
|
||
; Onboard RAM:
|
||
; Bank A can be 0,2,4,or 8MB
|
||
; Bank B can be 0,2,4,or 8MB
|
||
; If 2MB banks, then there must be two banks, for a total of 4MB
|
||
; If 4MB banks, then one or two banks allowed, for either 4MB or 8MB
|
||
; If 8MB bank, then one or two banks allowed, for either 8MB or 16MB
|
||
;
|
||
; Expansion RAM:
|
||
; Banks C,D,E,F can have 0,2,4,or 8MB.
|
||
; All expansion banks with RAM in them must be the same size. Banks must be loaded in order.
|
||
;
|
||
;_____________________________________________________________________________________________
|
||
PrattMerge ;
|
||
|
||
; find out which banks have memory
|
||
; input: d5.l -- each non-zero nibble means corresponding bank has memory
|
||
; output: d4.b -- each non-zero bit means corresponding bank has memory, bits 0-5
|
||
;
|
||
movea.l d5,a5 ; save a copy of nibble sizes
|
||
moveq #0,d0 ; initialize count
|
||
move.b #PrattBankBits,d4 ; load initial mask for RAM Configuration Register (in Pratt)
|
||
@bankloop move.b d5,d1 ; get copy of nibble sizes
|
||
andi.b #$0F,d1 ; look at low nibble
|
||
bne.s @next ; nibble non-zero -> memory in bank, so leave bit set
|
||
bclr d0,d4 ; no memory in this bank, so clear bit
|
||
@next lsr.l #4,d5 ; look at next nibble
|
||
addq #1,d0 ; inc nibble count
|
||
cmpi.b #PrattNumbanks-1,d0 ; have we looked at all the banks?
|
||
ble.s @bankloop
|
||
move.l a5,d5 ; restore copy of nibble sizes
|
||
|
||
; figure out the onboard configuration (Banks A and B)
|
||
; output: d1 has the onboard memory bank bit configuration bits configured
|
||
;
|
||
move.b #PrattDensBits,d1 ; load initial mask for RAM Density Register (in Pratt)
|
||
move.l d5,d0 ; get copy of nibble sizes
|
||
andi.l #$0000000F,d0 ; find out how much in bank 0
|
||
bne.s @check2 ; more than 0 MB, go check for 2
|
||
andi.b #Pratt0MBbank,d1 ; there is no RAM on the daughter card
|
||
bra.s @getExpMem
|
||
@check2 cmpi.l #1,d0 ; check for 2 MB (nibble size = 1 for 2MB chunksize)
|
||
bne.s @check4 ; more than 2MB, go check for 4
|
||
andi.b #Pratt2MBbank,d1 ; there are 2MB
|
||
bra.s @getExpMem ;
|
||
@check4 cmpi.l #2,d0 ; check for 4MB (nibble size = 2 for 2MB chunksize)
|
||
bne.s @set8 ; more than 4MB, must be 8
|
||
andi.b #Pratt4MBbank,d1 ; there are 4 MB
|
||
bra.s @getExpMem
|
||
@set8 andi.b #Pratt8MBbank,d1 ; set 8 MB bank size
|
||
|
||
; find out size of expansion memory banks
|
||
; output: d1 has the expansion memory bank size bit configured
|
||
;
|
||
@getExpMem move.l #$00000F00,d0 ; find out how much in bank C (D,E,F must be the same size)
|
||
and.l d5,d0 ; the formula is (2^(n-1) * 2) MB where "n" is the nibble value
|
||
bne.s @check2e
|
||
andi.b #Pratt0MBExBank,d1
|
||
bra.s @writeConfigRegs
|
||
@check2e cmpi.l #$00000100,d0 ; check for 2 MB (nibble size = 1)
|
||
bne.s @check4e
|
||
andi.b #Pratt2MBExBank,d1
|
||
bra.s @writeConfigRegs
|
||
@check4e cmpi.l #$00000200,d0 ; check for 4 MB (nibble size = 2)
|
||
bne.s @set8e
|
||
andi.b #Pratt4MBExBank,d1
|
||
bra.s @writeConfigRegs
|
||
@set8e andi.b #Pratt8MBExBank,d1 ; set config for 8MB banks on the expansion card
|
||
|
||
@writeConfigRegs
|
||
movea.l PrattAddr(a0),a5 ; get ptr to Pratt <SM16>
|
||
IF forRomulator THEN
|
||
TestInRAM a0 ; are we in RAM?
|
||
bne.s @done ; yes, then don't really muck with RAM Config registers
|
||
ENDIF
|
||
move.b d1,PrattRAMDensity(a5) ; set Pratt RAM density register value
|
||
move.b d4,PrattRAMConfig(a5) ; set Pratt RAM config register value
|
||
bset.b #0,PrattRefresh(a5) ; set Pratt Refresh rate to be generated every 33 clocks.
|
||
|
||
@done moveq #(3*4)+(6*8),d1 ; size of chunk table for this decoder
|
||
bra writeChunkTable ; write chunk table and exit...
|
||
|
||
|
||
;_____________________________________________________________________________________________ <H7> thru next <H7>
|
||
; Routine: djMEMCMerge <SM12>begin
|
||
;
|
||
; Inputs: d0 - bases valid bits
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks (Banks 0 thru 7)
|
||
; d6 - nibble sizes for an additional 8 banks (Banks 8 thru 15)
|
||
; a0 - ptr to table of base addresses
|
||
; a1 - ptr to universal RAMInfo table (first entry)
|
||
; a2 - SizeMem return address
|
||
;
|
||
; Outputs: a5 - points to the chunk table
|
||
;
|
||
; Destroys: d0-d1,a5
|
||
;
|
||
; NOTE: If you made it here, then D6 should be zero (no errors encountered during SizeBanks). <H8>
|
||
; If that's true, then if D6 EXITS this code also being zero, then we should be able <H8>
|
||
; to abuse it during this part of the code. <H8>
|
||
;_____________________________________________________________________________________________
|
||
|
||
WITH ProductInfo
|
||
|
||
djMEMCMerge
|
||
IF forSmurf THEN
|
||
bra HMCMerge ; >>SKIP this <SM5> <SM20>
|
||
ENDIF
|
||
|
||
LEA MEMCAddr+MEMCDRAMCfg0,A0 ; Point A0 to the first bank's Cfg reg
|
||
|
||
MOVEQ #0,D0
|
||
SUBA.L A3,A3 ; A3 = 0
|
||
MOVEQ #dj_MaxBanks-1,D1 ; # of banks minus 1 <H8>
|
||
|
||
@Loop MOVE.L A3,D4 ; Get running size in D4
|
||
SWAP D4 ; Poor man's BFEXTU D4{22:8},D4
|
||
LSR.W #6,D4
|
||
|
||
MOVE.L (A0),D0
|
||
MOVE.B D4,D0 ; Move bits 22-29 of addrs into bits 7-0 of cfg reg
|
||
MOVE.L D0,(A0)+
|
||
|
||
MOVEQ #$0F,D4 ; Nibble mask
|
||
CMPI.B #2-1,D1 ; Are we on the first set of 8 banks?
|
||
BHI.S @D5 ; -> Yes, use D5 for the first 8
|
||
|
||
@D6 AND.B D6,D4 ; Get the nibble (banks 8 thru 15)
|
||
ROR.L #4,D6 ; prep for next time
|
||
BRA.S @Comm
|
||
|
||
@D5 AND.B D5,D4 ; Get the nibble (banks 0 thru 7)
|
||
ROR.L #4,D5 ; Roll around for next time
|
||
|
||
@Comm TST.B D4 ; Any RAM in this bank?
|
||
BEQ.S @NextOne ; -> Nope, lupe sum more
|
||
|
||
SUBQ #1,D4 ; Multiplying by powers of 2 (start at 2^1)
|
||
MOVE.L D2,D0 ; chunkSize
|
||
LSL.L D4,D0 ; This bank's size in bytes
|
||
|
||
ADD.L D0,A3 ; Add this bank's size to the running total
|
||
@NextOne DBRA D1,@Loop
|
||
ROL.L #8,D6 ; Fix D6 (contains only 2 banks, but should be in LSB)
|
||
|
||
MOVE.L A3,D0 ; Get total RAM in d0
|
||
SWAP D0 ; Poor man's BFEXTU D4{22:8},D4
|
||
LSR.W #6,D0
|
||
MOVE.L D0,MEMCAddr+MEMCmemTop ; Move bits 22-29 of addrs into bits 7-0 of MemTop reg
|
||
|
||
; -----------------------------------------------------------------------------------------
|
||
;
|
||
; Put in interleave enabling code HERE.
|
||
;
|
||
; It must go here because if you turn it on after the chunk table is built, interleaving
|
||
; "scrambles" the banks and the chunk table would get scrambled as well.
|
||
;
|
||
; At this point, we can thrash A0
|
||
;
|
||
; Bank information is stored in D5 & D6. D5 = banks 0-7, D6 = banks 8&9
|
||
; Organization of D5 and D6 is:
|
||
;
|
||
; +-------------------------------------------------------+
|
||
; | bank | bank | bank | bank | bank | bank | bank | bank |
|
||
; | 7 | 6 | 5 | 4 | 3 | 2 | 1/9 | 0/8 | D5/D6 bank value positions
|
||
; +-------------------------------------------------------+
|
||
; -----------------------------------------------------------------------------------------
|
||
|
||
IF forRomulator THEN ; if you're running a ROM in RAM, you dont EVER <H15><SM10>
|
||
bra @skipInterleave ; want to turn on interleaving. it could make your day <H15><SM10>
|
||
ENDIF ; very unhappy <H15><SM10>
|
||
; Only allow interleave enable on djMEMC versions > 0. <H10> thru next <H10><SM10>
|
||
; Version 0 parts cause the machine to lock up if interleaving is enabled.
|
||
|
||
lea MEMCAddr+MEMCIntleaveEnable,a0; get interleave enable reg. address
|
||
moveq #$0E,d0 ; mask for djMEMC version number, shifted 1 bit to the left
|
||
rol.l #8,d0 ; shift mask to correct location
|
||
and.l (a0),d0 ; check djMEMC version
|
||
beq.s @skipInterleave ; IF djMEMC_Version != 0 THEN <H10><SM10>
|
||
|
||
; make sure banks are the same size first
|
||
|
||
move.l d5,d1 ; get 1st 8 banks info
|
||
move.l d1,d0
|
||
ror.l #4,d0 ; such that d0 = (d1 >> 4), or bank pairs in same bit positions
|
||
eor.l d0,d1 ; XOR them to see if they're the same
|
||
andi.l #$0F0F0F0F,d1 ; AND to get only bottom nibble of each byte
|
||
moveq.l #1,d0 ; starting bit of bank 0&1 in interleave reg.
|
||
move.l (a0),d4 ; get current OneBufferedBit value from interleave reg.
|
||
andi.w #$FFE0,d4 ; force the Interleaved bank bits to be unset
|
||
@chkNextPair
|
||
tst.b d5 ; test this bank PAIR
|
||
beq.s @nextpair ; BRIF both banks empty
|
||
tst.b d1 ; test if both banks EQUAL
|
||
bne.s @nextpair ; IF BankX == BankX+1 THEN
|
||
or.w d0,d4 ; set appropriate bit
|
||
@nextpair ; ENDIF
|
||
ror.l #8,d5 ; point to next bank pair
|
||
ror.l #8,d1 ; point to next XORed bank-pair results
|
||
rol.l #1,d0 ; rotate bit to next interleave bit
|
||
cmpi.b #%10000,d0 ; checking banks 8&9 yet?
|
||
bne.s @chkNextPair ; if still working with banks 0-7
|
||
|
||
; if you're here, then we need to test banks 8&9, found in D6.
|
||
|
||
tst.b d6 ; are both banks empty?
|
||
beq.s @setInterleave ; IF Bank8&9 != EMPTY
|
||
move.b d6,d1 ; get info for bank 8
|
||
move.b d1,d0 ; &9
|
||
andi.b #$0F,d1 ; isolate bank 8
|
||
ror.b #4,d0 ; align them so nibbles for 8&9 are the same
|
||
andi.b #$0F,d0 ; isolate bank 9
|
||
cmp.b d0,d1 ; check if bank 8 is same size as bank 9
|
||
bne.s @setInterleave ; IF Bank8 == Bank9 THEN
|
||
ori.b #%10000,d4 ; set bit for banks 8&9
|
||
@setInterleave ; ENDIF
|
||
move.l d4,(a0) ; and write it out to the interleave config reg.
|
||
|
||
@skipInterleave ; ENDIF <H10><SM12>
|
||
MOVEQ #(3*4)+(10*8),D1 ; size of chunk table for this decoder (3 longs + 10 banks)
|
||
BRA newWriteChunkTable ; write chunk table and exit... (ext nibbles in D6)
|
||
|
||
|
||
ENDWITH
|
||
; ----------------------------------------------------------------------------------------- <H7>
|
||
|
||
align 2 ; <SM12>
|
||
|
||
;_____________________________________________________________________________________________
|
||
; Routine: expandSize
|
||
;
|
||
; Inputs: d1.w - nibble size of this bank
|
||
; d2 - chunk size
|
||
;
|
||
; Outputs: d0 - .nnn...., where n = size in bytes of this bank
|
||
;
|
||
; Destroys: d1
|
||
;
|
||
; This routine converts the nibble size in d1 to a real size (in bytes) in d0, based on a
|
||
; chunk size in d2.
|
||
;_____________________________________________________________________________________________
|
||
expandSize
|
||
moveq #0,d0 ; assume no RAM
|
||
tst.w d1 ; any RAM?
|
||
beq.s @exit ; no, exit
|
||
move.l d2,d0 ; yes, get chunk size
|
||
subq.w #1,d1 ; count it
|
||
lsl.l d1,d0 ; multiply by correct power of 2
|
||
@exit RTS6
|
||
|
||
|
||
|
||
|
||
;=============================================================================================
|
||
;_____________________________________________________________________________________________
|
||
; Routine: writeChunkTable
|
||
;
|
||
; Inputs: a1 - ptr to universal RAMInfo table (first entry)
|
||
; d1 - size of chunk table (including 2 test longs and end of table longword)
|
||
; d2 - chunk size for this decoder
|
||
; d3 - total size of RAM in system
|
||
; d5 - nibble sizes for up to 8 banks
|
||
; d6 - nibble sizes for up to another 8 banks (newWriteChunkTable)
|
||
;
|
||
; Outputs: d0 - .nnn...., where n = size in bytes of this bank
|
||
;
|
||
; Destroys: d1/d5/d6/a7
|
||
;
|
||
; Writes the chunk table at the end of RAM, based on the values passed in. This routine
|
||
; creates a separate entry for each chunk that contains RAM.
|
||
;
|
||
; ¥¥ New Mod <H7> ¥¥ - If you have more than 8 banks, then you should call newWriteChunkTable
|
||
; with the first 8 banks of nibbles in D5 (as usual) and the second (up to) 8 banks of nibbles
|
||
; in D6. The total size of the chuck table should be in D1 (1 entry for each bank plus the
|
||
; test longs at the end of the table - same as always).
|
||
;_____________________________________________________________________________________________
|
||
|
||
writeChunkTable ; <11> <SM12>
|
||
moveq #0,d6 ; clear the extended nibble count for the old guys <H7><SM12>
|
||
newWriteChunkTable ; new entry point for machines with > 8 banks of memory <H7><SM12>
|
||
movea.l (a1),a5 ; get start of bank
|
||
move.l a5,a0 ; running bank start ptr
|
||
adda.l d3,a5 ; point to end of bank
|
||
suba.l d1,a5 ; allocate space for test space/chunk table
|
||
move.l a5,a7 ; remember start of chunk table
|
||
|
||
@loop moveq #$0F,d1 ; prepare to mask for size nibble
|
||
and.b d5,d1 ; get bank size nibble
|
||
beq.s @next ; skip if no RAM in this bank
|
||
BSR6 expandSize ; convert nibble size (in d1) --> real size (in d0)
|
||
move.l a0,(a7)+ ; write start
|
||
move.l d0,(a7)+ ; write length
|
||
add.l d0,a0 ; calculate next start
|
||
@next lsr.l #4,d5 ; shift in next bank nibble
|
||
bne.s @loop ; continue if more banks
|
||
|
||
move.l d6,d5 ; do we have more banks to do? ( > 8) <H7><SM12>
|
||
beq.s @finishup ; -> Nope, no more <H7><SM12>
|
||
clr.l d6 ; clr the extended nibble sizes (so we only do this once) <H7><SM12>
|
||
bra.s @loop ; do more banks <H7><SM12>
|
||
|
||
@finishup subq.l #1,d5 ; = FFFFFFFF <SM12>
|
||
move.l d5,(a7)+ ; write FFFFFFFF (terminator)
|
||
@fill clr.l (a7)+ ; clear test space
|
||
move.w a7,d0 ; at end of bank
|
||
bne.s @fill ; no, keep clearing
|
||
|
||
;.............................................................................................
|
||
MergeDone
|
||
movea.l (a1),sp ; sp := base of RAM
|
||
adda.l #$8000,sp ; sp := base of RAM + 32K
|
||
move.l a5,-(sp) ; push ptr to chunk table on stack
|
||
|
||
;_____________________________________________________________________________________________ <SM12>begin
|
||
;
|
||
; For machines with a sound buffer in high RAM (i.e., ASC-based machines), we'll move the
|
||
; RAM chunk table below the sound buffer. This will avoid collisions with large MMU tables.
|
||
; We need to do this here because SizeMem gets called more than once (by diagnostics), so
|
||
; that, for example, the warmstart flag will be valid across boots.
|
||
;
|
||
; BEFORE AFTER
|
||
;
|
||
; +-------------------+ <-- top of memory --> +-------------------+
|
||
; | RAM chunks | | |
|
||
; |-------------------| | |
|
||
; | | | |
|
||
; | BootGlobs & +-------------------+ +-------------------+
|
||
; | MMU tables | | | |
|
||
; | will grow dow| Sound Buffer | | Sound Buffer |
|
||
; | | | | | |
|
||
; | V +-------------------+ +-------------------+
|
||
; | | | RAM chunks |
|
||
; +-------------------+ |-------------------|
|
||
; | |
|
||
; | BootGlobs & |
|
||
; | MMU tables |
|
||
; | will grow down |
|
||
; | | |
|
||
; | V |
|
||
; | |
|
||
; +-------------------+
|
||
;_____________________________________________________________________________________________
|
||
|
||
MOVE.L A2,D3 ; save the return address <H13>
|
||
MOVEQ #0,D2 ; get the decoder type <H13>
|
||
BigBSR6 GetHardwareInfo,a0 ; <H13>
|
||
MOVEA.L (SP),A6 ; point to the chunk table <H13>
|
||
LEA @Resume,A2 ; (BSR2) <H13>
|
||
BRA.S SizeSoundBuffer ; get the size of a sound buffer in high RAM (if any) <H13>
|
||
@Resume BEQ.S @Done ; -> no sound buffer <H13>
|
||
SUB.L D0,(SP) ; adjust the address of the new chunk table <H13>
|
||
SUB.L A6,D1 ; calculate the size of the chunk table <H13>
|
||
@MoveChunks MOVE.B -(A1),-(A0) ; move the RAM chunk table to its new home <H13>
|
||
SUBQ.L #1,D1 ; <H13>
|
||
BGT.S @MoveChunks ; <H13>
|
||
@Done MOVEA.L D3,A2 ; restore the return address <H13>
|
||
|
||
moveq #0,d6 ; Z flag set to indicate no error(s) <15>
|
||
jmp (a2)
|
||
|
||
|
||
;_____________________________________________________________________________________________
|
||
;
|
||
; Routine: SizeSoundBuffer
|
||
;
|
||
; Inputs: D2.B- decoder type (from Universal)
|
||
; A2 - return address
|
||
; A6 - physical address of RAM chunk table
|
||
;
|
||
; Outputs: D0 - size of sound buffer (zero if none)
|
||
; A0 - pointer to start of sound buffer
|
||
; A1 - pointer to end of RAM
|
||
; A6 - physical address of RAM chunk table
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: returns the starting address and size of a sound buffer in high RAM.
|
||
;_____________________________________________________________________________________________
|
||
|
||
SizeSoundBuffer ; <H13>
|
||
LEA @bufSizeTbl-4,A1
|
||
MOVEQ #0,D0 ; assume no sound buffer in high RAM
|
||
@FindDecoder
|
||
ADDQ.W #4,A1 ; skip over the previous routine offset
|
||
MOVE.W (A1)+,D0 ; get the next decoder type
|
||
BEQ.S @Done ; -> end of list
|
||
CMP.B D2,D0 ; does the decoder match?
|
||
BNE.S @FindDecoder ; -> no, try the next one
|
||
MOVE.L (A1)+,D0 ; yes, get offset from top of RAM to start of sound buffer
|
||
|
||
MOVEA.L A6,A1 ; point to the start of the chunk table
|
||
BRA.S @FirstChunk ; and start looking
|
||
@FindLastChunk
|
||
ADDQ.W #8,A1 ; skip over the previous chunk start/size
|
||
@FirstChunk TST.L (A1) ; are we at the end of the table?
|
||
BPL.S @FindLastChunk ; -> nope, keep going
|
||
|
||
MOVE.L -(A1),D1 ; calculate the address of the end of the last chunk
|
||
ADD.L -(A1),D1
|
||
MOVEA.L D1,A1 ; and save it
|
||
MOVEA.L D1,A0 ; calculate where the end of the moved chunk table will be
|
||
SUBA.L D0,A0 ; (this is also the start of the sound buffer)
|
||
@Done TST.L D0 ; set the CCR
|
||
JMP (A2)
|
||
|
||
|
||
; IMPORTANT: Because of the way that ConfigureRAM works (in StartInit), the following table sizes must be
|
||
; multiples of 1024.
|
||
@bufSizeTbl DC.W DecoderKinds.MSCDecoder ; MSC
|
||
DC.L (8*1024)
|
||
DC.W DecoderKinds.PrattDecoder ; Pratt (for Blackbird)
|
||
DC.L (32*1024) ; Sound can use a FIFO size up to 32K (includes modem sound buffer)
|
||
|
||
DC.W 0 ; end of list <SM12>end
|
||
|
||
|
||
|
||
END
|