; ; 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): ; ; 2/1/94 chp Add logic to set the clock conversion factor and select/reselect ; timeout values for MacRISC-style CPUs. ; 11/22/93 pdw Rolling in from . ; 11/8/93 pdw Added support for new Cold Fusions with old parts! ; 11/19/93 chp DonΥt call ClearSCSIIRQ for level-sensitive HBAs. ; 9/29/93 chp Add a test and call to initialize Grand Central DMA hardware. ; 11/7/93 pdw Got rid of forPDMProto around DoWeHaveAMIC3B to help (but not ; solve) build Bob's build problems. ; 10/29/93 DCB roll-in. ; 10/28/93 pdw I don't remember. ; 10/14/93 pdw roll-in. ; 10/12/93 pdw Added support for Synchronous data transfers, rewrote State ; Machine, message handling etc. ; 10/6/93 pdw Fixed up the forPDMProto stuff. ; 10/4/93 RC Put forPDMProto around AMIC3/2 special code ; 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug ; stuff. ; 8/13/93 pdw Cleaned up "that shit above". ; 8/12/93 KW conditionalizing smurf branches ; 8/11/93 KW added some branches based on new smurf boxes ; 7/20/93 pdw Pulled out DoWeHaveFastSCSI functionality into an independent ; routine so that other routines can use it. ; 7/17/93 pdw Did I change something in here? ; 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. ; 5/25/93 DCB Changed some bsr.s to bsr.w to fix the build. ; 5/25/93 DCB Rollin from Ludwig (The item below) ; 5/21/93 PW Getting Mac's SCSI ID from PRAM instead of hard-coded. (This was ; a BUG!) ; 5/5/93 PW Converted names to meanies-friendly names. Updated with latest ; from Ludwig stuff. ; 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. ; 2/17/93 PW Removed some TERROR tags. ; 4/8/93 DCB Added Initialization code for Wombat class machines.. ; 3/29/93 PW Changed handling of CF3: if threshold-8, setting it up here ; without SaveResidual on, else setting only SaveResidual. ; 3/20/93 PW Unknown changes. ; 1/31/93 PW Update from the latest of Ludwig. Also changes required for PDM ; (will update Ludwig with these as needed myself). ; 1/27/93 PW Added nonSerializedIO checks and NOPs for PDM support. ; 12/5/92 PW EXPORTed Init53c9xRegs for fix to Reset interrupt bug in Curio. ; 12/3/92 fau Added boxRiscQuadra to the previous DAFBExists change. ; 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). ; 10/30/92 DCB Various Interrupt Handling improvements (using the new macros) ; 8/31/92 PW Changed register and command definitions to reflect changes to ; SCSIEqu53c96. ; 8/24/92 PN Take out CycloneboxEVT1 stuff ; 8/9/92 CCH Modified boxflag check for Quadras to include RISC Quadras. ; 7/28/92 PW Resolved differences in sources. ; 7/27/92 PW Got DMA working. ; 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? bne.s @21to25MHz ; Yes -> Cyclone @notCyclone TestFor HMCDecoder ; Do we have a HMC (e.g. PDM)? 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 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