mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 20:49:19 +00:00
500 lines
17 KiB
Plaintext
500 lines
17 KiB
Plaintext
;
|
||
; File: HALc96HWInit.a
|
||
;
|
||
; Contains: 53c96 Hardware Initialization routines
|
||
;
|
||
; Written by: Paul Wolf
|
||
;
|
||
; Copyright: © 1990-1994 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM31> 2/1/94 chp Add logic to set the clock conversion factor and select/reselect
|
||
; timeout values for MacRISC-style CPUs.
|
||
; <SM30> 11/22/93 pdw Rolling in from <MCxx>.
|
||
; <MC6> 11/8/93 pdw Added support for new Cold Fusions with old parts!
|
||
; <SM29> 11/19/93 chp Don’t call ClearSCSIIRQ for level-sensitive HBAs.
|
||
; <SMG2> 9/29/93 chp Add a test and call to initialize Grand Central DMA hardware.
|
||
; <SM27> 11/7/93 pdw Got rid of forPDMProto around DoWeHaveAMIC3B to help (but not
|
||
; solve) build Bob's build problems.
|
||
; <SM26> 10/29/93 DCB <MC> roll-in.
|
||
; <MC5> 10/28/93 pdw I don't remember.
|
||
; <SM25> 10/14/93 pdw <MC> roll-in.
|
||
; <MC4> 10/12/93 pdw Added support for Synchronous data transfers, rewrote State
|
||
; Machine, message handling etc.
|
||
; <MC3> 10/6/93 pdw Fixed up the forPDMProto stuff.
|
||
; <MC2> 10/4/93 RC Put forPDMProto around AMIC3/2 special code
|
||
; <SM24> 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug
|
||
; stuff.
|
||
; <SM23> 8/13/93 pdw Cleaned up "that shit above".
|
||
; <SM22> 8/12/93 KW conditionalizing smurf branches
|
||
; <SM21> 8/11/93 KW added some branches based on new smurf boxes
|
||
; <SM20> 7/20/93 pdw Pulled out DoWeHaveFastSCSI functionality into an independent
|
||
; routine so that other routines can use it.
|
||
; <SM19> 7/17/93 pdw Did I change something in here?
|
||
; <SM18> 6/29/93 pdw Massive checkins: Change asynchronicity mechanism to CallMachine
|
||
; stack switching mechanism. Adding support for Cold Fusion.
|
||
; Rearranging HW/SW Init code. Some code optimizations.
|
||
; <SM17> 5/25/93 DCB Changed some bsr.s to bsr.w to fix the build.
|
||
; <SM16> 5/25/93 DCB Rollin from Ludwig (The item below)
|
||
; <LW6> 5/21/93 PW Getting Mac's SCSI ID from PRAM instead of hard-coded. (This was
|
||
; a BUG!)
|
||
; <SM15> 5/5/93 PW Converted names to meanies-friendly names. Updated with latest
|
||
; from Ludwig stuff.
|
||
; <LW4> 3/26/93 PW Put explicit bit lists in the InitCFx code instead of using
|
||
; constants from a header file for the whole combination of bits.
|
||
; <LW3> 2/17/93 PW Removed some TERROR tags.
|
||
; <SM14> 4/8/93 DCB Added Initialization code for Wombat class machines..
|
||
; <SM13> 3/29/93 PW Changed handling of CF3: if threshold-8, setting it up here
|
||
; without SaveResidual on, else setting only SaveResidual.
|
||
; <SM12> 3/20/93 PW Unknown changes.
|
||
; <SM11> 1/31/93 PW Update from the latest of Ludwig. Also changes required for PDM
|
||
; (will update Ludwig with these as needed myself).
|
||
; <LW2> 1/27/93 PW Added nonSerializedIO checks and NOPs for PDM support.
|
||
; <SM9> 12/5/92 PW EXPORTed Init53c9xRegs for fix to Reset interrupt bug in Curio.
|
||
; <SM8> 12/3/92 fau Added boxRiscQuadra to the previous DAFBExists change.
|
||
; <SM7> 12/3/92 fau Changed the use of DAFBExists to check for the
|
||
; Spike/Eclipse/Zydeco box flag. Those registers on DAFB are only
|
||
; needed on those machines. Changed the check for BoxCyclone to a
|
||
; TestFor PSCExists (this assumes that only Cyclone type machines
|
||
; have a PSC).
|
||
; <SM6> 10/30/92 DCB Various Interrupt Handling improvements (using the new macros)
|
||
; <SM5> 8/31/92 PW Changed register and command definitions to reflect changes to
|
||
; SCSIEqu53c96.
|
||
; <SM4> 8/24/92 PN Take out CycloneboxEVT1 stuff
|
||
; <SM3> 8/9/92 CCH Modified boxflag check for Quadras to include RISC Quadras.
|
||
; <SM2> 7/28/92 PW Resolved differences in sources.
|
||
; <SM2> 7/27/92 PW Got DMA working.
|
||
; <SM1> 7/27/92 PW Virtually initial check-in.
|
||
;
|
||
;==========================================================================
|
||
|
||
|
||
MACHINE MC68020 ; '020-level
|
||
BLANKS ON ; assembler accepts spaces & tabs in operand field
|
||
PRINT OFF ; do not send subsequent lines to the listing file
|
||
; don't print includes
|
||
|
||
PostNOP EQU 1 ;
|
||
|
||
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a' ; for VIA bit and -TestFor- definitions
|
||
INCLUDE 'Debug.a' ; for NAME macro
|
||
|
||
INCLUDE 'SCSI.a'
|
||
INCLUDE 'SCSIEqu53c96.a'
|
||
|
||
INCLUDE 'HALc96equ.a'
|
||
|
||
PRINT ON ; do send subsequent lines to the listing files
|
||
CASE OBJECT
|
||
|
||
IMPORT GetInitiatorID
|
||
IMPORT RecordEvent ; Recorder.a
|
||
IMPORT InitAMIC ; HALc96AMIC.a
|
||
IMPORT InitHW_GC ; HALc96GC.c
|
||
|
||
|
||
;==========================================================================
|
||
;
|
||
; Init53c9xHW
|
||
;
|
||
; C Calling convention:
|
||
; long Init53c9xHW(HBADesc_53c9x *hwDesc)
|
||
;
|
||
;——————————————————————————————————————————————————————————————————————————
|
||
|
||
Init53c9xHW PROC EXPORT
|
||
|
||
IMPORT AsmInit53c9xHW
|
||
|
||
move.l A5, -(sp) ; save
|
||
move.l 8(sp), A5 ; get pointer to hwDesc
|
||
bsr.w AsmInit53c9xHW
|
||
move.l (sp)+, A5
|
||
|
||
rts
|
||
|
||
NAME 'Init53c9xHW'
|
||
|
||
ENDP
|
||
|
||
;--------------------------------------------------------------------------
|
||
;
|
||
; AsmInit53c9xHW - reset and initialize the 53C96 SCSI controller
|
||
; This routine resets all functions in the chip and returns
|
||
; it to a disconnected state.
|
||
;
|
||
; INPUTS
|
||
; a3 -> pointer to SCSI port base address
|
||
; a2 -> pointer to SCSI DAFB register
|
||
; (NOTE - this routine assumes that we are in 32-bit mode!)
|
||
;
|
||
; OUTPUTS
|
||
; none
|
||
;
|
||
; trashes: none
|
||
|
||
AsmInit53c9xHW PROC EXPORT
|
||
|
||
IMPORT InitHW_SCSI96_BIOS, DoWeHaveFastSCSI
|
||
WITH HALc96GlobalRecord
|
||
|
||
@trashedRegs REG A0/A2-A3
|
||
|
||
movem.l @trashedRegs, -(sp)
|
||
|
||
DisableSCSIIRQ ; make sure we don't accidentally generate ints
|
||
|
||
move.l HALc96GlobalRecord.baseRegAddr(A5), a3 ; where the 53c96 is
|
||
|
||
move.l A3, -(sp)
|
||
bsr DoWeHaveFastSCSI ; see if we have a 53FC96
|
||
beq.s @f96
|
||
tst.b HALc96GlobalRecord.HBAisFast(A5) ; test the IsFast flag
|
||
bne.s @f96 ; if it's not set already,...
|
||
move.b #$40, HALc96GlobalRecord.HBAisFast(A5) ; ...set the IsFast flag
|
||
@f96
|
||
addq.l #4, sp
|
||
;
|
||
;………… Now we do our true reset to make sure everything's undone from that weird sequence above
|
||
;
|
||
move.b #cResetChip, rCMD(a3) ; send reset-scsi-chip cmd
|
||
nop
|
||
|
||
move.b #cNOP, rCMD(a3) ; NOP required after HW or SW reset
|
||
move.b #cFlushFIFO, rCMD(a3) ; Flush FIFO
|
||
|
||
nop
|
||
|
||
;
|
||
;………… Initialize c96 configuration registers
|
||
;
|
||
move.l A5, -(sp) ; HALg is only parameter to GetInitID
|
||
bsr GetInitiatorID ; returns InitID in D0 (like a C fn!)
|
||
addq.l #4, sp
|
||
|
||
or.b #mCF1_ResetIntrpDisable, D0 ; plus we still want reset ints disabled
|
||
move.b D0, rCF1(a3)
|
||
; 0 = slow cable mode disabled
|
||
; 1 = disable intrp to host on bus reset
|
||
; 0 = parity test mode disabled
|
||
; 0 = parity checking disable
|
||
; (ie. do not check parity on incoming data)
|
||
; 0 = chip mode test disabled
|
||
; 7 = use 7 as default myBusID
|
||
|
||
move.b #mCF2_SCSI2, rCF2(a3)
|
||
; 0 = do not reserve FIFO byte during sync xfer
|
||
; 0 = disable phase latch
|
||
; (Ie. status regr is a live state indicator of SCSI phase lines)
|
||
; for f96 part, this bit turns on 24bit xfer count as well
|
||
; 0 = ignore byte control inputs
|
||
; 0 = DACK* is enabled decr the xfer counter
|
||
; 1 = do use SCSI-2 features
|
||
; 0 = do not abort if parity error is detected (when target)
|
||
; 0 = do not carry parity from DMA bus (i.e. generate parity on xmit)
|
||
; 0 = do not flag outgoing parity errs (DMA-xfer)
|
||
|
||
move.b #mCF3_SaveResidual, rCF3(A3)
|
||
; 1 = do not assert DREQ on residual byte at end of xfer
|
||
; 0 = disable alternate DMA mode
|
||
; 0 = disable threshold 8 mode (we'll change it in Initc96Asm if need be)
|
||
|
||
nop
|
||
|
||
|
||
|
||
;………… Initialize the DAFB if we got one …………
|
||
;
|
||
tst.b HALc96GlobalRecord.needsDAFBinit(A5)
|
||
beq.s @setupC96 ; only Spike/Eclipse have a VIA2 and DAFB
|
||
|
||
move.l HALc96GlobalRecord.dafbAddr(A5), A2 ; get address of DAFB register
|
||
|
||
; Check whether we're 25 or 33MHz and set SCSI chip speed values appropriately
|
||
|
||
move.l VIA2, a0 ; get VIA2 so that we can check the speed bit
|
||
move.b vBufB(a0), d0 ; read PBx values for 25/33MHz checks
|
||
btst #v2Speed, d0 ; are we 25 MHz or 33 Mhz?
|
||
beq.s @25MHzDAFB ; if Speed == 33MHz THEN
|
||
@33MHzDAFB
|
||
move.l #tsc_cf_stg_33, (a2) ; setup DAFB SCSI config register.
|
||
bra.s @setupC96 ; ELSE // Speed == 25MHz
|
||
@25MHzDAFB
|
||
move.l #tsc_cf_stg_25, (a2) ; setup DAFB SCSI config register.
|
||
; ENDIF
|
||
|
||
|
||
;………… Set up Clock Conversion Factor and Select/Reselect Timeout registers …………
|
||
;
|
||
; CPU SCSI
|
||
; Quadra700 25 25
|
||
; Quadra900 25 15.6672
|
||
; Zydeco 33 24.28416 (boxFlag=Eclipse)
|
||
; Cyclone 33 25 or 24.576 (which?)
|
||
; PDM-Curio xx 20
|
||
; PDM-Fast xx 40
|
||
; TNT-Curio xx 20
|
||
; TNT-Fast xx 40
|
||
;
|
||
@setupC96
|
||
cmp.b #pdmaTypeBIOS,HALc96GlobalRecord.dmaType(A5) ; Is this a Wombat or Primus/Optimus?
|
||
bne.s @notBIOSbased
|
||
bsr.l InitHW_SCSI96_BIOS ; initialize BIOS stuff
|
||
bra.s @21to25MHz
|
||
@notBIOSbased
|
||
TestFor PSCExists ; Do we have a PSC? <SM7>
|
||
bne.s @21to25MHz ; Yes -> Cyclone
|
||
@notCyclone
|
||
|
||
TestFor HMCDecoder ; Do we have a HMC (e.g. PDM)? <SM7>
|
||
bnz.b @PDMorMacRISC
|
||
TestFor GrandCentralExists ; Do we have Grand Central (e.g. TNT)?
|
||
bz.b @PDMnorMacRISC
|
||
@PDMorMacRISC
|
||
tst.b HALc96GlobalRecord.HBAisFast(A5) ; are we talking to an CF96?
|
||
bne.s @40MHz ; fast -> 40MHz
|
||
bra.s @20MHz ; else (Curio) -> 20MHz
|
||
@PDMnorMacRISC
|
||
|
||
TestFor SCSI96_2Exists ; check for a Q700 versus Q9x0
|
||
beq.s @21to25MHz ; 1 bus? yes-> it's a 700 with 25 CPU/25 SCSI
|
||
|
||
; Either 900 or 950, Check for difference between 25 and 33MHz:
|
||
|
||
btst #v2Speed,d0 ; are we running at 25 or 33 MHZ?
|
||
bne.s @21to25MHz ; set -> 33MHz CPU = 25MHz SCSI clock
|
||
@16Mhz ; clr -> 25MHz CPU = 16MHz SCSI clock
|
||
move.b #ccf16to20MHz, rCKF(a3) ; load clock conversion factor (CCF) value
|
||
move.b #SelTO16Mhz, rSTO(a3) ; load select/reselect timeout value
|
||
bra.s @endClockSetup
|
||
|
||
@21to25MHz ;
|
||
move.b #ccf21to25MHz, rCKF(a3) ; load clock conversion factor (CCF) value
|
||
move.b #SelTO25Mhz, rSTO(a3) ;
|
||
bra.s @endClockSetup
|
||
|
||
@20MHz
|
||
move.b #ccf16to20MHz, rCKF(a3) ; Curio is running at 20MHz
|
||
move.b #SelTO20Mhz, rSTO(a3) ;
|
||
bra.s @endClockSetup
|
||
|
||
@40MHz
|
||
move.b #ccf36to40MHz, rCKF(a3) ; load clock conversion factor (CCF) value
|
||
move.b #SelTO40Mhz, rSTO(a3) ;
|
||
|
||
@endClockSetup
|
||
nop
|
||
|
||
move.b #initOp, rSyncOffset(a3) ; select sync or async operation; if sync then
|
||
; sync offset value must be nonzero
|
||
; Set synch xfer period and offset if using
|
||
; synch data xfer
|
||
nop
|
||
move.b rINT(a3), d0 ; read & clear rFOS, rSTA & rINT into throwaway
|
||
nop
|
||
move.b rINT(a3), d0 ; read again just in case there was a stacked int
|
||
|
||
cmp.b #LEVEL, intSensSCSI(A5) ; can’t really clear LEVEL-sensitive IRQ
|
||
beq.b @1
|
||
ClearSCSIIRQ
|
||
@1
|
||
|
||
;
|
||
;………… Initialize DMA Hardware (if it exists) …………
|
||
;
|
||
tst.b HBAhasDMA(A5) ; does HBA have real DMA?
|
||
beq.s @endDMAstuff ; ->
|
||
@hasDMA
|
||
cmp.b #dmaTypePSC, dmaType(A5) ; is it a PSC-type DMA?
|
||
beq.s @hasPSC ; -> yes
|
||
cmp.b #dmaTypeAMIC, dmaType(A5) ; is it an AMIC-type DMA?
|
||
beq.s @hasAMIC ; -> yes
|
||
cmp.b #dmaTypeGC, dmaType(A5) ; is it a Grand Central-type DMA?
|
||
beq.s @hasGC ; -> yes
|
||
|
||
DebugStr 'HWInit:Bad hwDesc - dmaType unknown'
|
||
|
||
@hasPSC bra.s @endDMAstuff ; no PSC init here
|
||
|
||
@hasAMIC bsr InitAMIC ; init the AMIC (turn off Run bit)
|
||
bra.s @endDMAstuff
|
||
|
||
@hasGC bsr InitHW_GC
|
||
|
||
@endDMAstuff
|
||
|
||
movem.l (sp)+, @trashedRegs
|
||
moveq.l #0, D0
|
||
rts
|
||
|
||
ENDWITH
|
||
|
||
NAME 'Init53x9xRegs'
|
||
|
||
ENDP
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————————————————
|
||
;
|
||
; InitHW_SCSI96_BIOS - reset and initialize the 53C96 SCSI controller once the gibbly loads.
|
||
; This routine resets all functions in the chip and returns
|
||
; it to a disconnected state.
|
||
;
|
||
; INPUTS
|
||
; a3 -> pointer to SCSI port base address
|
||
;
|
||
; trashes: d0, d1
|
||
|
||
InitHW_SCSI96_BIOS PROC EXPORT
|
||
|
||
WITH DecoderInfo, DecoderKinds, ProductInfo ;
|
||
|
||
|
||
; Check whether or not we're 25 or 33MHz and set SCSI bus speed values appropriately
|
||
; Get machine type + CPU speed information from VIA1
|
||
;
|
||
; 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 (0) or NOT! [Reserved] (1)
|
||
;
|
||
; Retrieve CPU Speed information from VIA1 Port A
|
||
|
||
@trashedRegs REG D0/D2/D3/A0/A2
|
||
|
||
movem.l @trashedRegs, -(sp) ; save stuff
|
||
|
||
movea.l UnivInfoPtr,a0 ; point to the DecoderInfo table
|
||
adda.l ProductInfo.DecoderInfoPtr(a0),a0
|
||
|
||
movea.l VIA1Addr(a0),a2 ; get VIA1 address to get machine/cpu_speed info
|
||
moveq #%00101000,d3 ; force VIA1 VDirA to have the correct directions
|
||
move.b d3,VDirA(a2) ; ... so we can read the CPU ID extension info
|
||
moveq #%00010100,d3 ; get VBufA, bits PA4, PA2 (dont need PA6, PA1)
|
||
and.b VBufA(a2),d3 ; get plastics_type/cpu_speed information
|
||
|
||
lea BIOSAddr,a2 ; get BIOS address for ConfigSonic_SCSI setup
|
||
move.b BIOS_SONIC_SCSI(a2),d2 ; save Sonic bit but trash
|
||
andi.b #BIOSSCSIFilter,d2 ; everything else
|
||
|
||
lsr.b #2,d3 ; shift PA4,PA2 down to bits 2-0
|
||
bne.s @25MHz ; 0=20MHz, otherwise check higher
|
||
@20MHz
|
||
ori.b #BIOScfg20MHz,d2 ; setup for and'ing the correct SCSI cfg bits
|
||
bra.s @contSetup
|
||
@25MHz
|
||
subq.b #4,d3 ; split the rest of the values
|
||
beq.s @33MHz
|
||
bgt.s @40MHz
|
||
|
||
ori.b #BIOScfg25MHz,d2 ; setup for and'ing the correct SCSI cfg bits
|
||
bra.s @contSetup
|
||
@33MHz
|
||
ori.b #BIOScfg33MHz,d2 ; setup for and'ing the correct SCSI cfg bits
|
||
bra.s @contSetup
|
||
|
||
@40MHz
|
||
ori.b #BIOScfg40MHz,d2 ; setup for and'ing the correct SCSI cfg bits
|
||
|
||
@contSetup
|
||
move.b d2,BIOS_SONIC_SCSI(a2) ;
|
||
|
||
movem.l (sp)+, @trashedRegs ; restore stuff
|
||
rts ;
|
||
|
||
NAME 'InitHW_SCSI96_BIOS'
|
||
|
||
ENDP
|
||
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————————————————
|
||
|
||
DoWeHaveFastSCSI PROC EXPORT
|
||
;
|
||
;………… First we reset the chip and see if we can get the Chip ID (from the F96) by doing
|
||
; the magic <Reset, NOP, FeaturesEnable, DMA+NOP, read ChipID> sequence
|
||
;
|
||
move.l A3, -(sp)
|
||
|
||
move.l 8(sp), A3 ; get hardware address
|
||
move.b #cResetChip, rCMD(a3) ; load reset-scsi-chip cmd, this cmd has
|
||
; the same effect as a hw reset
|
||
nop
|
||
move.b #cNOP, rCMD(a3) ; NOP required after HW or SW reset
|
||
|
||
move.b #mCF2_FeaturesEnable, rCF2(A3) ; turn on Features enable then,
|
||
move.b #$80+cNOP, rCMD(A3) ; send a DMA NOP command then,
|
||
nop
|
||
|
||
move.b rChipID(A3), D0 ; get the chip ID
|
||
cmp.b #$A2, D0 ; is it an FC96?
|
||
seq D0
|
||
|
||
move.l (sp)+, A3
|
||
tst D0
|
||
rts
|
||
|
||
NAME 'DoWeHaveFastSCSI'
|
||
|
||
ENDP
|
||
|
||
|
||
;—————————————————————————————
|
||
DoWeHaveAMIC3B PROC EXPORT
|
||
;
|
||
via2slotIER equ $50f26012
|
||
amic3Bflag EQU $60<<24 ; $6 in high nibble
|
||
move.w SR, -(sp)
|
||
or.w #$0700, SR ; block interrupts
|
||
|
||
move.l #amic3Bflag, D1
|
||
beq.s @ckSlotBit1
|
||
move.l D1, A0
|
||
add.w #$efe8, A0
|
||
move.l (A0), A0
|
||
move.l $f0(A0), D1
|
||
beq.s @ckSlotBit2
|
||
@ckSlotBit1
|
||
move.l D1, -(sp) ; save D1
|
||
move.b via2slotIER, D1
|
||
|
||
move.b #$82, via2slotIER
|
||
btst.b #1, via2slotIER
|
||
bne.s @notAMIC3
|
||
move.b #$02, via2slotIER
|
||
btst.b #1, via2slotIER
|
||
bra.s @exit
|
||
|
||
@ckSlotBit2
|
||
move.l D1, -(sp) ; save D1
|
||
move.b via2slotIER, D1 ; get current Interrupt Enable flags
|
||
|
||
move.b #$84, via2slotIER ; try to set new NuBus slot flag
|
||
btst.b #2, via2slotIER ; does it stick?
|
||
beq.s @notAMIC3 ; nope -> not AMIC3
|
||
move.b #$04, via2slotIER ; try to clear new NuBus slot flag
|
||
btst.b #2, via2slotIER ; does it stick?
|
||
beq.s @isAMIC3 ; yup -> is AMIC3
|
||
@notAMIC3
|
||
move.l (sp)+, D1
|
||
move.w (sp)+, SR ; reenable interrupts
|
||
cmp.b D0, D0 ; set Z
|
||
rts
|
||
|
||
@isAMIC3
|
||
lsl.b #7-2, D1 ; get the old value of bit 2 into bit 7 (set/clr bit)
|
||
or.b #4, D1 ; tell it which bit we want to set/clear
|
||
move.b D1, via2slotIER ; restore old value of bit
|
||
move.l (sp)+, D1
|
||
move.w (sp)+, SR ; reenable interrupts
|
||
@exit
|
||
cmp.w #0, A7 ; clear Z
|
||
rts
|
||
;
|
||
ENDP
|
||
|
||
END |