sys7.1-doc-wip/OS/SCSIMgr4pt3/HALc96HWInit.a
2019-07-27 22:37:48 +08:00

500 lines
17 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 Dont 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) ; cant 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