mac-rom/OS/StartMgr/SizeMem.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
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.
2017-12-26 09:52:23 +08:00

2737 lines
119 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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