; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > $.Source.PMF.osinit GBLL ErrorsInR0 ErrorsInR0 SETL Module ; if FALSE, use XOS_GenerateError for ; RAM version ; if TRUE, return error ptr in R0 GBLL ProtectStationID ; if TRUE, disallow OSBYTE &A2,0,n ProtectStationID SETL {TRUE}:LAND::LNOT:STB [ STB ; STB and NC machines probably want Num lock off. KBStat_Default * KBStat_NoShiftLock :OR: KBStat_NoNumLock | ; Desktop machines probably want Num lock on. KBStat_Default * KBStat_NoShiftLock ] ; ***************************************************************************** ExecuteInit ROUT Push R14 ; Point to OsbyteVars ; and initialise them BYTEWS WsPtr LDRB R1, LastBREAK ; 0 => soft, 1 => power-on, 2 => hard CMP R1, #1 ADRCC R2, SoftResetVars ADREQ R2, PowerOnResetVars ADRHI R2, HardResetVars LDRCCB R3, NoIgnore ; preserve NoIgnore over soft reset MOVCS R3, #0 ; if hard or power-on reset, zero it STRCS R3, TimerAlpha +0 ; and zero both copies of TIME STRCS R3, TimerAlpha +4 STRCS R3, TimerBeta +0 STRCS R3, TimerBeta +4 MOV R4, R1 ; preserve LastBREAK MOV R1, WsPtr ; start at the beginning ADR R11, ByteVarInitTable ByteVarInitLoop LDRB R0, [R11], #1 ; copy a byte from table STRB R0, [R1], #1 ; to vars TEQ R1, R2 ; at end ? BNE ByteVarInitLoop ; [no, then loop] STRB R3, NoIgnore ; put NoIgnore back STRB R4, LastBREAK ; put LastBREAK back ; Initialise buffer pointers MOV R0, #4*(NBuffers-1) ; index to pointer MOV R1, #0 ; value to store BuffPtrInitLoop STR R1, [R0, #BuffInPtrs] STR R1, [R0, #BuffOutPtrs] SUBS R0, R0, #4 BPL BuffPtrInitLoop ; mark printer as dormant STR R1, PrinterActive ; (R1=0) ; Initialise event semaphores ADR R0, EventSemaphores ADD R2, R0, #32 10 STR R1, [R0], #4 ; clear all 32 event semaphores TEQ R0, R2 BNE %BT10 STRB R1, FlashState STRB R1, SerialInHandle ; zero serial handles STRB R1, SerialOutHandle ; Initialise LatchB and soft copy ; MOV R1, #0 ; AND with 0 (was omitted on earlier MOS) ; R1 already zero MOV R0, #0 ; EOR with 0 BL UpdateLatchB [ DriversInKernel MOV R1, #DIVRESET6850 ; reset 6551 MOV R2, #0 BL ModifyControl6850 ] ; set up IOC timer 0 before we read from CMOS (cos it uses timer for delays) MOV R1, #IOC LDR R0, =20000-1 ; R0 = Timer delay (units of 0.5 microsecond) ; 20000*0.5E-6 = 0.01 Seconds 100Hz ; TMD 21-May-93: "-1" correction applied STRB R0, [R1, #Timer0LL] ; Set up the delay MOV R0, R0, LSR #8 STRB R0, [R1, #Timer0LH] STRB R0, [R1, #Timer0GO] ; and start the ticks LDRB R0, LastBREAK TEQ R0, #0 BEQ %FT20 BL ReadMachineType BL ReadUniqueID BL ReadHardCMOSDefaults 20 BL ReadCMOSDefaults [ StorkPowerSave BL PowerHardware ;On Stork, ensure Combo chip, Winnie, Floppy etc are powered ] [ STB BL ConfigureCombo | [ IO_Type = "IOMD" BL Configure37C665 ;RiscPC, Kryten and Stork use only SMC 37C665 | BL Configure82C710 ;Earlier code copes with 82C710,82C711 and 37C665 ] ] [ DriversInKernel ; reset ACIA LDR R11, =ACIA LDRB R0, ACIAStatus ; set up DCD, DSR bits in SerialFlags AND R0, R0, #(ACIADSR :OR: ACIADCD) MOV R0, R0, LSL #DCDDSRShift STR R0, SerialFlags ; other bits are zero LDRB R0, ACIACommand ORR R0, R0, #ACIADTR ; enable transmit and receive STRB R0, ACIACommand ] MOV R1, #IOC [ :LNOT: NewClockChip MOV R0, #0 STRB R0, SecondsTime ; zero seconds and centiseconds STRB R0, CentiTime LDRB R0, [R1, #IOCControl] ; load IOC control register AND R0, R0, #rtc_minutes_bit STRB R0, MinTick ; Initialise the minute odd/even flag MOV R0, #1 STRB R0, SecondsDirty ; mark the seconds as dirty (non-zero) ] [ DriversInKernel MOV R0, #timer0_bit :OR: pack_bit :OR: vsync_bit | MOV r0, #timer0_bit :OR: vsync_bit ] STRB R0, [R1, #IOCIRQCLRA] ; clear pending tim0, vsync irqs (+ pack irq if appropriate) LDRB R0, [R1, #IOCIRQMSKA] ORR R0, R0, #timer0_bit :OR: vsync_bit STRB R0, [R1, #IOCIRQMSKA] ; Enable timer 0 + vsync irqs [ DriversInKernel LDRB R0, [R1, #IOCIRQMSKB] ; enable 6551 interrupt ORR R0, R0, #serial_bit STRB R0, [R1, #IOCIRQMSKB] ] [ E2ROMSupport :LAND: STB ; Don't set time to value held in RTC if the RTC chip is not fitted ; system time will default to epoch: Midnight 1st Jan 1900 MOV R1, #0 LDRB R0, [r1, #RTCFitted] TEQ R0, #1 BEQ %FT28 ; Set default time to UNIX epoch (1970) +1day not RISCOS epoch (1900) so time() doesn't return -1 secs0070 * (86400*(365*70+18)) ; from time() in risc_oslib.c.armsys LDR R7, =(secs0070 * 100) ; centiseconds LSW MOV R8, #&33 ; centiseconds MSW BL Store5ByteInRealTime B %FT30 28 ] BL CheckYear ; check for year wrap scenario BL RTCToRealTime ; insert soft key 10 30 MOV R2, #&CA BL RDCHS Pull PC LTORG ; ***************************************************************************** ; ; ReadHardCMOSDefaults - Read CMOS values for a hard/power-on reset ; NB must be called in supervisor mode ReadHardCMOSDefaults Push R14 MOV R0, #PigCMOS BL Read STRB R0, PrinterIgnore MOV R0, #PSITCMOS BL Read TST R0, #2 ; NoIgnore bit MOVEQ R1, #0 MOVNE R1, #&80 STRB R1, NoIgnore MOV R1, R0, LSR #5 ; printer type now in bits 0..2 STRB R1, PrinterDrivType MOV R0, #MODETVCMOS BL Read MOV R2, R0, LSR #4 ; bit0:=interlace, bits 1-3 := vertical AND R1, R2, #1 STRB R1, TVInterlace MOV R2, R2, LSL #31-3 ; bits 29-31 := vertical MOV R2, R2, ASR #29 ; sign extend STRB R2, TVVertical MOV R0, #DBTBCMOS BL Read LDRB R1, StartOptions TST R0, #&10 ; bit 4 = boot bit ORREQ R1, R1, #8 ; noboot => set bit 3 BICNE R1, R1, #8 ; boot => clear bit 3 STRB R1, StartOptions LDR R2, =VduDriverWorkSpace+CursorFlags ANDS R1, R0, #8 ; noscroll bit - put 0 or 1 MOVNE R1, #1 ; in bottom byte of CursorFlags STRB R1, [R2] ; leave other bytes alone MOV R0, #CountryCMOS ; read country CMOS and store in var BL Read ; but don't bind 'Default' to a fixed STRB R0, Country ; country at this stage [ :LNOT: DriversInKernel BL SetUpPrinterBuffer ] Pull PC ; ***************************************************************************** ; ; ReadCMOSDefaults - Read CMOS values for any reset ; NB must be called in supervisor mode ReadCMOSDefaults Push R14 [ DriversInKernel MOV R0, #PSITCMOS BL Read MOV R1, R0, LSR #2 ; baud bits now in bits 0..2 AND R1, R1, #7 ; 0 => 75, ... ,7 => 19200 ADD R1, R1, #1 ; 1 => 75, ... ,8 => 19200 Push R1 BL DoOsbyte07 Pull R1 BL DoOsbyte08 ] MOV R0, #DBTBCMOS BL Read TST R0, #2 ; NZ => loud MOVEQ R1, #&D0 ; (quiet) MOVNE R1, #&90 ; (LOUD) STRB R1, BELLinfo [ DriversInKernel MOV R1, R0, LSR #5 ; bits 5..7 -> bits 0..2 MOV R1, R1, LSL #2 ; put in bits 2..4 ORR R1, R1, #&42 ; or in default 6850 bits MOV R2, #0 ; replace old value BL ModifyControl6850 ] MOV R0, #StartCMOS BL Read MOVS R0, R0, LSL #(32-5) ; bit 5 -> carry, bit 4 -> N bit MOVPL R0, #KBStat_Default + KBStat_ShiftEnable ; SHCAPS MOVMI R0, #KBStat_Default + KBStat_NoCapsLock ; NOCAPS MOVCS R0, #KBStat_Default ; CAPS STRB R0, KeyBdStatus [ ModeSelectors BL Read_Configd_MonitorType LDR r1, =VduDriverWorkSpace+CurrentMonitorType ; set current to default STR r0, [r1] ] Pull R14 ; and drop thru to ... ReadKeyDefaults Push R14 MOV R0, #KeyDelCMOS ; Read the default out of CMOS RAM BL Read ; comes back in R0 STRB R0, KeyRepDelay MOV R0, #KeyRepCMOS ; Read the default out of CMOS RAM BL Read ; comes back in R0 STRB R0, KeyRepRate Pull PC ; ***************************************************************************** ; ; PostInit - Called by Sam after modules have been initialised ; PostInit ROUT Push R14 BYTEWS WsPtr LDRB R0, LastBREAK ; get reset type TEQ R0, #0 BEQ %FT10 ; [soft reset, skip] [ StorkPowerSave SWI XPortable_ReadFeatures BVC %FT01 ; MOV R0, #0 MOV R1, #0 SWI XPortable_Speed ; attempt to make the portable go fast! MOVVC R1, #PortableFeature_Speed MOVVS R1, #0 01 AND R0, R1, #(PortableFeature_Speed :OR: PortableFeature_Idle :OR: PortableFeature_Stop) STRB r0, [r0, #PortableFlags] | MOV r0, #0 ; allow SWI Portable_Speed to be issued STRB r0, [r0, #PortableFlag] ] [ BleedinDaveBell MOV R0, #1 ; indicate keyboard UK MOV R1, #101 ; indicate alphabet Latin1 | MOV R0, #2 ; indicate keyboard Master MOV R1, #100 ; indicate alphabet Bfont ] STRB R0, Keyboard STRB R1, Alphabet STRB R1, KeyAlphabet ; alphabet corresponding to keyboard 10 Pull R14 B KeyPostInit [ :LNOT: STB ; ***************************************************************************** ; ; SWI OS_ResyncTime ; ; in: r0 = 0 - Real time clock soft copy only ; r0 <> 0 reserved for future expansion ; ; out: r0 preserved ; ResyncTimeSWI Push "LR" BL CheckYear ;may have been frozen over new year! BL RTCToRealTime Pull "LR" ExitSWIHandler ] ; ***************************************************************************** ; ; UpdateLatchB - update latch B and soft copy ; ; LATCHB := (LATCHB AND R1) EOR R0 ; UpdateLatchB Push "R2, R3, R14" MOV R14, PC ORR R2, R14, #I_bit TEQP R2, #0 ; disable IRQ MOV R2, #0 LDRB R3, [R2, #LatchBSoftCopy] AND R3, R3, R1 EOR R3, R3, R0 STRB R3, [R2, #LatchBSoftCopy] [ IO_Type <> "IOMD" ; there ain't no Latch B on IOMD! LDR R2, =LatchB STRB R3, [R2] ] TEQP R14, #0 Pull "R2, R3, PC" [ STB ; ***************************************************************************** ; ; UpdateCLines - update IOMD_CLINES 8bit IO port ; In: ; r3: new value ; r4: mask of bits to set ; ; Out: ; All regs preserved UpdateCLines ENTRY "r0, r1" LDR r0, =(IOMD_Base + IOMD_CLINES) LDRB r1, [r0] ORR r1, r1, #IOMD_C_ReadMask ; Set readable bits BIC r1, r1, r4 ; Clear bits to write ORR r1, r1, r3 ; Set bits to write STRB r1, [r0] EXIT ; ***************************************************************************** | ; ***************************************************************************** ; ; UpdateMonitorTypeLatch - update monitor type latch and soft copy ; ; Returns the result in R4 UpdateMonitorTypeLatch Push "R2, R3, R14" MOV R14, PC ORR R2, R14, #I_bit TEQP R2, #0 ; disable IRQ MOV R2, #0 LDRB R3, [R2, #CLine_Softcopy] MOV R3, #1 ;Set our bit only STRB R3, [R2, #CLine_Softcopy] MOV R2, #IOMD_Base STRB R3, [R2, #IOMD_CLINES] ;Write the new reg out LDRB R3, [R2, #IOMD_CLINES] ;Read it back AND R4, R3, #1 ;Clear all but our bit into R4 TEQP R14, #0 ;Re-enable IRQ Pull "R2, R3, PC" ; ***************************************************************************** ] ; The initial values for all of the osbyte variables ; as decreed by arthur. ByteVarInitTable ; The main osbyte variables, accessed ; via calls &A6 to &FF DCW OsbyteVars-&A6 ; VarStart # 2 ; &A6,&A7 = 0,0 ; ROMPtr # 2 ; &A8,&A9 = 0,0 ; ROMInfo # 2 ; &AA,&AB = 0,0 ; KBTran # 2 ; &AC,&AD = 0,0 ; VDUvars # 2 ; &AE,&AF ; = 0 ; CFStime # 1 ; &B0 = 0 ; InputStream # 1 ; &B1 = &FF ; KeyBdSema # 1 ; &B2 ; = &00 ; ROMPollSema # 1 ; &B3 = &80 ; OSHWM # 1 ; &B4 (hi-byte of &8000) ; = 1 ; RS423mode # 1 ; &B5 = 0 ; NoIgnore # 1 ; &B6 = &00 ; CFSRFS # 1 ; &B7 = &00,&00 ; VULAcopy # 2 ; &B8,&B9 ; = &00 ; ROMatBRK # 1 ; &BA = &FF ; BASICROM # 1 ; &BB ; = &04 ; ADCchanel # 1 ; &BC = &04 ; ADCmaxchn # 1 ; &BD = &00 ; ADCconv # 1 ; &BE ; = &FF ; RS432use # 1 ; &BF = &42 ; RS432conflag # 1 ; &C0 ; = 0 ;&19 ; FlashCount # 1 ; &C1 /* changed to fx 9 0 by RCM 31/10/91 */ = &19 ; SpacPeriod # 1 ; &C2 = 0 ;&19 ; MarkPeriod # 1 ; &C3 /* changed to fx 9 0 by RCM 31/10/91 */ ; = &32 ; KeyRepDelay # 1 ; &C4 = &08 ; KeyRepRate # 1 ; &C5 ; = &00 ; ExecFileH # 1 ; &C6 = &00 ; SpoolFileH # 1 ; &C7 ; = &00 ; ESCBREAK # 1 ; &C8 (200) ; = &00 ; KeyBdDisable # 1 ; &C9 = KBStat_Default ; KeyBdStatus # 1 ; &CA ; = &11 ; RS423HandShake # 1 ; &CB = &00 ; RS423InputSupr # 1 ; &CC = &00 ; RS423CFSFlag # 1 ; &CD ; = &00 ; EconetOScall # 1 ; &CE = &00 ; EconetOSrdch # 1 ; &CF = &00 ; EconetOSwrch # 1 ; &D0 ; = &00 ; SpeechSupr # 1 ; &D1 = &00 ; SoundSupr # 1 ; &D2 ; = &01 ; BELLchannel # 1 ; &D3 = &90 ; BELLinfo # 1 ; &D4 = &64 ; BELLfreq # 1 ; &D5 = &06 ; BELLdur # 1 ; &D6 ; = &81 ; StartMessSupr # 1 ; &D7 ; = &00 ; SoftKeyLen # 1 ; &D8 ; = &00 ; PageModeLineCount # 1 ; &D9 ; = &00 ; VDUqueueItems # 1 ; &DA ; = &09 ; TABch # 1 ; &DB = &1B ; ESCch # 1 ; &DC ; = &01,&D0,&E0,&F0 ; IPbufferCh # 4 ; &DD,&DE,&DF,&E0 = &01,&80,&90,&00 ; RedKeyCh # 4 ; &E1,&E2,&E3,&E4 ; = &00 ; ESCaction # 1 ; &E5 = &00 ; ESCeffect # 1 ; &E6 ; = &00 ; u6522IRQ # 1 ; &E7 = &00 ; s6850IRQ # 1 ; &E8 = &00 ; s6522IRQ # 1 ; &E9 ; = &00 ; TubeFlag # 1 ; &EA ; = &00 ; SpeechFlag # 1 ; &EB ; = &00 ; WrchDest # 1 ; &EC = &00 ; CurEdit # 1 ; &ED ; = &30 ; KeyBase ; &EE = &01 ; Shadow ; &EF = &00 ; Country ; &F0 ; = &00 ; UserFlag # 1 ; &F1 ; = &64 ; SerULAreg # 1 ; &F2 ; = &05 ; TimerState # 1 ; &F3 ; = &FF ; SoftKeyConsist # 1 ; &F4 ; = &01 ; PrinterDrivType # 1 ; &F5 = &0A ; PrinterIgnore # 1 ; &F6 ; = &01,&00,&00 ; BREAKvector # 3 ; &F7,&F8,&F9 ; = &00 ; DRIVER ; &FA = &00 ; DISPLAY ; &FB ; = &FF ; LangROM # 1 ; &FC ; = &01 ; LastBREAK # 1 ; &FD ; = &0F ; KeyOpt # 1 ; &FE ; = &08 ; StartOptions # 1 ; &FF ; ; ByteVarInitTableEnd ByteVarInitTableSize * ByteVarInitTableEnd - ByteVarInitTable ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LTORG oldirqowner & IRQ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; ReadMachineType - Determine machine type and store it in IOSystemType ; ReadMachineType ENTRY "r0-r12" [ IO_Type = "IOMD" [ MorrisSupport MOV r12, #IOMD_Base [ {TRUE} ; ARM7500FE support LDRB r0, [r12, #IOMD_ID0] LDRB r11, [r12, #IOMD_ID1] ORR r0, r0, r11, LSL #8 LDR r11, =IOMD_Original TEQ r0, r11 MOVEQ r11, #0 ; assume Medusa MOVNE r11, #IOST_7500 ; else assume Morris TEQ r11, #IOST_7500 ; and set EQ if Morris to do conditional stuff below | LDRB r0, [r12, #IOMD_ID0] CMP r0, #&E7 LDRB r0, [r12, #IOMD_ID1] CMPEQ r0, #&5B MOVEQ r11, #IOST_7500 ;EQ, Morris MOVNE r11, #0 ;NE, assume Medusa ] ; ; On Kryten, Morris pin Event2 is tied low so bit Nevent2 is a ONE ; On Stork, Morris pin Event2 is tied high so bit Nevent2 is a ZERO ; On STB/NCD, Morris pin Event2 is tied high so bit Nevent2 is a ZERO, but we don't have a LCD ; controller or battery manager so we'll not set IOST_BATMAN ; LDREQB r0, [r12, #IOMD_IRQSTD] ;EQ, Morris [ BatManSupport TSTEQ r0, #IOMD_Nevent2_bit ORREQ r11, r11, #IOST_BATMAN ;EQ, Stork ie Morris & BATMAN ] ORR r0, r11, #IOST_IOEB ; pretend we've got IOEB ; ; r11 holds 0 for IOMD (Risc PC) ; or IOST_7500 for Morris (Kryten, Falcon, Omega) ; or IOST_7500 + IOST_BATMAN for Morris (Stork) | MOV r0, #IOST_IOEB ; pretend we've got IOEB ] | TEQP pc, #SVC_mode + I_bit + F_bit ; disable IRQs and FIQs MOVNV r0, r0 LDR r1, =IOEB_ASICPresent MOV r0, #&FA STRB r0, [r1] LDRB r0, [r1] TEQP pc, #SVC_mode + I_bit AND r0, r0, #&0F TEQ r0, #5 ; must read 5 is ASIC present MOVNE r0, #0 ; no IOEB, LC or 82C710 BNE %FT10 ; there is an IOEB ASIC present, so it's safe to test for LC ASIC LDR r1, =LC_ASICPresent LDRB r0, [r1] AND r0, r0, #&0E ; bits 3210 should be 010x TEQ r0, #&04 MOVNE r0, #IOST_IOEB ; IOEB but no LC MOVEQ r0, #IOST_IOEB :OR: IOST_LC ; IOEB and LC 10 ] MOV r1, #0 ; normal Hsync and address pointer STRB r0, [r1, #IOSystemType] ; now read monitor lead type. TEQ r0, #0 ; no IOEB MOVEQ r2, #&FF ; then return all ones for monitor lead type BEQ %FT90 [ MPEGPoduleNTSCNotPALMask <> 0 ! 1, "Sorry, I don't do MPEGPoduleNTSCNotPALMask any more" ] [ STB LDR r0, =VIDC ; on VIDC20 we invert HSYNC by writing to External Register [ MorrisSupport ; On Morris, monitor auto-detect has been moved to IOMD_CLINES [ IOMD_C_MonitorType <> 0 ASSERT (IOMD_C_MonitorType = (1<<0)) ; this code only understands auto-detect in bit 0 ] TST R11, #IOST_7500 LDREQ r3, =IOMD_MonitorType ; Not Morris, address is in old place LDRNE r3, =(IOMD_Base + IOMD_CLINES) | LDR r3, =IOMD_MonitorType ] ; MorrisSupport LDR r1, =VIDCExternal+Ext_InvertCompVSYNC+Ext_DACsOn+Ext_ERegExt ; normal HSYNC value STR r1, [r0] ORR r2, r1, #Ext_InvertHSYNC ; value for inverted HSYNC LDRB r4, [r3] ; base value [ MorrisSupport [ IOMD_C_PALNTSCType <> 0 ASSERT (IOMD_C_PALNTSCType = (1<<4)) ; this code only understands PAL/NTSC auto-detect in bit 4 AND r4, r4, #(IOMD_C_MonitorType :OR: IOMD_C_PALNTSCType) ORR r4, r4, r4, LSR #1 ; Shift PAL/NTSC bit into bit 3 AND r4, r4, #&0F ; only use bits 0..3 | AND r4, r4, #IOMD_C_MonitorType ; only one bit ] | AND r4, r4, #&0F ; only use bits 0..3 ] MOV r5, #0 ; bits 0..3 = bits which have ever changed ; bits 4..7 = bits whose deinverted value was high last time ; bits 8..11 = bits whose deinverted value just went high-low ; bits 12..15 = bits whose deinverted value just went high-low-low ; bits 16..19 = bits which could be hsync ; ie after every high-low there was low-low (after deinversion) ; bits 20..23 = bits which are definitely random MOV r10, #&0F ; used inside CheckBits MOV r12, #256 ; number of iterations 20 STR r2, [r0] LDRB r6, [r3] ; read value with inverted sync STR r1, [r0] LDRB r7, [r3] ; read value with normal sync [ MorrisSupport [ IOMD_C_PALNTSCType <> 0 AND r6, r6, #(IOMD_C_MonitorType :OR: IOMD_C_PALNTSCType) ORR r6, r6, r6, LSR #1 ; Shift PAL/NTSC bit into bit 3 AND r6, r6, #&0F ; only use bits 0..3 AND r7, r7, #(IOMD_C_MonitorType :OR: IOMD_C_PALNTSCType) ORR r7, r7, r7, LSR #1 ; Shift PAL/NTSC bit into bit 3 AND r7, r7, #&0F ; only use bits 0..3 | AND r6, r6, #IOMD_C_MonitorType ; only one bit AND r7, r7, #IOMD_C_MonitorType ] | AND r6, r6, #&0F ; only use bits 0..3 AND r7, r7, #&0F ] EOR r8, r6, r4 ; bits which have changed from steady value to inverted one ORR r5, r5, r8 ; OR into mask of bits which have ever changed EOR r8, r7, r4 ; bits which have changed from steady value to normal one ORR r5, r5, r8 ; OR into mask of bits which have ever changed EOR r6, r6, #&0F ; deinvert inverted value BL CheckBits ; call check routine with first value MOV r6, r7 BL CheckBits ; call check routine with second value SUBS r12, r12, #1 BNE %BT20 | ; STB [ VIDC_Type = "VIDC20" LDR r0, =VIDC ; on VIDC20 we invert HSYNC by writing to External Register | LDR r0, =VIDCClockSelect ; on VIDC1 we write to latch instead ] [ IO_Type = "IOMD" LDR r3, =IOMD_MonitorType | LDR r3, =IOEB_MonitorType ] [ VIDC_Type = "VIDC20" LDR r1, =VIDCExternal+Ext_InvertCompVSYNC+Ext_DACsOn+Ext_ERegExt ; normal HSYNC value STR r1, [r0] ORR r2, r1, #Ext_InvertHSYNC ; value for inverted HSYNC | STRB r1, [r0] ; set up normal Hsync MOV r2, #4 ; inverted Hsync ] [ MorrisSupport TST R11, #IOST_7500 BLNE UpdateMonitorTypeLatch ;Result back in R4 LDREQB r4, [r3] | LDRB r4, [r3] ; base value ] AND r4, r4, #&0F ; only use bits 0..3 MOV r5, #0 ; bits 0..3 = bits which have ever changed ; bits 4..7 = bits whose deinverted value was high last time ; bits 8..11 = bits whose deinverted value just went high-low ; bits 12..15 = bits whose deinverted value just went high-low-low ; bits 16..19 = bits which could be hsync ; ie after every high-low there was low-low (after deinversion) ; bits 20..23 = bits which are definitely random MOV r10, #&0F ; used inside CheckBits MOV r12, #256 ; number of iterations 20 [ VIDC_Type = "VIDC20" STR r2, [r0] | STRB r2, [r0] ] [ MorrisSupport TST R11, #IOST_7500 BLNE UpdateMonitorTypeLatch ;Result back in R4 MOVNE r6, r4 LDREQB r6, [r3] | LDRB r6, [r3] ; read value with inverted sync ] [ VIDC_Type = "VIDC20" STR r1, [r0] | STRB r1, [r0] ] [ MorrisSupport TST R11, #IOST_7500 BLNE UpdateMonitorTypeLatch ;Result back in R4 MOVNE r7,r4 LDREQB r7,[r3] | LDRB r7, [r3] ; read value with normal sync ] AND r6, r6, #&0F AND r7, r7, #&0F EOR r8, r6, r4 ; bits which have changed from steady value to inverted one ORR r5, r5, r8 ; OR into mask of bits which have ever changed EOR r8, r7, r4 ; bits which have changed from steady value to normal one ORR r5, r5, r8 ; OR into mask of bits which have ever changed EOR r6, r6, #&0F ; deinvert inverted value BL CheckBits ; call check routine with first value MOV r6, r7 BL CheckBits ; call check routine with second value SUBS r12, r12, #1 BNE %BT20 ] ; STB ; now process result LDR r1, =VIDCExternal+Ext_InvertCompVSYNC+Ext_InvertCompHSYNC+Ext_DACsOn+Ext_ERegExt ; put back default value STR r1, [r0] BIC r4, r4, r5 ; don't put port value in for bits that have changed BIC r5, r5, r5, LSR #16 ; make bits 0..3 of r5 indicate random bits ANDS r2, r4, #1 ; for each bit pair 00 => low, 01 => high, 10 => Hsync, 11 => random TST r5, #1 :SHL: 16 MOVNE r2, #2 :SHL: 0 TST r5, #1 MOVNE r2, #3 :SHL: 0 TST r4, #2 ORRNE r2, r2, #1 :SHL: 2 TST r5, #2 :SHL: 16 ORRNE r2, r2, #2 :SHL: 2 TST r5, #2 ORRNE r2, r2, #3 :SHL: 2 TST r4, #4 ORRNE r2, r2, #1 :SHL: 4 TST r5, #4 :SHL: 16 ORRNE r2, r2, #2 :SHL: 4 TST r5, #4 ORRNE r2, r2, #3 :SHL: 4 TST r4, #8 ORRNE r2, r2, #1 :SHL: 6 TST r5, #8 :SHL: 16 ORRNE r2, r2, #2 :SHL: 6 TST r5, #8 ORRNE r2, r2, #3 :SHL: 6 [ IO_Type = "IOMD" :LAND: {FALSE} ASSERT IOMD_MonitorIDMask = 1 AND r2, r2, #3 ; only bit 0 of ID valid on IOMD-based systems ] [ STB :LAND: IOMD_C_TVMode <> 0 ; set the TVMode to 0 (VGA) if id bits1,0 != 01 (TV) AND r3, r2, #2_11 ; bits we're interested in CMP r3, #2_01 ; TV? BEQ %FT90 ; yes MOV r3, #0 MOV r4, #IOMD_C_TVMode BL UpdateCLines ] 90 MOV r1, #0 STRB r2, [r1, #MonitorLeadType] EXIT CheckBits ROUT AND r8, r10, r5, LSR #12 ; bits that were H-L-L BIC r8, r8, r6 ; bits that are H-L-L-L ORR r5, r5, r8, LSL #16 ; OR into bits that could be hsync ORR r8, r5, r5, LSR #4 AND r8, r6, r8, LSR #8 ; bits that just went H-L-H or H-L-L-H AND r8, r8, r5, LSR #16 ; bits that just went H-L-H or H-L-L-H and could have been hsync ORR r5, r5, r8, LSL #20 ; they're definitely random now BIC r5, r5, r8, LSL #16 ; and they're definitely not hsync now AND r8, r5, #&FF :SHL: 4 ; get H bits, and H-L bits BIC r8, r8, r6, LSL #4 ; knock out bits that were H and are now H BIC r8, r8, r6, LSL #8 ; knock out bits that were H-L and are now H BIC r5, r5, #&FF :SHL: 8 ; knock out all H-L and H-L-L bits ORR r5, r5, r8, LSL #4 ; put in new H-L and H-L-L bits BIC r5, r5, #&F :SHL: 4 ; knock out old H bits ORR r5, r5, r6, LSL #4 ; put in new H bits BIC r5, r5, r5, LSR #20 ; knock out H bits if we know it's random MOV pc, lr ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; TranslateMonitorLeadType - Determine monitor type and default mode + sync from monitor lead type ; ; in: Monitor lead type in variable MonitorLeadType (surprisingly!) ; ; out: r3 = default mode to use ; r4 = default monitortype to use ; r5 = default sync to use ; TranslateMonitorLeadType ENTRY "r0-r2" MOV r1, #Service_MonitorLeadTranslation LDRB r2, [r1, #MonitorLeadType-Service_MonitorLeadTranslation] SWI XOS_ServiceCall TEQ r1, #0 ; if service claimed, then exit with these numbers EXIT EQ ADR r0, MonitorLeadList 10 LDR r14, [r0], #4 EOR r1, r2, r14, LSR #24 ; differences EOR r14, r14, #&FF000000 ; make don't cares into zero TST r14, #&C0000000 BICEQ r1, r1, #&C0 ; knock out difference pairs if don't care TST r14, #&30000000 BICEQ r1, r1, #&30 TST r14, #&0C000000 BICEQ r1, r1, #&0C TST r14, #&03000000 BICEQ r1, r1, #&03 TEQ r1, #0 ; if still have differences, then loop BNE %BT10 MOV r0, #&FF AND r3, r0, r14 ; mode in bits 0..7 AND r4, r0, r14, LSR #8 ; monitortype in bits 8..15 AND r5, r0, r14, LSR #16 ; sync in bits 16..23 EXIT MACRO MonitorLeadItem $lead, $mode, $monitortype, $sync ASSERT $lead < 256 ASSERT $mode < 256 ASSERT $monitortype < 256 ASSERT $sync < 256 DCD (($lead):SHL:24):OR:(($sync):SHL:16):OR:(($monitortype):SHL:8):OR:($mode) MEND [ IO_Type = "IOMD" MonitorLeadList [ STB [ IOMD_C_MonitorType = 0 ; no auto-detect bit [ IOMD_C_PALNTSCType = 0 ; no PAL/NTSC bits: MonitorLeadItem 4_3333, 12, 0, 1 ; PAL TV assumed | ; IOMD_C_PALNTSCType = 0 MonitorLeadItem 4_0333, 12, 0, 1 ; PAL TV MonitorLeadItem 4_1333, 46, 8, 1 ; NTSC TV ] ; IOMD_C_PALNTSCType = 0 | [ :LNOT: ChrontelSupport [ IOMD_C_PALNTSCType = 0 ; no PAL/NTSC bits: MonitorLeadItem 4_3331, 12, 0, 1 ; PAL TV assumed | ; IOMD_C_PALNTSCType = 0 ; wealth of bits: MonitorLeadItem 4_0331, 12, 0, 1 ; PAL TV MonitorLeadItem 4_1331, 46, 8, 1 ; NTSC TV ] ; IOMD_C_PALNTSCType = 0 ] ; :LNOT: ChrontelSupport ] ; IOMD_C_MonitorType = 0 MonitorLeadItem 4_3333, 28, 3, 0 ; VGA-capable monitors 256 colours | ; STB MonitorLeadItem 4_3330, 27, 3, 0 ; VGA-capable monitors MonitorLeadItem 4_3333, 12, 0, 1 ; Others - assume TV standard ]; STB | ;IO_Type = "IOMD" MonitorLead_MonoVGA * 4_3101 MonitorLead_ColourVGA * 4_3110 MonitorLead_ColourSVGA * 4_3010 ; should be type 4, but for the LiteOn we bodge it to 1 MonitorLead_Multisync * 4_3211 MonitorLead_TV * 4_3112 MonitorLead_NoConnect * 4_3111 MonitorLead_Undefined * 4_3333 MonitorLeadList MonitorLeadItem MonitorLead_Multisync, 27, 1, 1 MonitorLeadItem MonitorLead_MonoVGA, 27, 3, 0 MonitorLeadItem MonitorLead_ColourVGA, 27, 3, 0 MonitorLeadItem MonitorLead_ColourSVGA, 27, 1, 0 ; bodge for LiteOn (should be 27, 4, 0) MonitorLeadItem MonitorLead_Undefined, 12, 0, 1 ; used for all other combinations ] [ StorkPowerSave ; ; List of latch addresses and initial values. ; PowerTab DCD HWLatchPA, InitLatchPA DCD HWLatchPB, InitLatchPB DCD HWLatchMC, InitLatchMC DCD HWLatchMA, InitLatchMA DCD 0 PowerHardware ;On Stork, ensure Combo chip, Winnie, Floppy etc are powered ENTRY "r0,r1" MOV r0, #0 LDRB lr, [r0, #IOSystemType] TST lr, #IOST_BATMAN EXIT EQ ;EQ, not Stork, so hardware already powered ; ; On Stork. ; ; Now would be a good time to hit the power control latches ; to ensure everything is powered up. ; ADR R14, PowerTab 05 LDMIA R14!, {R0, R1} TEQ R0, #0 STRNEB R1, [R0] BNE %BT05 10 EXIT ] [ STB ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; ConfigureCombo - Configure SMC 665/669 or UMC 8669 if present ; ComboBase * &03010000 ; Base address of combo chip = PC/AT I/O 000H ; SMC-type stuff SMC_CSR * &03F0 * 4 ; Configuration Select Register (CSR) SMC_CSRalt669 * &0370 * 4 ; Alternative Configuration Select Register on SMC 669 ; (this register is used if RTS2 is high on reset, which we don't have direct control of) SMC_config * &55 ; value to write to enter configuration mode SMC_endconfig * &AA ; value to write to end configuration mode SMC_IDreg * &0D ; device ID register SMC_data * &03F1 * 4 ; Configuration Access Port (data) SMC_665 * &65 ; 665 ID SMC_669 * &03 ; 669 ID ; UMC-type stuff UMC_CSR * &0108 * 4 ; Configuration Select Register (CSR) UMC_config * &AA ; value to write to enter configuration mode UMC_endconfig * &55 ; value to write to end configuration mode UMC_data * &0109 * 4 ; Configuration Access Port (data) ; ; Configure SMC 37C665/669 or UMC8669 combo chip ; Note that older devices (eg 82C710, 82C711, SMC651) are no longer supported ASSERT :LNOT: OldComboSupport ConfigureCombo ENTRY "r0-r2" TEQP pc, #SVC_mode + I_bit + F_bit ; Disable FIQ and IRQ LDR r0, =ComboBase ; R0-> Base address of combo chip ; See if we have a SMC665/669 and try to configure it ADD r2, r0, #SMC_CSR ; first try in normal place MOV lr, #SMC_config STRB lr, [r2] ; Write &55 to CSR twice STRB lr, [r2] ; to enter configuration mode MOV lr, #SMC_IDreg STRB lr, [r2] LDRB lr, [r2, #SMC_data-SMC_CSR] TEQ lr, #SMC_665 ; 665 ? ADREQ r1, ConfigSMC665Table BEQ %FT20 TEQ lr, #SMC_669 ; 669 ? BEQ %FT18 ; Not a SMC chip at the normal place, but the SMC 669 may move its configuration registers ; to &370 if RTS2 was high on trailing edge of reset, so try there ADD r2, r0, #SMC_CSRalt669 MOV lr, #SMC_config STRB lr, [r2] ; Write &55 to CSR twice STRB lr, [r2] ; to enter configuration mode MOV lr, #SMC_IDreg STRB lr, [r2] LDRB lr, [r2, #SMC_data-SMC_CSR] TEQ lr, #SMC_669 ; 669 ? BEQ %FT18 ; Not a SMC chip that we recognise, maybe we have a UMC8669 ADR r1, ConfigUMC8669Table 10 LDRB lr, [r1], #1 ; get "Index Entry Valid" STRB lr, [r0, #UMC_CSR] TEQ lr, #UMC_endconfig ; end of table? BEQ %FT12 LDRB lr, [r1], #1 ; get config index STRB lr, [r0, #UMC_CSR] LDRB lr, [r1], #1 ; get config data STRB lr, [r0, #UMC_data] ; and write it BNE %BT10 12 ; UMC8669 is not self-identifying, so see if what we wrote is still there MOV lr, #UMC_config STRB lr, [r0, #UMC_CSR] ; Write &AA to enter config mode MOV lr, #&C0 STRB lr, [r0, #UMC_CSR] ; CR0 LDRB r2, [r0, #UMC_data] MOV lr, #UMC_endconfig ; maybe don't need to do this STRB lr, [r0, #UMC_CSR] ; exit config mode TEQ r2, #2_00111110 ; Value for CR0 from ConfigUMC8669Table ;�665s and 669s offer the same features as far as MOVEQ r1, #IOST_37C665 ; OS_ReadSysInfo(3) is concerned, so use same value for both MOVNE r1, #0 ; Don't know what this is, give up B %FT30 ; SMC config loop 18 ADR r1, ConfigSMC669Table 20 LDRB lr, [r1], #1 ; get config index STRB lr, [r2] TEQ lr, #SMC_endconfig ; end of table? LDRNEB lr, [r1], #1 ; if not then get config data STRNEB lr, [r2, #SMC_data-SMC_CSR] ; and write it BNE %BT20 ;�665s and 669s offer the same features as far as MOV r1, #IOST_37C665 ; OS_ReadSysInfo(3) is concerned, so use same value for both ; Record type of chip found 30 MOV r0, #0 LDRB lr, [r0, #IOSystemType] BIC lr, lr, #IOST_82C710 :OR: IOST_82C711 :OR: IOST_37C665 ORR lr, lr, r1 STRB lr, [r0, #IOSystemType] TEQP pc, #SVC_mode + I_bit ; Restore IRQ/FIQ state EXIT ConfigSMC665Table [ ComboIRQsActiveHigh DCB &01, 2_10010111 ; Enable config, COM3@338, COM4@238, IRQs active hi, ; // is extended & powered @278 | DCB &01, 2_10000111 ; Enable config, COM3@338, COM4@238, IRQs active low, ; // is extended & powered @278 ] DCB &02, 2_11011100 ; COM2 powered & enabled @2F8, COM1 powered & enabled @3F8 ; (default) DCB &03, 2_01111000 ; floppy stuff (default) DCB &04, 2_00000011 ; EPP v1.9, MIDI disabled, normal //floppy, ; // uses ECP & EPP modes DCB &05, 0 ; 4 drive support, don't swap drives, normal density, ; FDC burst mode, IDE@1F0-7,3F6-7, FDC@3F0-7 (default) ; DCB &06, &FF ; floppy drive types (default) ; DCB &07, 0 ; don't auto-powerdown anything (default) ; DCB &08, 0 ; ADRA7:4 address decode (default) ; DCB &09, 0 ; ADRA10:8 address decode (default) ; DCB &0A, 0 ; FIFO threshold for ECP // = ??? (default) ; DCB &0B, 0 ; floppy data rates (default) ; DCB &0C, 0 ; UART2 & UART1 standard speed, UART2 standard mode, ; UART2 full duplex, XMIT active hi, RCV active hi (default) DCB &00, 2_10111011 ; Valid config, OSC & BR on, FDC enabled & powered, ; IDE AT & enabled DCB SMC_endconfig, 0 ; Exit config mode ConfigSMC669Table DCB &01, 2_10010100 ; Enable config, // is extended, // is powered DCB &02, 2_10001000 ; COM2 powered, COM1 powered (default) DCB &03, 2_01110000 ; floppy stuff (bit 3 now reserved) DCB &04, 2_00000011 ; IR rx&tx on COM2 rx & tx pins, EPP v1.9, MIDI disabled, ; normal //floppy, uses ECP & EPP modes DCB &05, 0 ; 4 drive support, don't swap drives, normal density, ; FDC burst mode (default) ; DCB &06, &FF ; floppy drive types (default) ; DCB &07, 0 ; don't auto-powerdown anything ; DCB &08, 0 ; ADRA7:4 address decode (default) ; DCB &09, 0 ; ADRx disabled, ADRA10:8 address decode (default) ; DCB &0A, 0 ; FIFO threshold for ECP // = ??? (default) ; DCB &0B, 0 ; floppy data rates (default) ; DCB &0C, 0 ; UART2 & UART1 standard speed, UART2 standard mode, ; UART2 full duplex, XMIT active hi, RCV active hi (default) DCB &10, 2_01000000 ; 24MHz input to PLL (*not* default) ; DCB &1E, &80 ; GAMECS disabled (default) ; DCB &1F, 0 ; floppy drive types (default) DCB &20, &FC ; FDC@3F0-7 DCB &21, &7C ; IDE@1F0-7 DCB &22, &FD ; IDE Alternate Status Register @3F6 DCB &23, &9E ; //@278 DCB &24, &FE ; COM1@3F8 DCB &25, &BE ; COM2@2F8 DCB &26, 0 ; no FDC DMA, no // DMA (default) DCB &27, 2_01100101 ; FDC uses IRQ_F, // uses IRQ_E DCB &28, 2_01000011 ; UART1 uses IRQ_D, UART2 uses IRQ_C DCB &29, 0 ; IRQIN does not use any IRQ_x (default) DCB &00, 2_10001010 ; Valid config, FDC powered, IDE enabled DCB SMC_endconfig, 0 ; Exit config mode ConfigUMC8669Table DCB UMC_config, &C0, 2_00111110 ; IR full-duplex, games off, IDE on, ; // in EPP & ECP mode, UART2 on, UART1 on, FDC off DCB UMC_config, &C1, 2_00101111 ; Direct access PnP register, Disable PnP, ; IDE@1F0-7,3F6-7, //@278, COM2@2F8, COM1@3F8, ; FDC@3F0-7 DCB UMC_config, &C2, 2_10000001 ; Not supspended, IR unselected/disabled, ; don't swap floppy, IBM mode floppy, ; floppy is R/W (default) DCB UMC_endconfig, 0 ; Exit config mode ALIGN | ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Configure82C710 - Configure 82C710/82C711/SMC 665 if present ; ; 82C710 stuff CnTbase * &03010000 ; Base address of 82C710 = PC/AT I/O 000H CRI710 * &0390 CRI710Off * CRI710*4 ; 82C710 Configuration Register Index port CAP710Off * CRI710Off +4 ; 82C710 Configuration Access Port (data) ConRegA710 * &02FA*4 ConRegB710 * &03FA*4 CRI711Off * &03F0*4 ; 82C711 Configuration Register Index port CAP711Off * CRI711Off +4 ; 82C711 Configuration Access Port (data) [ IO_Type <> "IOMD" Configure82C710 ENTRY "r0,r1" MOV r0, #0 LDRB lr, [r0, #IOSystemType] TST lr, #IOST_IOEB ; no IOEB, then don't bother EXIT EQ TEQP pc, #SVC_mode + I_bit + F_bit ; Disable FIQ and IRQ LDR r0, =CnTbase ; R0-> 82C710 base address ; First try to configure 82C711 or SMC665 MOV lr, #&55 STRB lr, [r0, #CRI711Off] ; Write &55 to CRI711 twice STRB lr, [r0, #CRI711Off] ; to enter configuration mode MOV lr, #&0D ; Check for SMC 665 STRB lr, [r0, #CRI711Off] LDRB lr, [r0, #CAP711Off] TEQ lr, #&65 ADREQ r1, ConfigSMCTable ; different table for SMC 665 ADRNE r1, Config711Table ; R1-> 82C711 configuration data Push "lr" ; need to test for 665 again 20 LDRB lr, [r1], #1 ; get config index STRB lr, [r0, #CRI711Off] TEQ lr, #&AA ; end of table? LDRNEB lr, [r1], #1 ; if not then get config data STRNEB lr, [r0, #CAP711Off] ; and write it BNE %BT20 Pull "lr" TEQ lr, #&65 ; if we configured SMC 665 then MOVEQ r1, #IOST_37C665 ; set flag in IOSystemType BEQ %FT30 ; and no need to faff about for 710/711 ; Now try to configure 82C710 (won't work on 711) MOV lr, #&55 ; Magic number from 82C710 data sheet STRB lr, [r0, #ConRegA710] ; Start configuration mode MVN lr, lr ; Complement the magic number STRB lr, [r0, #ConRegB710] MOV lr, #&36 ; Another magic number from C&T STRB lr, [r0, #ConRegB710] MOV r1, #CRI710 /4 ; 82C710 configuration address /4 STRB r1, [r0, #ConRegB710] ; Write configuration address MVN lr, r1 ; Complement the data STRB lr, [r0, #ConRegA710] ; Complete configuration sequence ADR r1, Config710Table ; R1-> 82C710 configuration data 10 LDRB lr, [r1], #1 ; Get next 82C710 config reg index, R1++ STRB lr, [r0, #CRI710Off] ; Write index TEQ lr, #&0F ; Configuration register selected? LDRB lr, [r1], #1 ; Get config data, R1++ STRB lr, [r0, #CAP710Off] ; Write config data BNE %BT10 ; Repeat until config register written ; now if we're on 82C710 then 1st serial port is at &3F8 ; and if we're on 82C711 then 1st serial port is at &2F8 STRB lr, [r0, #&2FF * 4] ; store &AA in serial scratchpad register for 82C711 port 1 MOV lr, #&55 STRB lr, [r0, #&3FF * 4] ; store &55 in serial scratchpad register for 82C710 STRB lr, [r0, #CRI711Off] ; Write &55 to CRI711 twice STRB lr, [r0, #CRI711Off] ; to reenter configuration mode MOV lr, #&02 ; select config register 2 STRB lr, [r0, #CRI711Off] MOV lr, #2_00011100 ; move 1st serial port to &3F8 STRB lr, [r0, #CAP711Off] MOV lr, #&AA STRB lr, [r0, #CRI711Off] ; exit config mode MOV r1, #0 ; by default no 82C710 or 82C711 LDRB lr, [r0, #&3FF * 4] ; read scratchpad register TEQ lr, #&55 ; &55 => 82C710 MOVEQ r1, #IOST_82C710 TEQ lr, #&AA MOVEQ r1, #IOST_82C711 30 MOV r0, #0 LDRB lr, [r0, #IOSystemType] BIC lr, lr, #IOST_82C710 :OR: IOST_82C711 :OR: IOST_37C665 ORR lr, lr, r1 STRB lr, [r0, #IOSystemType] TEQP pc, #SVC_mode + I_bit ; Restore IRQ/FIQ state EXIT ] [ IO_Type <> "IOMD" Config710Table ; Index, Data ; 82C710 configuration data DCB &01, 2_01000000 ; Bi-dir parallel DCB &02, 2_00001000 ; Default, UART clock DCB &04, &FE ; Default, UART base address= &3F8 (COM1) DCB &06, &9E ; Default, Parallel base address= &278 (LPT3) DCB &09, &9E ; GPCS=&278 (so writes to printer control go to PAL too) DCB &0A, 2_00001010 ; GPCS A1=1 (to detect printer control), GPCS enabled DCB &0B, 2_01110000 ; IRQs active lo, GPCS is an o/p DCB &0C, 2_10100001 ; IDE/FDC enabled, mouse disabled DCB &0D, 0 ; Default, mouse address DCB &0E, 2_00000000 ; Default, test modes disabled DCB &00, 2_10101100 ; Valid config, OSC/BR on, Ser/Par enable DCB &0F, 0 ; Write config register == end of list Config711Table DCB &01, 2_10000111 ; Enable config read, IRQ active low, parallel powered/extended, default addr. DCB &02, 2_00001101 ; 2nd serial port disabled, 1st enabled at &2F8 (to be moved to &3F8 later) DCB &03, 0 ; Test mode disabled DCB &00, 2_10111011 ; Valid config, OSC/BR on, FDC enabled/powered, IDE AT,enabled DCB &AA, 0 ; Exit config mode ] ConfigSMCTable DCB &01, 2_10000111 ; Enable config read, IRQ active low, parallel powered/extended, default addr. DCB &02, 2_00011100 ; 2nd serial port disabled, 1st enabled at &3F8 DCB &03, &78 ; extra stuff for SMC DCB &04, 2_00000011 ; allow extended parallel port modes DCB &05, 0 DCB &06, &FF DCB &07, 0 DCB &08, 0 DCB &09, 0 DCB &0A, 0 DCB &00, 2_10111011 ; Valid config, OSC/BR on, FDC enabled/powered, IDE AT,enabled DCB &AA, 0 ; Exit config mode ALIGN [ IO_Type = "IOMD" ; ; Simplified version of Configure82C710 programs SMC 37C665 only. ; Configure37C665 ENTRY "r0,r1" TEQP pc, #SVC_mode + I_bit + F_bit ; Disable FIQ and IRQ LDR r0, =CnTbase ; R0-> SMC 665 base address ; First try to configure the SMC665 MOV lr, #&55 STRB lr, [r0, #CRI711Off] ; Write &55 to CRI711 twice STRB lr, [r0, #CRI711Off] ; to enter configuration mode MOV lr, #&0D ; Check for SMC 665 STRB lr, [r0, #CRI711Off] LDRB lr, [r0, #CAP711Off] TEQ lr, #&65 MOVNE r1, #0 ;NE: not a SMC 665 this should never happen BNE %FT30 ;NE: on a RiscPC, Kryten or Stork ADR r1, ConfigSMCTable ; R1-> SMC 665 configuration data 20 LDRB lr, [r1], #1 ; get config index STRB lr, [r0, #CRI711Off] TEQ lr, #&AA ; end of table? LDRNEB lr, [r1], #1 ; if not then get config data STRNEB lr, [r0, #CAP711Off] ; and write it BNE %BT20 MOV r1, #IOST_37C665 30 MOV r0, #0 LDRB lr, [r0, #IOSystemType] BIC lr, lr, #IOST_82C710 :OR: IOST_82C711 :OR: IOST_37C665 ORR lr, lr, r1 STRB lr, [r0, #IOSystemType] TEQP pc, #SVC_mode + I_bit ; Restore IRQ/FIQ state EXIT ] ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; ReadUniqueID - Read unique machine ID ; ; 10-Dec-93 BCockburn Modified to leave raw 64 bit ID from chip in RawMachineID defaultlatch * 20000-1 ; TMD 21-May-93: "-1" correction applied Tsyc * 5 ; time between frames - minimum of 1�s, so give it a bit more Trstl * 500 ; time reset pulse held low - minimum of 480�s, so give it a bit more Trsth * 500 ; time reset pulse held high - minimum of 480�s, so give it a bit more Tlow0 * 80 ; time for write0 low - min 60�s, max 120�s Tlow1 * 5 ; time for write1 low - min 1�s, max 15�s Tslot * 90 ; time for total read/write slot - min 60�s, max 120�s Trdlow * 5 ; time for read slot low before release - min 1�s, max 15�s Trddat * 3 ; time after read slot high before read it ASSERT Tslot-Tlow0 > Tsyc ASSERT Trdlow+Trddat < 15 ; Macro to set wire to a given state, and optionally count transitions (starting at low) while waiting for a given time MACRO SetWire $hilo, $time, $monstate, $count LCLS reg [ "$hilo"="LOW" reg SETS "r4" | ASSERT "$hilo"="HIGH" reg SETS "r5" ] [ ($time) = 0 STRB $reg, [r1, #IOCControl] ; set appropriate level on line | ASSERT ($time) < 32768 MOV r12, #(($time)*2):AND:&FF STRB r12, [r1, #Timer0LL] ; program low latch MOV r12, #(($time)*2):SHR:8 STRB r12, [r1, #Timer0LH] ; program high latch STRB $reg, [r1, #IOCControl] ; set appropriate level on line STRB r12, [r1, #Timer0GO] ; and start timer LDRB r12, [r1, #IOCIRQSTAA] ; dummy instruction to avoid bug in IOC LDRB r12, [r1, #IOCIRQSTAA] ; dummy instruction (repeated for FE) STRB r11, [r1, #IOCIRQCLRA] ; immediately clear IRQ bit [ "$monstate"<>"" MOV $monstate, #0 ] [ "$count"<>"" MOV $count, #0 ] 10 LDRB r12, [r1, #IOCIRQSTAA] TST r12, r11 [ "$count"<>"" ADDEQ $count, $count, #1 ] [ "$monstate"="" BEQ %BT10 ; not timed out, so just loop | BNE %FT30 ; timed out LDRB r12, [r1, #IOCControl] TST r12, #IOEB_unique_machine_ID_bit BEQ %BT10 ; if still low then loop to 10 ADD $monstate, $monstate, #1 ; increment number of transitions 20 LDRB r12, [r1, #IOCIRQSTAA] TST r12, r11 [ "$count"<>"" ADDEQ $count, $count, #1 ] BNE %FT30 ; timed out LDRB r12, [r1, #IOCControl] TST r12, #IOEB_unique_machine_ID_bit BNE %BT20 ; if still high then loop to 20 ADD $monstate, $monstate, #1 ; increment number of transitions B %BT10 30 ] ] MEND ReadUniqueID ENTRY "r0-r12" MOV r0, #0 LDR r1, =IOC TEQP pc, #SVC_mode + I_bit + F_bit LDRB r3, [r0, #IOCControlSoftCopy] BIC r4, r3, #IOEB_unique_machine_ID_bit ; r4 is value to pull ID line low ORR r5, r3, #IOEB_unique_machine_ID_bit ; r5 is value to pull ID line high MOV r11, #timer0_bit BL SendResetPulse BVS ResetFailed BL SendCommandWord MOV r7, #-8 ; -no. of bytes to store = 8 bits type + 48 bits ID + 8 bits checksum 10 BL GetAByte STRB r6, [r7, #RawMachineID+8] ADDS r7, r7, #1 BNE %BT10 BL RestoreIOCState BL CheckCRC BVS IDError EXIT ResetFailed BL RestoreIOCState IDError MOV r0, #0 STR r0, [r0, #RawMachineID+0] ; indicate no ID by putting zero here STR r0, [r0, #RawMachineID+4] EXIT RestoreIOCState ENTRY STRB r3, [r1, #IOCControl] ; put back old value MOV r12, #defaultlatch :AND: &FF STRB r12, [r1, #Timer0LL] ; and restore old timer 0 latch values MOV r12, #defaultlatch :SHR: 8 STRB r12, [r1, #Timer0LH] STRB r12, [r1, #Timer0GO] TEQP pc, #SVC_mode + I_bit ; restore old interrupt state EXIT SendResetPulse ROUT SetWire HIGH, Tsyc SetWire LOW, Trstl,,r6 SetWire HIGH, Trsth,r10 TEQ r6, #0 ; ADREQ r0, IOCBugHappenedError ORREQS pc, lr, #V_bit CMP r10, #3 ; H-L-H is ok BICEQS pc, lr, #V_bit ; ADRHI r0, TooManyTransitionsError ; H-L-H-L... ; CMP r10, #2 ; ADREQ r0, NeverWentHighAgainError ; H-L ; CMP r10, #1 ; ADREQ r0, NeverWentLowError ; H ; ADRCC r0, NeverWentHighError ; stayed low permanently even though we released it ORRS pc, lr, #V_bit [ {FALSE} ; only for debugging NeverWentHighError = "Never went high", 0 NeverWentLowError = "Never went low", 0 NeverWentHighAgainError = "Never went high again", 0 TooManyTransitionsError = "Too many transitions", 0 IOCBugHappenedError = "IOC bug happened", 0 ALIGN ] SendCommandWord ROUT LDR r6, =&10F ; &0F is command word 10 MOVS r6, r6, LSR #1 BICEQS pc, lr, #V_bit BCS SendOne SetWire LOW, Tlow0 SetWire HIGH, Tslot-Tlow0 B %BT10 SendOne SetWire LOW, Tlow1 SetWire HIGH, Tslot-Tlow1 B %BT10 GetAByte ROUT MOV r6, #&80 10 SetWire LOW, Trdlow SetWire HIGH, Trddat LDRB r10, [r1, #IOCControl] SetWire HIGH, Tslot-Trdlow-Trddat MOVS r10, r10, LSR #IOEB_ID_bit_number+1 ; move bit into carry MOVS r6, r6, RRX BCC %BT10 MOV r6, r6, LSR #24 BICS pc, lr, #V_bit CheckCRC ROUT LDR r1, =RawMachineID ; pointer to current byte MOV r2, #0 MOV r3, #7 ; number of bytes to do 10 LDRB r4, [r1], #1 EOR r2, r2, r4 MOV r4, #8 ; number of bits to do 20 MOVS r2, r2, LSR #1 ; shift bit out into carry EORCS r2, r2, #&8C ; feedback carry into other bits SUBS r4, r4, #1 ; one less bit to do BNE %BT20 ; loop until done whole byte SUBS r3, r3, #1 ; one less byte to do BNE %BT10 ; loop until done all 7 bytes LDRB r4, [r1], #1 ; read CRC TEQ r4, r2 ; if incorrect ORRNES pc, lr, #V_bit ; then exit indicating error BICS pc, lr, #V_bit LTORG END