boot3/OS/SCSIMgr4pt3/HALc96HWInit.a

500 lines
16 KiB
Plaintext
Raw Normal View History

;
; File: HALc96HWInit.a
;
; Contains: 53c96 Hardware Initialization routines
;
; Written by: Paul Wolf
;
; Copyright: <09> 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<6F>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)
;
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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
;
;<3B><><EFBFBD><EFBFBD> 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
;
;<3B><><EFBFBD><EFBFBD> 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
;<3B><><EFBFBD><EFBFBD> Initialize the DAFB if we got one <20><><EFBFBD><EFBFBD>
;
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
;<3B><><EFBFBD><EFBFBD> Set up Clock Conversion Factor and Select/Reselect Timeout registers <20><><EFBFBD><EFBFBD>
;
; 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<61>t really clear LEVEL-sensitive IRQ
beq.b @1
ClearSCSIIRQ
@1
;
;<3B><><EFBFBD><EFBFBD> Initialize DMA Hardware (if it exists) <20><><EFBFBD><EFBFBD>
;
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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
;
; 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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DoWeHaveFastSCSI PROC EXPORT
;
;<3B><><EFBFBD><EFBFBD> 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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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